I'm having trouble renaming a folder inside a document library using the REST api provided by SharePoint 2013. Here is the code I'm using below.
string digest = String.Empty;
using (var response = await connector.HttpClient.PostAsync("_api/contextinfo", null, token))
{
response.EnsureSuccessStatusCode();
var obj = await response.ReadObject("d");
digest = obj["GetContextWebInformation"].Value<string>("FormDigestValue");
}
using (var request = new HttpRequestMessage(HttpMethod.Post, String.Format("/_api/Web/GetFolderByServerRelativeUrl('{0}')", operation.Path.FullName)))
{
request.Headers.Add("X-HTTP-Method", "MERGE");
request.Headers.Add("IF-MATCH", "*");
request.Headers.Add("X-RequestDigest", digest);
//{ '__metadata': { 'type': 'SP.Folder' }, 'Name': 'New name' }
dynamic obj = new JObject();
obj.__metadata = new JObject();
obj.__metadata.type = "SP.Folder";
obj.Name = operation.DesiredName;
request.Content = new ODataJObjectContent(obj);
using (var response = await connector.HttpClient.SendAsync(request, token))
{
response.EnsureSuccessStatusCode();
await response.ReadText();
}
}
In Fiddler here is the request:
POST http://2013.blah.com/_api/Web/GetFolderByServerRelativeUrl('/Shared%20Documents/Test') HTTP/1.1
X-HTTP-Method: MERGE
IF-MATCH: *
X-RequestDigest: 0xA7C057B3AECE805B7313909570F64B8EACD7A677014B8EBE7F75CC5A7C081F87973D94E7CC22346964ECAB1FE3C6B326DA3B67DF7A646FE6F47E9B1E686C3985,11 Apr 2013 15:13:05 -0000
Accept: application/json; odata=verbose
Content-Type: application/json; odata=verbose
Host: 2013.skysync.com
Content-Length: 50
Expect: 100-continue
{"__metadata":{"type":"SP.Folder"},"Name":"Test2"}
And then the response:
HTTP/1.1 204 No Content
Cache-Control: private, max-age=0
Expires: Wed, 27 Mar 2013 15:13:15 GMT
Last-Modified: Thu, 11 Apr 2013 15:13:15 GMT
Server: Microsoft-IIS/8.0
X-SharePointHealthScore: 0
SPClientServiceRequestDuration: 15
X-AspNet-Version: 4.0.30319
SPRequestGuid: 53bd109c-43bb-2064-4a1b-82298b670ece
request-id: 53bd109c-43bb-2064-4a1b-82298b670ece
X-RequestDigest: 0x9CDB4F31CC5F3877C4383657C12BEC6CFF10FC28AB6A0BB2D9D38B4279187CBD1450359BDFF07F0E63FF550BFF96C46E0476FB895CDA104348AC066D86246BC6,11 Apr 2013 15:13:15 -0000
X-FRAME-OPTIONS: SAMEORIGIN
X-Powered-By: ASP.NET
MicrosoftSharePointTeamServices: 15.0.0.4420
X-Content-Type-Options: nosniff
X-MS-InvokeApp: 1; RequireReadOnly
Date: Thu, 11 Apr 2013 15:13:15 GMT
Everything looks good until I go back to SharePoint and the Test folder is still the same name. I'm following the guidelines from here and I've seen other very similar examples. I can rename it through the interface without any problem.
Thanks in advance for any help!
The following example demonstrates how to rename Folder via SharePoint 2013 REST service
Scenario: rename Archive folder to 2015 located in Documents
library
using (var client = new SPHttpClient(webUri, userName, password))
{
RenameFolder(client, webUri.ToString(),"Documents/Archive","2015");
}
where
private static void RenameFolder(SPHttpClient client, string webUrl,string folderUrl,string folderName)
{
var folderItemUrl = webUrl + "/_api/web/GetFolderByServerRelativeUrl('" + folderUrl + "')/ListItemAllFields";
var data = client.ExecuteJson(folderItemUrl);
var itemPayload = new {
__metadata = new { type = data["d"]["__metadata"]["type"] },
Title = folderName,
FileLeafRef = folderName,
};
var itemUrl = data["d"]["__metadata"]["uri"];
var headers = new Dictionary<string, string>();
headers["IF-MATCH"] = "*";
headers["X-HTTP-Method"] = "MERGE";
client.ExecuteJson((string)itemUrl, HttpMethod.Post, headers, itemPayload);
}
Note:
SPHttpClient class - inherits from HttpClient and provides some additional SharePoint specific functionaly such as getting
request digest
SPHttpClientHandler class - hides all the intricacies related to SharePoint Online authentication
Try to add list in your manifest file. It seems like a permissions problem, and when you have to "trust" an application then choose the list which you want to operate with.
Related
Okay, so I'm very new to using API's in code and I've been able to use a few that were actually pretty easy. But none of them required authentication. I've been trying to use Jira's REST API service via C#'s HttpClient class. See code below:
public void UpdateJiraIssue(string issueValue)
{
string url = $#"http://jira.mySite.com/rest/api/2/issue/{issueValue}/editmeta";
string jsonString = #"myNeatJsonData";
var content = new StringContent(jsonString, Encoding.UTF8, "application/json");
//Initialize Client
HttpClient apiClient = new HttpClient();
apiClient.BaseAddress = new System.Uri(url);
apiClient.DefaultRequestHeaders.Accept.Clear();
byte[] cred = UTF8Encoding.UTF8.GetBytes("username:password");
apiClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(cred));
apiClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
async Task RunJiraAPI()
{
using (HttpResponseMessage resp = await apiClient.PostAsync("editmeta", content))
{
if (resp.IsSuccessStatusCode)
{
var jsonSring = await resp.Content.ReadAsStringAsync();
}
}
}
RunJiraAPI();
return;
}
The problem I run into is that I get a 401 error (Authentication). Here's what my 'resp' object contains when I run the code:
resp: {StatusCode: 401, ReasonPhrase: ' ', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
X-AREQUESTID: 400x1314x1
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
Content-Security-Policy: frame-ancestors 'self'
X-ASEN: SEN-11158344
X-AUSERNAME: anonymous
Cache-Control: no-store, no-transform, no-cache
Set-Cookie: atlassian.xsrf.token=B2ZY-C2JQ-1AGH-PBLW_5ccc79da5af8e6abcb9bff5250f3305af3b2877a_lout; Path=/; Secure
WWW-Authenticate: OAuth realm="https%3A%2F%2Fjira.mySite.com"
X-Powered-By: ARR/3.0
X-Powered-By: ASP.NET
Date: Wed, 15 Jan 2020 13:40:22 GMT
Content-Length: 109
Content-Type: application/json; charset=UTF-8
}}
Request Message: {Method: POST, RequestUri: 'https://jira.rhlan.com/rest/api/2/issue/RHD-1116/editmeta', Version: 1.1, Content: System.Net.Http.StringContent, Headers:
{
Authorization: Basic cWE6aGVjc29mdDEyMw==
Accept: application/json
Content-Type: Application/json; charset=utf-8
Content-Length: 70
}}
Status Code: Unauthorized
I need to work on my json string a bit to get it working right (which is why I didn't include what it actually contains), but once I get passed the authentication error, I'll probably actually change things to do a get Jira issue via the API so I can see all the json data returned that way. Then I'll edit my json string accordingly.
Any ideas what I'm doing wrong here?
You can pass in credentials assuming you have a username and an api token.
string credentials= string.Format("{0}:{1}", username, apitoken);
byte[] byteCredentials = UTF8Encoding.UTF8.GetBytes(credentials);
And in your apiClient you can use it like this.
apiClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteCredentials));
You need a username and api-token. Your api-token should be your login password.
I'm trying to pass an object using TempData to another action method. Instead of redirecting to the action method, the controller gives me a white screen with the current action method in the URL. If I comment out the line where I pass the object to TempData, it redirects correctly. Is my object too complex to pass? Is there an alternative way of passing a complex object to another action methods?
Where I pass the object to TempData:
public async Task<IActionResult> UploadFile(IFormFile file)
{
if (file == null || file.Length == 0)
return Content("file not selected");
else
{
var path = Path.Combine(
Directory.GetCurrentDirectory(), "wwwroot",
"processes.json");
using (var stream = new FileStream(path, FileMode.Create))
{
await file.CopyToAsync(stream);
}
RetrieveModels rm = rm = new RetrieveModels(path);
List<FoundPattern> foundList = new List<FoundPattern>();
List<ProcessModel> processes = rm.Processes;
FindPatterns findp = new FindPatterns(processes, pt.KpiPatterns);
foundList = findp.fp;
TempData["list"] = foundList.ToList();
TempData["Name"] = "Multiple Business Processes";
return RedirectToAction("Overview");
}
}
Action method I want to get redirected to:
public IActionResult Overview()
{
var list = TempData["list"] as List<FoundPattern>;
ViewData["Name"] = TempData["Name"];
return View(list);
}
List of objects I'm trying to pass to TempData:
public class FoundPattern
{
public KpiPattern pattern = new KpiPattern();
public List<FoundElement> elements = new List<FoundElement>();
}
List of objects within object:
public class FoundElement
{
public List<string> ElementNames = new List<string>();
public bool Present { get; set; }
}
Response headers when it works:
HTTP/1.1 302 Found
Location: /Home/Overview
Server: Kestrel
Set-Cookie: .AspNetCore.Mvc.CookieTempDataProvider=CfDJ8Mu_qDgU_59HncGqqkEm39LG_cUi_rzUyuXXaEYreUFPL2etHRuHPv_5GVKDLcIIcvFhQg1KOzDBfhbvDbjZDpcp8JYzq5kpLHtfnw962pyXNHyCNbx_MOkKwGFSG_dQ_M7LlSVxWYHjqalsSe26K4IlRfGN8V9B5MAgIhWoURgF; path=/; samesite=strict; httponly
X-SourceFiles: =?UTF-8?B?QzpcVXNlcnNcWkFUXHNvdXJjZVxyZXBvc1xLUEl0b29sXEtQSXRvb2xcSG9tZVxVcGxvYWRGaWxl?=
X-Powered-By: ASP.NET
Date: Wed, 07 Feb 2018 10:38:40 GMT
Content-Length: 0
HTTP/1.1 200 OK
Transfer-Encoding: chunked
Content-Type: text/html; charset=utf-8
Server: Kestrel
Set-Cookie: .AspNetCore.Mvc.CookieTempDataProvider=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; samesite=strict
X-SourceFiles: =?UTF-8?B?QzpcVXNlcnNcWkFUXHNvdXJjZVxyZXBvc1xLUEl0b29sXEtQSXRvb2xcSG9tZVxPdmVydmlldw==?=
X-Powered-By: ASP.NET
Date: Wed, 07 Feb 2018 10:38:40 GMT
Response headers when it doesn't work:
HTTP/1.1 500 Internal Server Error
Server: Kestrel
X-SourceFiles: =?UTF-8?B?QzpcVXNlcnNcWkFUXHNvdXJjZVxyZXBvc1xLUEl0b29sXEtQSXRvb2xcSG9tZVxVcGxvYWRGaWxl?=
X-Powered-By: ASP.NET
Date: Wed, 07 Feb 2018 10:41:28 GMT
Content-Length: 0
You are using the CookieTempDataProvider to manage TempData. Alas, it results in storing the TempData in cookies, as the name suggests.
The problem is that your data is too large to fit in the cookie. You may wish to use a different ITempDataProvider implementation (such as SessionStateTempDataProvider).
I am having a big problem when trying to authenticate to QuickBlox's server using a Token.
The method I use is:
public static async Task<LoginResponse> GetLoginResponseAsync(string email, string password)
{
LoginResponse result = null;
using (var client = new HttpClient())
{
string token = QbProvider.SessionResponse.Session.Token;
LoginRequest request = new LoginRequest()
{
Email = email,
Password = password
};
using (var requestMessage = new HttpRequestMessage(HttpMethod.Post, LoginUrlRequest))
{
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("QB-Token", token);
using (var response = await client.SendAsync(requestMessage))
{
string json = response.Content.ReadAsStringAsync().Result;
result = JsonConvert.DeserializeObject<LoginResponse>(json);
}
}
}
return result;
}
The server's response is:
{"errors":["Token is required"]}
And the headers (debugging) in the client object are:
{
StatusCode: 401, ReasonPhrase: 'Unauthorized', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
Access-Control-Allow-Origin: *
Cache-Control: no-cache
Date: Thu, 01 Jun 2017 12:05:29 GMT
QuickBlox-REST-API-Version: 0.1.1
Server: openresty/1.9.15.1
Status: 401 Unauthorized
Strict-Transport-Security: max-age=31536000
WWW-Authenticate: OAuth realm=users
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-Request-Id: 584a0dca-fc44-4114-9626-327ac1729f67
X-Runtime: 0.003430
X-XSS-Protection: 1; mode=block
Connection: keep-alive
Content-Type: application/json; charset=utf-8
Content-Length: 32
}
}
When I use the Token in Postman, the server's response is successfull.
Do you know what am I doing wrong?
Thank you so much in advance!
Regards.
Try adding your token header using requestMessage.Headers.Add("QB-Token", token) instead of your Authorization one – by #dukedukes
I need to show the image on my web page. I have given the url of the image as:
<img src="http://localhost:57401/assets/getimagebyid/?userId=22&imageId=2012" alt="Sample Image">
This is the API method to get the stream:
public HttpResponseMessage GetImageById(int userId, int imageId)
{
var objResponse = new HttpResponseMessage();
var ImageStream = ImageStorage.DownloadImageStream(userId, imageId);
var resourceByteArray = new byte[ImageStream .Length];
var dataStream = new MemoryStream(resourceByteArray);
objResponse.Content = new StreamContent(dataStream);
objResponse.Content.Headers.ContentType = new MediaTypeHeaderValue("image/jpeg");
objResponse.StatusCode = HttpStatusCode.OK;
return objResponse;
}
These are the response headers in the developer console:
HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Length: 209855
Content-Type: image/jpeg
Expires: -1
Server: Microsoft-IIS/8.0
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?QzpcaW5ldHB1Ylx3d3dyb290XFBob3RvQnV0bGVyXFBob3RvQnV0bGVyLkFQSVxhc3NldHNcZ2V0YXNzZXRzYnlpZFw=?=
X-Powered-By: ASP.NET
Date: Tue, 24 May 2016 10:57:09 GMT
There is no error in the above code. Also, the status is 200(OK). Why the image is not showing on the web page? What am I missing?
I am trying to extract the ETag from the response header. It does exist in the response. I can see it using firebug and I can see it in the response object using the inspector:
Status: 200 OK
X-Api-Version: 1.3.2
Access-Control-Allow-Origin: *
X-Runtime: 0.151298
Connection: keep-alive
Content-Length: 8185
Cache-Control: public, max-age=11216
Content-Type: application/json; charset=utf-8
Date: Fri, 09 Mar 2012 01:40:05 GMT
Expires: Fri, 09 Mar 2012 04:47:01 GMT
ETag: "bd3fe1123a8f55e01ca859f4804e8fbe"
Last-Modified: Fri, 09 Mar 2012 00:47:01 GMT
Server: nginx/1.0.11
All the other code is working fine, making the HttpWebRequest, getting the respose etc. The only problem is I always get null when trying to get the ETag (which does existing in the response header).
Here is the simplified code:
var request = (HttpWebRequest)WebRequest.Create(validUri);
SetHeaders(); // helper function to set basic headers.
var response = request.GetResponse();
var stream = response.GetResponseStream();
var reader = new StreamReader(stream);
var result = reader.ReadToEnd();
var etag = response.Headers.Get("ETag");
Anyone know why I can't seem to extract the existing ETag?
Your code does not reproduce the problem you are describing. Your problem is in something that you have not mentioned. Here is a short complete program based on your code, that executes and does print out the value of ETag without a problem:
using System;
using System.IO;
using System.Net;
namespace SO9628006
{
class Program
{
static void Main()
{
var request = (HttpWebRequest)WebRequest.Create("http://www.fiddler2.com/Fiddler/Fiddler.css");
var response = request.GetResponse();
var stream = response.GetResponseStream();
var reader = new StreamReader(stream);
var result = reader.ReadToEnd();
var etag = response.Headers.Get("ETag");
Console.WriteLine(etag);
}
}
}
Output:
"6c3673ba919ec71:243"
Could you please provide short but complete program that illustrates your issue?