I have this problem. i have to submit a file (or not) to an endpoint on an API of bmc.
the KEY:entry with the VALUE:data_entry.txt is the json to send with the values, as the same of the body.
The attach-z2AF_WIAttachment1 is the file i want to submit. I'm it's always throuwing some error, or headers invalid, or filetype not valid, but in postman is working.
I cant convert to C#.
this is my code so far, or now.
try
{
//authentication
var dict = new Dictionary<string, string>();
dict.Add("username", "applicationUsernameJonDoe");
dict.Add("password", "applicationPassowrdXPTO");
var clientLogin = new HttpClient();
var req = new HttpRequestMessage(HttpMethod.Post, Endpoint_loginITSM) { Content = new FormUrlEncodedContent(dict) };
var res = clientLogin.SendAsync(req); //.Result.ToString();
var body = res.GetAwaiter().GetResult().Content.ReadAsStringAsync();
//pedido de criação de registo
using (var client = new HttpClient())
{
client.Timeout = TimeSpan.FromMinutes(10);
var request = new HttpRequestMessage
{
RequestUri = new Uri(Endpoint_CreateITSM),
Method = HttpMethod.Post
};
request.Headers.Add("Authorization", body.Result.ToString());
if (!string.IsNullOrEmpty(registos.Objeto.fileName))
{
registos.Objeto.Registo.z2AF_WIAttachment1 = registos.Objeto.fileName;
}
string json = JsonConvert.SerializeObject(new { values = registos.Objeto });
byte[] file_bytes = System.Convert.FromBase64String(registos.Objeto.fileEncoded);
MemoryStream memoryStream = new MemoryStream();
using (BsonDataWriter writer = new BsonDataWriter(memoryStream))
{
JsonSerializer serializer = new JsonSerializer();
serializer.Serialize(writer, registos.Objeto.Registo);
}
var data_entry_bytes = memoryStream.ToArray();
// we need to send a request with multipart/form-data
var multiForm = new MultipartFormDataContent();
ByteArrayContent data_entry_json_content = new ByteArrayContent(data_entry_bytes);
data_entry_json_content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
data_entry_json_content.Headers.ContentDisposition = new ContentDispositionHeaderValue("entry")
{
FileName = "data_entry.txt",
Name = "entry",
};
multiForm.Add(data_entry_json_content);
ByteArrayContent z2AF_WIAttachment1_content = new ByteArrayContent(file_bytes);
z2AF_WIAttachment1_content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
z2AF_WIAttachment1_content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attach-z2AF_WIAttachment1")
{
FileName = registos.Objeto.fileName,
Name = "attach-z2AF_WIAttachment1",
};
multiForm.Add(z2AF_WIAttachment1_content);
request.Content = multiForm;
var result = await client.SendAsync(request);
var resBody = result.Content.ReadAsStringAsync().Result.ToString();//.ConfigureAwait(false);
dynamic _resBody = JsonConvert.DeserializeObject<dynamic>(resBody);
string registoID = _resBody["values"].SysRequestID;
return ResponseHandler<string>.Resposta(false, "resposta api bit criar registos", registoID);
}
}
catch (Exception e)
{
string classname = this.GetType().Name;
CentralLibrary.Services.ErrorLoggingService.ErrorLogsForCore(classname, e, _env.WebRootPath);
return ResponseHandler<string>.Resposta(true, "EXCEPTION : resposta api bit criar registos", e.Message);
}
Here is a better solution.
I had a problem with the last, but for someone who doesnt wnat to use de library RestClient that's the way. But this is working 100% and i have JsonProperty Names for NewtonSoft.Json so this workin with names like
[JsonProperty("z1D Action")]
public string z1D_Action { get; } = "CREATE";
so, my code is, and using an object AbrirRegistosITSM with nested object AbrirRegistosITSM_com_anexo my final solution is
AbrirRegistosITSM _registo = new AbrirRegistosITSM
{
Values = new AbrirRegistosITSM_com_anexo
{
Details = registos.Objeto.Comentario,
Customer_Login = registos.username,
Login_ID = registos.username,
SR_Type_Field_3 = registos.Objeto.Tipologia,
SR_Type_Field_28 = registos.Objeto.Categoria,
z2AF_WIAttachment1 = registos.Objeto.FicheiroNome
}
};
var client = new RestClient(Endpoint_CreateITSM);
string baseFolder = _env.WebRootPath;
string pathDir = Path.Combine(baseFolder, DateTime.Now.ToString().Replace('/', '_').Replace(' ', '_').Replace(':', '_'));
Directory.CreateDirectory(pathDir);
string pathDirFile = Path.Combine(pathDir, registos.Objeto.FicheiroNome);
File.WriteAllBytes(pathDirFile, Convert.FromBase64String(registos.Objeto.FicheiroBase64));
string pathEntryDir = Path.Combine(baseFolder, DateTime.Now.ToString().Replace('/', '_').Replace(' ', '_').Replace(':', '_'));
Directory.CreateDirectory(pathEntryDir);
string patnEntrydirFile = Path.Combine(pathEntryDir, "data_entry.txt");
File.WriteAllText(patnEntrydirFile, JsonConvert.SerializeObject(new { values = _registo.Values }));
var request = new RestRequest();
request.Method = Method.Post;
request.AddHeader("Authorization", token);
request.AddFile("entry", patnEntrydirFile, "application/json");
request.AddFile("attach-z2AF_WIAttachment1", pathDirFile, "application/octet-stream");
var reqbody = JsonConvert.SerializeObject(_registo);
request.AddParameter("application/json", reqbody, ParameterType.RequestBody);
RestResponse response = client.Execute(request);
var respostaBody = response.Content.ToString();//.ConfigureAwait(false);
dynamic _respostaBody = JsonConvert.DeserializeObject<dynamic>(respostaBody);
string _registoID = _respostaBody["values"]["Request Number"];
then i return the request number that what i need, but you have a lot of values there. I use NewtonSoft remember that. I dont use JsonSerializer because i wasn't able to save the json property names with spaces with JsonSerializer.
I'm not entirely sure what's going wrong here. It can be a lot of things, but I might be able to get you going. The last couple of weeks I build a HttpClient that sends a file with metadata to a GraphQL endpoint.
Please ensure the following:
I think you are requesting the file through an call. Please store it in a variable as a Byte[] using the ReadAsByteArrayAsync(). Do note decode it or cast it to a string or anything. You'll just corrupt the file.
var response = client.GetAsync(fileUrl);
var downloadedFile = await response.Result.Content.ReadAsByteArrayAsync();
The following code might not work entirely in your case, but should help you get going building the right request, since I'm also sending metadata in my request containing the file extension and some other information. This will most likely send the file to your API without a file extension.
using (var client = new HttpClient())
{
var file = new byte[] { 1, 2, 3 };
var fileToUpload = new ByteArrayContent(file);
var formData = new MultipartFormDataContent
{
{ fileToUpload, "entry", "passInFileExtensionForExample"},
{ fileToUpload, "attach-z2AF_WIAttachment1", "passInFileExtensionForExample" }
};
var response = await client.PostAsync("endpoint", formData);
}
Add the Bearer token using the following code:
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
So i've discover the solution for my problem. I'm gonna to submit only one file. I have to submit also the Json body as a file "entry" "data_entry.txt" and for HttpRequestMessage you have to have a content MultipartFormDataContent and here you can add as many files as you have. i have to convert the Json body to a file ( in this case i converted to binary Array) with the name entry, and the name of the file data_entry.txt, but it's what the endpoint needs, so...whatever.
using (var client = new HttpClient())
{
client.Timeout = TimeSpan.FromMinutes(10);
MultipartFormDataContent content = new MultipartFormDataContent();
//adicionar ficheiro
byte[] file_bytes = System.Convert.FromBase64String(registos.Objeto.fileEncoded);
StreamContent fileContent = new StreamContent(new MemoryStream(file_bytes));
fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
Name = "files[attach-z2AF_WIAttachment1]",
FileName = registos.Objeto.fileName
};
fileContent.Headers.ContentType = MediaTypeHeaderValue.Parse("application/octet-stream");
content.Add(fileContent);
//adicionar ficheiro entry
StreamContent entryStreamContent = new StreamContent(new MemoryStream(ObjectToByteArray(registos.Objeto.Registo)));
entryStreamContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
Name = "files[entry]",
FileName = "data_entry.txt"
};
entryStreamContent.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");
content.Add(entryStreamContent);
var request = new HttpRequestMessage
{
RequestUri = new Uri(Endpoint_CreateITSM),
Method = HttpMethod.Post,
Content= content
};
request.Headers.Add("Authorization", body.Result.ToString());
string json = JsonConvert.SerializeObject(new { values = registos.Objeto.Registo});
request.Content = new ByteArrayContent(Encoding.UTF8.GetBytes(json));
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
var resposta = await client.SendAsync(request);
var respostaBody = resposta.Content.ReadAsStringAsync().Result.ToString();//.ConfigureAwait(false);
dynamic _respostaBody = JsonConvert.DeserializeObject<dynamic>(respostaBody);
string _registoID = _respostaBody["values"].SysRequestID;
return ResponseHandler<string>.Resposta(false, "resposta api bit criar registos", _registoID);
So this is my solution. and it's working :)
I am doing a request through postman to a specific url but I set the form-data type in order to get data to the site like this:
Now I want to program this request inside C# but everything I tried so far is returning a 400 Bad Request response. This is what I tried:
public async Task<CheckAccessTokenModel> CheckAccessTokenAsync(string accessToken)
{
string uriString = "someurl";
var uri = new Uri(uriString);
try
{
using(var httpClient = new HttpClient())
{
var request = new HttpRequestMessage
{
Method = HttpMethod.Post,
RequestUri = uri
};
var ClientId = ConfigurationAccessor.Configuration["WebCredentials:ClientId"];
var Secret = ConfigurationAccessor.Configuration["WebCredentials:Secret"];
var authString = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{ClientId}:{Secret}"));
request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", authString);
MultipartFormDataContent content = new MultipartFormDataContent();
content.Add(new StringContent("token"), accessToken);
request.Content = content;
var response = await httpClient.SendAsync(request);
var checkTokenResponseData = await response.Content.ReadAsStringAsync();
//return new CheckAccessTokenModel { Active = true, Exp = 1647431224233 };
return JsonConvert.DeserializeObject<CheckAccessTokenModel>(checkTokenResponseData);
}
}
catch
{
return null;
}
}
I am doing it with the MultipartFormDataContent Object as suggested by many others here but it still won't work.
What can be the problem here?
EDIT: Wrong picture replaced
You can simply
request.Content = new StringContent($"token={accessToken}");
With form data I think it's something like this:
var data = new Dictionary<string, string>
{
{"token", acccessToken}
};
using var content = new FormUrlEncodedContent(data);
request.Content = content;
I'm trying to Get all files from a folder on a SharePoint site AND creating folders on said site. So GET/POST.
When i'm trying to GET the files from the folder https://xxxxxx.sharepoint.com/sites/Test/Syra_Test/
i get a 200 success but nothing in the resulting json.: "{"odata.metadata":"https://xxxxxx.sharepoint.com/_api/$metadata#SP.ApiData.Files12\","value":[]}" i'm guessing its path issues but i don't know.
see function1()
I am now trying to create folders, however i get a 403 error.
see function2()
private static void Function1(){
//string RESTURL = "{0}/_api/web/lists/GetByTitle('Test')/items?$top=1";
string RESTURL = "{0}/_api/web/GetFolderByServerRelativeUrl('/General')/Files";
string webUrl = "https://xxxxxx.sharepoint.com";
string USER = "xxxxx#xxxxx.com";
var passWord = new SecureString();
string PWD = "xxxxx";
PWD.ToList().ForEach(passWord.AppendChar);
var credential = new SharePointOnlineCredentials(USER, passWord);
using (var handler = new HttpClientHandler() { Credentials = credential })
{
//Get authentication cookie
Uri uri = new Uri(webUrl);
handler.CookieContainer.SetCookies(uri, credential.GetAuthenticationCookie(uri));
//Invoke REST API
using (var client = new HttpClient(handler))
{
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = client.GetAsync(string.Format(RESTURL, webUrl)).Result;
response.EnsureSuccessStatusCode();
string jsonData = response.Content.ReadAsStringAsync().Result;
}
}
}
private static void Function2(){
string RESTURL = "{0}/_api/web/folders";
string webUrl = "https://xxxx.sharepoint.com";
string USER = "xxxx#xxxxx.com";
var passWord = new SecureString();
string PWD = "xxxxx";
PWD.ToList().ForEach(passWord.AppendChar);
var credential = new SharePointOnlineCredentials(USER, passWord);
using (var handler = new HttpClientHandler() { Credentials = credential })
{
//Get authentication cookie
Uri uri = new Uri(webUrl);
handler.CookieContainer.SetCookies(uri, credential.GetAuthenticationCookie(uri));
//Invoke REST API
using (var client = new HttpClient(handler))
{
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Add("X-HTTP-Method", "POST");
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
string json = "{'__metadata': { 'type': 'SP.Folder' }, 'ServerRelativeUrl': '/shared documents/folderSyraCreated'}";
StringContent strContent = new StringContent(json);
HttpResponseMessage response = client.PostAsync(string.Format(RESTURL, webUrl), strContent).Result;
response.EnsureSuccessStatusCode();
string jsonData = response.Content.ReadAsStringAsync().Result;
}
}
}
Can't use external dll's (csom) in this case (plugin for an economy system)
Hope it makes sense :)
I am trying to upload image to ServiceNow incident using SNow API provided in this link:
https://developer.servicenow.com/dev.do#!/reference/api/orlando/rest/c_AttachmentAPI#r_AttachmentAPI-POSTmultipart
I've written below C# code to post the image:
string url = "https://mycompany.service-now.com/api/now/attachment/upload/"
, userName = "MyUser", passwd = "MyPassword";
var httpClientHandler = new HttpClientHandler()
{
Credentials = new NetworkCredential(userName, passwd),
};
using (var httpClient = new HttpClient(httpClientHandler))
{
// Add an Accept header for JSON format.
httpClient.DefaultRequestHeaders.Accept.Clear();
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var multipartContent = new MultipartFormDataContent();
multipartContent.Headers.TryAddWithoutValidation("Content-Type", "multipart/form-data");
multipartContent.Add(new StringContent("incident"), "table_name");
multipartContent.Add(new StringContent("f264fd3a1bghghgjjhg8f7b4bcbb6"), "table_sys_id"); // id of my incident
multipartContent.Add(new ByteArrayContent(File.ReadAllBytes("D:\\MyImage.jpeg")), "uploadFile", "MyImage.jpeg");
var response = httpClient.PostAsync(new Uri(url), multipartContent).Result;
string result = response.Content.ReadAsStringAsync().Result;
MessageBox.Show(result);
}
However, I keep getting:
Requested URI does not represent any resource
What could be the problem and how to adjust the code accordingly?
After removing the "/" at the end of the url, and also adding double qoutes around the keys in the headers as I read from this post:
https://community.servicenow.com/community?id=community_question&sys_id=328614ffdb00eb808e7c2926ca9619ad&view_source=searchResult
The final working code is:
string url = "https://mycompany.service-now.com/api/now/attachment/upload"
, userName = "MyUser", passwd = "MyPassword";
var httpClientHandler = new HttpClientHandler()
{
Credentials = new NetworkCredential(userName, passwd),
};
using (var httpClient = new HttpClient(httpClientHandler))
{
// Add an Accept header for JSON format.
httpClient.DefaultRequestHeaders.Accept.Clear();
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var fileStream = new ByteArrayContent(File.ReadAllBytes("D:\\Image.jpeg"));
fileStream.Headers.Remove("Content-Type");
fileStream.Headers.Add("Content-Type", "application/octet-stream");
fileStream.Headers.Add("Content-Transfer-Encoding", "binary");
fileStream.Headers.Add("Content-Disposition", $"form-data;name=\"uploadFile\"; filename=\"{"Image.jpeg"}\"");
var multipartContent = new MultipartFormDataContent();
multipartContent.Add(new StringContent("incident"), "\"table_name\"");
multipartContent.Add(new StringContent("f264fd3a1bghghgjjhg8f7b4bcbb6"), "\"table_sys_id\"");
multipartContent.Add(fileStream, "uploadFile");
var response = httpClient.PostAsync(new Uri(url), multipartContent).Result;
string result = response.Content.ReadAsStringAsync().Result;
MessageBox.Show(result);
}
I want to search sharepoint document using C# api call.
I am trying below code:
string URL = "http://server/_api/search/query?query_parameter=value&query_parameter=value";
System.Net.Http.HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(string.Format("{0}:{1}", "XXXXX", "XXXXXX"))));
using (client)
{
HttpResponseMessage httpResponseMessage = await client.GetAsync(URL);
HttpResponseMessage responsemMsgx = httpResponseMessage;
if (responsemMsgx.IsSuccessStatusCode)
{
}
}
But,i am have a doubt regarding URL below:
string URL = "http://server/_api/search/query?query_parameter=value&query_parameter=value";
Please help me with the sharepoint server and constructing the URL.
My expected output is something like JSON .
If you want to search documents, we can use the Search REST API below to achieve it.
/_api/search/query?querytext='IsDocument:True'
C# example:
string siteUrl = "http://sp2013/sites/team";
string searchQuery = "/_api/search/query?querytext='IsDocument:True'";//search all documents
var credential = new System.Net.NetworkCredential("username", "password", "domainname");
HttpClientHandler handler = new HttpClientHandler() { Credentials = credential };
HttpClient client = new HttpClient(handler);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Add("Accept", "application/json;odata=verbose");
client.DefaultRequestHeaders.Add("ContentType", "application/json;odata=verbose");
var result = client.GetAsync(siteUrl+searchQuery).Result;
var content = result.Content.ReadAsStringAsync().Result;
JObject jobj = JObject.Parse(content);
JArray jarr = (JArray)jobj["d"]["query"]["PrimaryQueryResult"]["RelevantResults"]["Table"]["Rows"]["results"];
foreach (JObject j in jarr)
{
JArray results = (JArray)j["Cells"]["results"];
var title = "";
var path = "";
foreach (JObject r in results)
{
if (r["Key"] != null)
{
if (r["Key"].ToString() == "Title")
{
title = r["Value"].ToString();
}
if (r["Key"].ToString() == "Path")
{
path = r["Value"].ToString();
}
}
}
Console.WriteLine(title + "|" + path);
}