#c# #sharepoint #httpclient #ntlm #csom
#c# #sharepoint #httpclient #ntlm #csom
Вопрос:
Я пытаюсь получить доступ к файлу Excel, расположенному на сайте в Sharepoint. У меня нет возможности вносить изменения со стороны сервера. Я могу получить доступ к файлу из Chrome, когда я ввожу ссылку, файл автоматически загружается. Но когда я попытался загрузить с помощью кода C # (.Net framework 4.6.1), я получил несанкционированное исключение, код ошибки 401. Я попробовал несколько вещей. Сначала я попробовал CSOM (объектная модель Sharepoint на стороне клиента). Код выглядит следующим образом
static void Main(string[] args)
{
var link2 = @"File link";
ClientContext context = new ClientContext(link2);
Web web = context.Web;
context.ExecutingWebRequest = clientContext_ExecutingWebRequest;
context.Credentials = CredentialCache.DefaultCredentials;
context.Load(web);
ExceptionHandlingScope scope = new ExceptionHandlingScope(context);
using (scope.StartScope())
{
using (scope.StartTry())
{
context.ExecuteQuery();// <- Unautherized exception
Console.WriteLine(web.Title);
}
using (scope.StartCatch())
{
Console.WriteLine(scope.ServerStackTrace);
}
}
Console.ReadLine();
}
static void clientContext_ExecutingWebRequest(object sender, WebRequestEventArgs e)
{
e.WebRequestExecutor.WebRequest.Headers.Add("X-FORMS_BASED_AUTH_ACCEPTED", "f");
}
После этого я вернулся к традиционному методу и использовал HttpClient. Код следует
static void Main(string[] args)
{
var link = @"sitelink";
var link2 = @"filelink";
var credential = new CredentialCache
{
{ new Uri(link2),"NTLM", CredentialCache.DefaultNetworkCredentials}
};
var options = new HttpClientHandler
{
Credentials = credential
};
//var client = new HttpClient(options);
using (var client = new HttpClient(options))
{
var requestMessage = new HttpRequestMessage();
requestMessage.Headers.Add("X-FORMS_BASED_AUTH_ACCEPTED", "f");
requestMessage.Method = HttpMethod.Get;
requestMessage.RequestUri = new Uri(link2);
requestMessage.Headers.Add("Use-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.135 Safari/537.36");
var response = client.SendAsync(requestMessage).Resu<
Console.WriteLine(JsonConvert.SerializeObject(response,Formatting.Indented));
if (response != null amp;amp; response.IsSuccessStatusCode)// <- Status false, Unautherized is in the response header
{
using (var reader = new io.StreamReader(response.Content.ReadAsStreamAsync().Result))
{
io.File.WriteAllText(@"C:UsersNamesourcereposTestExcel.xlsx", reader.ReadToEndAsync().Result );
}
}
}
Console.WriteLine("DOne");
}
Я новичок в sharepoint и ценю любую помощь. Заранее спасибо.
\\\\\\\\\\\\\\\\\\\
Еще одна попытка
var link2 = @"file link";
var client = new HttpClient(new HttpClientHandler
{
UseDefaultCredentials = true
});
io.Stream resultStream = null;
try
{
resultStream = client.GetStreamAsync(link2).Resu<
var reader = new io.StreamReader(resultStream);
io.File.WriteAllText(@"C:UsersNamesourcereposTestExcel.xlsx", reader.ReadToEndAsync().Result);
reader.Close();
} catch (Exception e)
{
Console.WriteLine(JsonConvert.SerializeObject(e,Formatting.Indented));
}
Console.WriteLine("Done");
Console.ReadLine();
Завершите сериализованный объект исключения
{
"ClassName": "System.AggregateException",
"Message": "One or more errors occurred.",
"Data": null,
"InnerException": {
"ClassName": "System.Net.Http.HttpRequestException",
"Message": "Response status code does not indicate success: 401 (Unauthorized).",
"Data": null,
"InnerException": null,
"HelpURL": null,
"StackTraceString": null,
"RemoteStackTraceString": null,
"RemoteStackIndex": 0,
"ExceptionMethod": null,
"HResult": -2146233088,
"Source": null,
"WatsonBuckets": null,
"SafeSerializationManager": {
"m_serializedStates": [
{}
]
},
"CLR_SafeSerializationManager_RealType": "System.Net.Http.HttpRequestException, System.Net.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken="
},
"HelpURL": null,
"StackTraceString": " at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)rn at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)rn at System.Threading.Tasks.Task`1.get_Result()rn at SharePointTrail.Program.Main(String[] args) in C:\Users\name\source\repos\SharePointTrail\SharePointTrail\Program.cs:line 27",
"RemoteStackTraceString": null,
"RemoteStackIndex": 0,
"ExceptionMethod": "8nThrowIfExceptionalnmscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=nSystem.Threading.Tasks.TasknVoid ThrowIfExceptional(Boolean)",
"HResult": -2146233088,
"Source": "mscorlib",
"WatsonBuckets": null,
"InnerExceptions": [
{
"ClassName": "System.Net.Http.HttpRequestException",
"Message": "Response status code does not indicate success: 401 (Unauthorized).",
"Data": null,
"InnerException": null,
"HelpURL": null,
"StackTraceString": null,
"RemoteStackTraceString": null,
"RemoteStackIndex": 0,
"ExceptionMethod": null,
"HResult": -2146233088,
"Source": null,
"WatsonBuckets": null,
"SafeSerializationManager": {
"m_serializedStates": [
{}
]
},
"CLR_SafeSerializationManager_RealType": "System.Net.Http.HttpRequestException, System.Net.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken="
}
]
}
Обновить
Sharepoint размещен в office 365.
Кажется, Office 365 заботится об авторизации. Когда я проверяю в Chrome dev tool, в исходном файле я нахожу пару файлов js (имена, которые я не могу здесь упомянуть).
Комментарии:
1. Это может быть связано с тем, что в Chrome вы уже вошли в систему. Вот почему вы не получаете 401 в Chrome, но при использовании C # вы еще не авторизованы. Для этого вам необходимо иметь токен доступа к вашему Sharepoint и прикрепить его в качестве заголовка к вашему запросу.
2. Спасибо @robalem. Но я совершенно новичок в sharepoint. Поэтому, пожалуйста, помогите мне понять, как я получу токен доступа? должен ли я выполнить обмен Oauth2? Как сохранить этот токен на протяжении всего срока службы приложения?
3. @AdityaNadig опубликованные вами фрагменты кода содержат много строк, которые выглядят как случайные попытки заставить что-то работать. Документы в SharePoint доступны по их URL. Вам не нужно более 3-4 строк, чтобы создать HttpClient с авторизацией Windows, выполнить
HttpClient.GetStreamAsync
и записать файл на диск. Весь добавленный вами код и заголовки могут только вызывать проблемы4. Не объясняя все это самостоятельно, взгляните на это руководство , в котором описывается, как получить токен доступа из Sharepoint Online. После получения токена вы можете добавить его к своему запросу.
5. Что касается кода CSOM, он не имеет особого смысла и снова выглядит как случайный код. ClientContext используется для подключения к сайту, а не для загрузки документа. Заголовки, области видимости и т.д. Не имеют смысла, и опять же, дополнительные заголовки будут вызывать только проблемы. Вы проверили документацию CSOM и примеры?