【问题标题】:Sharepoint 2013 REST API call using C#Sharepoint 2013 REST API 调用使用 C#
【发布时间】:2013-11-04 11:52:34
【问题描述】:

这是 Stackoverflow 中my earlier question 之一的后续问题。

我正在尝试使用 HTTPClient 和 Sharepoint 2013 REST API 连接到 Sharepoint Online Premise 以获取“文档库”中的文档。

我在这里所做的只是使用 HttpClient 进行简单的匿名 HTTP GET 调用。

代码如下:

System.Net.Http.HttpClient _Client = new System.Net.Http.HttpClient();
_Client.BaseAddress = new Uri("https://test.sharepoint.com/_vti_bin/ListData.svc");
_Client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/atom+xml"));
_Client.DefaultRequestHeaders.Add("auth_user", "test@test.onmicrosoft.com");
_Client.DefaultRequestHeaders.Add("auth_pass", "test");
_Client.DefaultRequestHeaders.Add("Accept", "application/json;odata=verbose");
HttpResponseMessage resp = _Client.GetAsync(new Uri("https://test.sharepoint.com/_vti_bin/ListData.svc/Documents()")).Result;
string respString = resp.Content.ReadAsStringAsync().Result;

我收到以下错误:

无法从传输连接读取数据:连接已关闭。

堆栈跟踪如下:

[IOException: Unable to read data from the transport connection: The connection was closed.]
   System.Net.ConnectStream.EndRead(IAsyncResult asyncResult) +6501654
   System.Net.Http.WebExceptionWrapperStream.EndRead(IAsyncResult asyncResult) +30
   System.Net.Http.StreamToStreamCopy.BufferReadCallback(IAsyncResult ar) +54

[HttpRequestException: Error while copying content to a stream.]

