Я пытаюсь прочитать значение из списка на удаленном сайте SharePoint (другое SP Web App). Веб-приложения настраиваются с помощью проверки подлинности на основе утверждений, а управляемая учетная запись SP клиентского веб-приложения настраивается с использованием имени участника-службы. Я полагаю, что Kerberos и утверждения настроены правильно, но я не могу связаться с удаленным сервером, и запрос вызывает исключение: «Удаленный сервер возвратил ошибку: (401) Несанкционированный».
Исключение возникает в строке ctx.ExecuteQuery();
, но оно не перехватывает исключение в if (scope.HasException)
; исключение перехватывается вызывающим кодом (вне блока using {}).
Когда я смотрю на трафик на удаленном сервере, используя Wireshark, это не похоже на то, что запрос даже попадает на сервер; это похоже на то, как если бы 401 произошел до того, как билет Kerberos был обменен на претензию.
Вот мой код:
using (ClientContext ctx = new ClientContext(contextUrl))
{
CredentialCache cc = new CredentialCache();
cc.Add(new Uri(contextUrl), "Kerberos", CredentialCache.DefaultNetworkCredentials);
ctx.Credentials = cc;
ctx.AuthenticationMode = ClientAuthenticationMode.Default;
ExceptionHandlingScope scope = new ExceptionHandlingScope(ctx);
Web ctxWeb = ctx.Web;
List ctxList;
Microsoft.SharePoint.Client.ListItemCollection listItems;
using (scope.StartScope())
{
using (scope.StartTry())
{
ctxList = ctxWeb.Lists.GetByTitle("Reusable Content");
CamlQuery qry = new CamlQuery();
qry.ViewXml = string.Format(ViewQueryByField, "Title", "Text", SharedContentTitle);
listItems = ctxList.GetItems(qry);
ctx.Load(listItems, items => items.Include(
item => item["Title"],
item => item["ReusableHtml"],
item => item["ReusableText"]));
}
using (scope.StartCatch()) { }
using (scope.StartFinally()) { }
}
ctx.ExecuteQuery();
if (scope.HasException)
{
result = string.Format("Error retrieving content<!-- Error Message: {0} | {1} -->", scope.ErrorMessage, contextUrl);
}
if (listItems.Count == 1)
{
Microsoft.SharePoint.Client.ListItem contentItem = listItems[0];
if (SelectedType == SharedContentType.Html)
{
result = contentItem["ReusableHtml"].ToString();
}
else if (SelectedType == SharedContentType.Text)
{
result = contentItem["ReusableText"].ToString();
}
}
}
Я понимаю, что часть с CredentialCache не должна быть необходимой в утверждениях, но каждый отдельный пример, который я могу найти, выполняется либо в консольном приложении, либо в каком-либо клиентском приложении; этот код выполняется в коде позади обычного ASP.NET UserControl.
Редактировать: Вероятно, стоит упомянуть, что приведенный выше код даже не работает, когда удаленный URL-адрес является корневым семейством сайтов в том же веб-приложении, что и вызывающий код (который находится в семействе сайтов в / sites /) - другими словами, даже если имя хоста совпадает с кодом вызова.
Любые предложения о том, что попробовать дальше, с благодарностью!
Mike