使用C#调用Sharepoint 2013的REST API

3
这是我在Stackoverflow上之前问题的跟进问题
我正在尝试使用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

我已经阅读了各种博客/文章,以获取解决问题的思路。但我仍未找到任何解决方案。
对此有什么想法吗?

你是在 ASP.NET 网站内部进行这个操作吗?我怀疑你的 .Result 调用出了一些问题。你尝试过使用 async/await 吗? - Darrel Miller
是的,我正在从一个ASP.NET网站进行这个操作。 - Bisileesh
3个回答

1

我在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)添加所需的一个额外请求标头。

下面是完整的代码片段:

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();

我运行了这个程序,最后打印出了“text”变量,并从SharePoint Online得到了有效的响应。

1
这会对你有所帮助:

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

将其放在request之前。

0

您尝试传递凭据的方式在SharePoint Online中是不受支持的。

微软发布了包含SharePointOnlineCredentials类SharePointOnline客户端组件SDK,该类提供了访问SharePoint Online资源所需的凭据。

以下示例演示了如何利用SharePointOnlineCredentials类HttpClient类来访问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

前提条件:使用SharePoint Online Client Components SDK中的SharePointOnlineCredentials类进行身份验证。

用法

 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;
 }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接