使用身份验证令牌休息后呼叫

Mar*_*ark 2 c# rest httpwebrequest sharepoint-2013

我正在尝试从我的客户端应用程序(WPF应用程序)向SharePoint Online(基于声明的Auth站点)发送Post请求.在这种情况下,它应该是对ListItem的更新,以将'Title'更改为'Test'.

我正在通过MsOnlineClaimsHelper类检索CookieContainer, 它成功地返回了一个身份验证令牌.

但是,当我尝试发送请求时,响应是 The remote server returned an error: (403) Forbidden.

WebRequest代码

try
{
    var claimshelper = new MsOnlineClaimsHelper(baseUrl, _userName, _password);
    var request = (HttpWebRequest)WebRequest.Create(baseUrl + "/" + url);

    request.CookieContainer = claimshelper.CookieContainer;
    request.Method = "POST";
    request.Headers.Add("X-HTTP-Method", "MERGE");
    request.Headers.Add("If-Match", "*");
    request.Accept = "application/json;odata=verbose";

    using (var streamWriter = new StreamWriter(request.GetRequestStream()))
    {
        streamWriter.Write(json);
        streamWriter.Flush();
    }

    var webResp = request.GetResponse() as HttpWebResponse;
    var theData = new StreamReader(webResp.GetResponseStream(), true);
    string payload = theData.ReadToEnd();
}
catch (Exception ex)
{


}
Run Code Online (Sandbox Code Playgroud)

休息网址:

/_api/lists/getbytitle('SampleList')/items(1)

Json Payload:

string json = "{ '__metadata': { 'type': 'SP.Data.SampleListListItem' }, 'Title': 'Test'}";
Run Code Online (Sandbox Code Playgroud)

错误:

The remote server returned an error: (403) Forbidden.

Vad*_*hev 7

自的SharePoint 2013 REST服务发生此错误需要用户为包括Request Digest与每个值create,updatedelete操作.然后,SharePoint使用此值来标识非正版请求.

如何提供"请求摘要"值

MsOnlineClaimsHelper class(MsOnlineClaimsHelper.cs文件)中添加以下方法以请求Form Digest值:

/// <summary>
/// Request Form Digest value
/// </summary>
/// <returns></returns>
private string GetFormDigest()
{
    var endpoint = "/_api/contextinfo";
    var request = (HttpWebRequest) WebRequest.Create(_host.AbsoluteUri + endpoint);

    request.CookieContainer = new CookieContainer();
    request.Method = "POST";
    //request.Accept = "application/json;odata=verbose";
    request.ContentLength = 0;

    using (var response = (HttpWebResponse)request.GetResponse())
    {
         using (var reader = new StreamReader(response.GetResponseStream()))
         {
             var result = reader.ReadToEnd();

             // parse the ContextInfo response
             var resultXml = XDocument.Parse(result);

             // get the form digest value
             var e = from e in resultXml.Descendants()
                                 where e.Name == XName.Get("FormDigestValue", "http://schemas.microsoft.com/ado/2007/08/dataservices")
                            select e;
             _formDigest = e.First().Value;   
         }
    }
    return _formDigest;
}
Run Code Online (Sandbox Code Playgroud)

FormDigest财产:

private string _formDigest;
public string FormDigest
{
    get
    {
       if (_formDigest == null || DateTime.Now > _expires)
       {
           return GetFormDigest();
       }
       return _formDigest;
    }
}
Run Code Online (Sandbox Code Playgroud)

如何使用SharePoint 2013 REST API对ListItem执行更新操作

以下示例演示如何使用提供的实现来请求表单摘要来执行列表项的更新

关键点:

  • X-RequestDigest header用于指定Form Digest值
  • Content Type必须指定请求

例:

var userName = "username@contoso.onmicrosoft.com";
var password = "password";
var payload = "{ '__metadata': { 'type': 'SP.Data.TasksListItem' }, 'Title': 'New Tasl'}";  //for a Task Item


try
{
    var claimshelper = new MsOnlineClaimsHelper(baseUrl, _userName, _password);
    var request = (HttpWebRequest)WebRequest.Create(baseUrl + "/" + endpointUrl);

    request.CookieContainer = claimshelper.CookieContainer;
    request.Headers.Add("X-RequestDigest", claimshelper.FormDigest);
    request.Method = "POST";
    request.Headers.Add("X-HTTP-Method", "MERGE");
    request.Headers.Add("If-Match", "*");
    request.Accept = "application/json;odata=verbose";
    request.ContentType = "application/json;odata=verbose";

    using (var writer = new StreamWriter(request.GetRequestStream()))
    {
        writer.Write(payload);
        writer.Flush();
    }

    var response = request.GetResponse() as HttpWebResponse;
    //...
 }
 catch (Exception ex)
 {
    //Error handling goes here.. 
 }
Run Code Online (Sandbox Code Playgroud)