In my SharePointREST Service I can make a call to add a folder to a library as follows:
public async Task<string> AddFolderAsync(string library, string folderName){ var _serverRelativeUrl = string.Join("/", new string[] { library, folderName }); var _type = "SP.Folder"; var kvPropertyValues = new List<KeyValuePair<string, string>> { new KeyValuePair<string, string>(ServerRelativeUrl, _serverRelativeUrl) }; string json = GetJsonMetadataStringByType(_type, kvPropertyValues); // this returns: '{'__metadata': {'type': 'SP.Folder'},'ServerRelativeUrl':'TEST/<folderName>'}' const string urlTemplate = "{0}/_api/web/folders"; var restUrl = string.Format(urlTemplate, webUrl); var endpoint = _authenticationManager.GetWebRequest(restUrl, HttpMethod.Post, null, false); using Stream requestStream = endpoint.GetRequestStream(); using StreamWriter writer = new(requestStream); { writer.Write(json); writer.Flush(); } HttpWebResponse httpResponse = await GetResponse(endpoint); // Further stuff to be done here...}
FYI, the json
value looks like this when inserted:
{'__metadata': {'type': 'SP.Folder'},'ServerRelativeUrl':'TEST/<folderName>'}
This is in alignment with the instructions found here:Learn Microsoft - SharePoint REST API
This works brilliant, the GetWebRequest
call populates the headers and returns the request, this works all good. The webrequest method looks like this:
public HttpWebRequest GetWebRequest(string url, HttpMethod method, string xHttpMethod, bool noMetaData){ try { var accessToken = EnsureAccessTokenAsync(siteURI, user, password).GetAwaiter().GetResult(); var odata = noMetaData ? OData.NOMETADATA : OData.VERBOSE; var endpointRequest = HttpWebRequest.CreateHttp(url); endpointRequest.Method = method.ToString(); endpointRequest.Accept = $"application/json;odata={odata}"; endpointRequest.ContentType = $"application/json;odata={odata}"; endpointRequest.Headers.Add("Authorization", "Bearer " + accessToken); if (!string.IsNullOrEmpty(xHttpMethod)) { endpointRequest.Headers.Add("IF-MATCH", "*"); endpointRequest.Headers.Add("X-HTTP-Method", xHttpMethod.ToUpper()); } return endpointRequest; } catch (System.Exception) { throw; }}
But when I try to do this same call via a HttpClient
call I get an "Bad Request" return?
i.e.
var sc = new StringContent(json, Encoding.UTF8, MediaTypeNames.Application.Json);var _httpResponse = await _authenticationManager.GetHttpResponseFromRequestWithBody(restUrl, HttpMethod.Post, sc, null);
I collect the HttpResponseMessage
via below two methods:
private HttpRequestMessage GetHttpRequestMessage(string url, HttpMethod method, string xHttpMethod, string odata){ var request = new HttpRequestMessage(method, url); // Set Bearer accessToken var accessToken = EnsureAccessTokenAsync(siteURI, user, password).GetAwaiter().GetResult(); request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken); // Set AcceptHeader var acceptHeader = MediaTypeWithQualityHeaderValue.Parse($"application/json;odata={odata}"); request.Headers.Accept.Add(acceptHeader); // IF-Match header if (!string.IsNullOrEmpty(xHttpMethod)) { // request.Headers.Add("IF-MATCH", "*"); request.Headers.IfMatch.Add(new EntityTagHeaderValue("*")); request.Headers.Add("X-HTTP-Method", xHttpMethod.ToUpper()); } return request;}public Task<HttpResponseMessage> GetHttpResponseFromRequestWithBody(string url, HttpMethod method, HttpContent content, string xHttpMethod, string odata = OData.NOMETADATA){ var request = GetHttpRequestMessage(url, method, xHttpMethod, odata); request.Content = content; Debug.WriteLine(request.Content); return httpClient.SendAsync(request);}
This works v=for every call where I need to 'GET' information, but not for the 'UPDATE/PUT' or 'POST' calls for some reason?
If I do that the response comes back as a "Bad Request" despite the fact that it is -as far as I can determine- an identical call?
Can anyone help out here?