[AggregateException: One or more errors occurred.]
   System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions) +3569193
   System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification) +73
   System.Threading.Tasks.Task`1.get_Result() +10522673
   WebApp.Test.Page_Load(Object sender, EventArgs e) in @Location
   System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e) +51
   System.Web.UI.Control.OnLoad(EventArgs e) +92
   System.Web.UI.Control.LoadRecursive() +54
   System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +772

我已经通过各种blogs/articles 来获得解决问题的一些想法。但我还没有找到任何解决方案。

对此有什么想法吗?

【问题讨论】:

  • 您是在 ASP.NET 网站中执行此操作吗?我怀疑您的 .Result 调用发生了一些奇怪的事情。你试过使用 async/await 吗?
  • 是的,我是从 ASP.NET 网站执行此操作的。

标签: .net rest sharepoint sharepoint-2013 dotnet-httpclient


【解决方案1】:

这将帮助你:

ServicePointManager.ServerCertificateValidationCallback = 
    delegate(object s, X509Certificate certificate, X509Chain chain, 
            SslPolicyErrors sslPolicyErrors) 
    { 
        return true; 
    };

放在request之前。

【讨论】:

    【解决方案2】:

    我在 Visual Studio 2013 中构建了一个快速的 .NET 4.5 控制台应用程序,并且能够通过一些小的更改使您的代码正常工作,并且能够成功地进行身份验证并调用 SharePoint Online 的 REST API。

    更改 #1:我添加了对两个 SharePoint 2013 客户端对象模型 (CSOM) DLL 的项目引用。您可以从此处安装 DLL:http://www.microsoft.com/en-us/download/details.aspx?id=35585。运行安装程序并将项目引用添加到 Microsoft.SharePoint.Client.dll 和 Microsoft.SharePoint.Client.Runtime.dll。您需要这些的原因是您可以使用 SharePointOnlineCredentials 类。

    更改 #2:我在您的两个异步调用中添加了“await”关键字,因为代码实际上并没有等待这些调用执行。

    更改 #3:我将 HttpClient 代码修改为 (1) 使用来自 SharePointOnlineCredentials 对象的凭据,(2) 获取并使用来自 SharePoint Online 的身份验证 cookie,以及 (3) 添加一个额外的需要的请求标头。

    这里是完整的代码sn-p:

    Uri uri = new Uri("https://mydomain.sharepoint.com");
    
    SharePointOnlineCredentials creds = new SharePointOnlineCredentials(
        "username@domain.com", StringUtilities.ToSecureString("YourPassword"));
    
    string authCookie = creds.GetAuthenticationCookie(uri);
    var cookies = new CookieContainer();
    cookies.Add(new Cookie("FedAuth", authCookie.TrimStart("SPOIDCRL=".ToCharArray()), "", uri.Authority));
    
    System.Net.Http.HttpClientHandler handler = new System.Net.Http.HttpClientHandler()
    {
        Credentials = creds,
        CookieContainer = cookies
    };
    
    System.Net.Http.HttpClient client = new System.Net.Http.HttpClient(handler);
    
    client.BaseAddress = new Uri(uri, "/_vti_bin/ListData.svc");
    client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/atom+xml"));
    client.DefaultRequestHeaders.Add("Accept", "application/json;odata=verbose");
    client.DefaultRequestHeaders.Add("X-FORMS_BASED_AUTH_ACCEPTED", "f");
    
    var response = await client.GetAsync(new Uri(uri, "/_vti_bin/ListData.svc/Documents()"));
    string text = await response.Content.ReadAsStringAsync();
    

    我运行此程序并在最后打印出“文本”变量,并从 SharePoint Online 获得了有效响应。

    【讨论】:

      【解决方案3】:

      SharePoint Online支持您尝试传递凭据的方式。

      Microsoft 发布了包含SharePointOnlineCredentials classSharePointOnline Client Components SDK,该SharePointOnlineCredentials class 提供了访问SharePoint Online 资源的凭据。

      以下示例演示了如何利用 SharePointOnlineCredentials classHttpClient class 来访问 SharePoint Online

      public class SPHttpClientHandler : HttpClientHandler
      {
          public SPHttpClientHandler(Uri webUri, string userName, string password)
          {
              CookieContainer = GetAuthCookies(webUri, userName, password);
              FormatType = FormatType.Json;
          }
      
      
          protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
          {
              request.Headers.Add("X-FORMS_BASED_AUTH_ACCEPTED", "f");
              if(FormatType == FormatType.Json)
                  request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
              return base.SendAsync(request, cancellationToken);
          }
      
      
          /// <summary>
          /// Retrieve SPO Auth Cookies 
          /// </summary>
          /// <param name="webUri"></param>
          /// <param name="userName"></param>
          /// <param name="password"></param>
          /// <returns></returns>
          private static CookieContainer GetAuthCookies(Uri webUri, string userName, string password)
          {
              var securePassword = new SecureString();
              foreach (var c in password) { securePassword.AppendChar(c); }
              var credentials = new SharePointOnlineCredentials(userName, securePassword);
              var authCookie = credentials.GetAuthenticationCookie(webUri);
              var cookieContainer = new CookieContainer();
              cookieContainer.SetCookies(webUri, authCookie);
              return cookieContainer;
          }
      
      
          public FormatType FormatType { get; set; }
      }
      
      public enum FormatType
      {
          Json,
          Xml
      }
      

      Gist: SPHttpClientHandler.cs

      先决条件:SharePointOnlineCredentials class from SharePoint Online Client Components SDK 用于身份验证。

      用法

       var handler = new SPHttpClientHandler(webUri, userName, password);
       using (var client = new HttpClient(handler))
       {
            client.BaseAddress = webUri;
            var result = client.GetAsync("/_vti_bin/ListData.svc/Documents").Result;
            var content = result.Content.ReadAsStringAsync().Result;
       }
      

      【讨论】:

        猜你喜欢
        • 2018-09-15
        • 2015-11-30
        • 2013-06-06
        • 1970-01-01
        • 2014-08-17
        • 1970-01-01
        • 2017-02-27
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多