Batch multipart content response, problem Japanese character - c#

Batch request returns 400 Bad Request.
I convert Japanese character to Shift-JIS: "description": 譌・ (shift_jis)
This is what it contains:
--batch_request
Content-Type:multipart/mixed;boundary=changeset_1
--changeset_1
Content-Type: application/http
Content-Transfer-Encoding:binary
Content-Id: 1
POST https://.... HTTP/1.1
Accept: application/json
Content-Type: application/json
{\"objectId\":\"5f6851c3-99cc-4a89-936d-4bb44fa78a34\",\"description\":\"譌・\"}
--changeset_1--
--batch_request--
Client:
public async Task<List<string>> POSTBatch(string endpoint, string contentbody)
{
HttpResponseMessage response = null;
HttpRequestMessage batchRequest = null;
HttpContent httpContent = null;
try
{
var requestcontent = new DemoRequestContent(contentbody);
httpContent = requestcontent.GetHttpContent(Encoding.UTF8, text/plain);
httpContent.Headers.Add(DemoConst.CSRF_NONCE, getCSRF_NONE().Result);
httpContent.Headers.ContentType = MediaTypeHeaderValue.Parse("multipart/mixed;boundary=batch_request");
var method = new HttpMethod("POST");
batchRequest = new HttpRequestMessage(method, baseURL + endpoint);
batchRequest.Content = httpContent;
response = await httpClient.SendAsync(batchRequest);
.............
// Spilt response
var multipartRespMsgs = getMultiPart(response);
...............
}
catch (Exception ex)
{
}
}
The key is to add a new content type "msgtype" header to the response:
private async Task<List<HttpResponseMessage>> getMultiPart(HttpResponseMessage response){
var multipartContent = await response.Content.ReadAsMultipartAsync();
var multipartRespMsgs = new List<HttpResponseMessage>();
foreach (HttpContent currentContent in multipartContent.Contents) {
// Two cases:
// 1. a "single" response
if (currentContent.Headers.ContentType.MediaType.Equals("application/http", StringComparison.OrdinalIgnoreCase)) {
if (!currentContent.Headers.ContentType.Parameters.Any(parameter => parameter.Name.Equals("msgtype", StringComparison.OrdinalIgnoreCase) && parameter.Value.Equals("response", StringComparison.OrdinalIgnoreCase))) {
currentContent.Headers.ContentType.Parameters.Add(new NameValueHeaderValue("msgtype", "response"));
}
multipartRespMsgs.Add(await currentContent.ReadAsHttpResponseMessageAsync());
// The single object in multipartRespMsgs contains a classic exploitable HttpResponseMessage (with IsSuccessStatusCode, Content.ReadAsStringAsync().Result, etc.)
}
// 2. a changeset response, which is an embedded multipart content
else {
var subMultipartContent = await currentContent.ReadAsMultipartAsync();
foreach (HttpContent currentSubContent in subMultipartContent.Contents) {
currentSubContent.Headers.ContentType.Parameters.Add(new NameValueHeaderValue("msgtype", "response"));
multipartRespMsgs.Add(await currentSubContent.ReadAsHttpResponseMessageAsync());
// Same here, the objects in multipartRespMsgs contain classic exploitable HttpResponseMessages
}
}
}
}
In my example, testString contains:
{\"objectId\":\"5f6851c3-99cc-4a89-936d-4bb44fa78a34\",\"description\":\"譌・\"}
When go to case 1:
multipartRespMsgs.Add(await currentContent.ReadAsHttpResponseMessageAsync()); // 400 Bad Request
UPDATE: Server log
org.apache.catalina.connector.ClientAbortException: java.io.IOException: An established connection was aborted by the software in your host machine
at org.apache.catalina.connector.OutputBuffer.realWriteBytes(OutputBuffer.java:372)
at org.apache.catalina.connector.OutputBuffer.flushByteBuffer(OutputBuffer.java:841)
at org.apache.catalina.connector.OutputBuffer.append(OutputBuffer.java:746)
at org.apache.catalina.connector.OutputBuffer.writeBytes(OutputBuffer.java:407)
at org.apache.catalina.connector.OutputBuffer.write(OutputBuffer.java:385)
at org.apache.catalina.connector.CoyoteOutputStream.write(CoyoteOutputStream.java:96)
at wt.servlet.ServletRequestMonitor$CountingOutputStream.write(ServletRequestMonitor.java:2388)
at java.util.zip.GZIPOutputStream.finish(GZIPOutputStream.java:168)
at wt.servlet.CompressionFilter$GzippingResponse.finish(CompressionFilter.java:623)
at wt.servlet.CompressionFilter$GzippingResponse.close(CompressionFilter.java:394)
at wt.servlet.CompressionFilter.doFilter(CompressionFilter.java:302)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at wt.servlet.RequestInterrupter.doFilter(RequestInterrupter.java:335)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at wt.servlet.ServletRequestMonitor.doFilter(ServletRequestMonitor.java:1660)
at wt.servlet.ServletRequestMonitorFilter.doFilter(ServletRequestMonitorFilter.java:56)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:543)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
at org.apache.coyote.ajp.AjpProcessor.service(AjpProcessor.java:524)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:818)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1637)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.io.IOException: An established connection was aborted by the software in your host machine
at sun.nio.ch.SocketDispatcher.write0(Native Method)
at sun.nio.ch.SocketDispatcher.write(SocketDispatcher.java:51)
at sun.nio.ch.IOUtil.writeFromNativeBuffer(IOUtil.java:93)
at sun.nio.ch.IOUtil.write(IOUtil.java:65)
at sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:471)
at org.apache.tomcat.util.net.NioChannel.write(NioChannel.java:136)
at org.apache.tomcat.util.net.NioBlockingSelector.write(NioBlockingSelector.java:101)
at org.apache.tomcat.util.net.NioSelectorPool.write(NioSelectorPool.java:157)
at org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper.doWrite(NioEndpoint.java:1322)
at org.apache.tomcat.util.net.SocketWrapperBase.doWrite(SocketWrapperBase.java:692)
at org.apache.tomcat.util.net.SocketWrapperBase.writeBlocking(SocketWrapperBase.java:485)
at org.apache.tomcat.util.net.SocketWrapperBase.write(SocketWrapperBase.java:409)
at org.apache.coyote.ajp.AjpProcessor.writeData(AjpProcessor.java:1390)
at org.apache.coyote.ajp.AjpProcessor.access$900(AjpProcessor.java:58)
at org.apache.coyote.ajp.AjpProcessor$SocketOutputBuffer.doWrite(AjpProcessor.java:1508)
at org.apache.coyote.Response.doWrite(Response.java:600)
at org.apache.catalina.connector.OutputBuffer.realWriteBytes(OutputBuffer.java:360)
... 35 more
Please give me the solution to this problem.
Thank you

Related

How to fix Unable to send GET request - 403 error

I am new to the C# world, and can't for the life of me figure out how to get around this error. I am trying to make a simple get request using a platform API key. I have built out the API connection in Google App Script on the same laptop, and it works fine, but when trying to build out the same API in C#, it is returning:
{StatusCode: 403, ReasonPhrase: 'Forbidden', Version: 1.1, Content: System.Net.Http.HttpConnectionResponseContent, Headers:
{
Date: Sun, 13 Mar 2022 02:41:29 GMT
Transfer-Encoding: chunked
Connection: close
CF-Chl-Bypass: 1
Permissions-Policy: accelerometer=(),autoplay=(),camera=(),clipboard-read=(),clipboard-write=(),fullscreen=(),geolocation=(),gyroscope=(),hid=(),interest-cohort=(),magnetometer=(),microphone=(),payment=(),publickey-credentials-get=(),screen-wake-lock=(),serial=(),sync-xhr=(),usb=()
Cache-Control: private, max-age=0, no-store, no-cache, must-revalidate, post-check=0, pre-check=0
X-Frame-Options: SAMEORIGIN
Expect-CT: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
Strict-Transport-Security: max-age=2592000
Server: cloudflare
CF-RAY: 6eb1692f8bd776c3-LHR
Content-Type: text/html; charset=utf-8
Expires: Thu, 01 Jan 1970 00:00:01 GMT
}}
The API documentation says:
"To authenticate against the API, include your API key in the 'Authorization' header, prefixed with 'Key ', in every request. Example: 'Authorization: Key yourapikey'"
And so, I have tried adding this to
a) the HttpClient via HttpClient.DefaultRequestHeaders.Authorization
b) the HttpClient via HttpClient.DefaultHeaders.Add
c) the HttpRequestMessage via HttpRequestMessage.Headers.Add
In each instance, the request URI looks good, as well as the headers, but still returning 403.
My current structure is:
// services
builder.Services.AddHttpClient("myplatform", c =>
{
c.BaseAddress = new Uri("https://seller-api.myplatform.com/v2/");
c.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
});
// controller
// constructor uses IHttpClientFactory
this._httpClient = clientFactory.CreateClient("myplatform");
// service
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Key", platformKey);
string endPoint = "offers" + CreateQueryString(pageNumber, pageSize);
// example endPoint: offers?page_number=1&page_size=100
var requestMsg = new HttpRequestMessage()
{
Method = HttpMethod.Get,
RequestUri = new Uri(httpClient.BaseAddress + endPoint)
};
try
{
var result = await httpClient.SendAsync(requestMsg);
}
catch (Exception ex)
{
}
Again, the content of the call works when calling through GoogleAppScript. What am I doing wrong in C#, and how can I correct this?
Not sure if this is all the information needed - let me know otherwise! Important to note, the target framework is .NET 6.0.
EDIT
As suggested by a comment around duplicate clients, I have removed the client factory. I am now creating a new HttpClient in the controller constructor, and passing this client to my service to do the GET request.
this._httpClient = new HttpClient();
Again, the client and the request message look well formed at time of request but still returning 403 error. Is there an issue with my VS22 client, or web client etc.?
Also, the call I am making successfully via Google AppScript is using UrlFetchApp. Not sure what is the issue here with the C# side..
EDIT2
Adding current GAS code for reference:
var url = 'https://seller-api.platform.com/v2';
var end_point = '/offers?';
var header = {
'Authorization': api_key
}
var params = {
'method': 'GET',
'headers': header
}
// call API
var page_query = 'page_number=' + page + '&page_size=' + maxItemsPerPage;
var full_url = url + end_point + page_query;
var response = UrlFetchApp.fetch(full_url, params);
The HTTP 403 Forbidden response status code indicates that the server understands the request but refuses to authorize it.
There are two ways add request headers when using HttpClient:
Add headers for all requests using HttpClient.DefaultRequestHeaders.
HttpClient = new HttpClient();
HttpClient.DefaultRequestHeaders.Add("Key", platformKey);
var response = await HttpClient.GetAsync(GetRandomNumberUrl);
response.EnsureSuccessStatusCode();
await response.Content.ReadAsStringAsync();
Add headers per request using HttpRequestMessage.Headers.
HttpClient = new HttpClient();
using (var request = new HttpRequestMessage(HttpMethod.Get, randomNumberUrl))
{
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", platformKey);
var response = await HttpClient.SendAsync(request);
response.EnsureSuccessStatusCode();
await response.Content.ReadAsStringAsync();
}
Your problem is here in this line:
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Key", platformKey);
your _httpClient and Authorization httpClient is not same instance.
Try this way:
HttpClient HttpClient = new HttpClient();
string url = "https://seller-api.platform.com/v2";
string end_point = "/offers?";
string api_key = "key here";
string page_query = "page_number=" + 10 + "&page_size=" + 20;
string full_url = url + end_point + page_query;
using (var request = new HttpRequestMessage(HttpMethod.Get, url))
{
request.Headers.Add("Authorization", api_key);
var response = await HttpClient.SendAsync(request);
response.EnsureSuccessStatusCode();
var m = await response.Content.ReadAsStringAsync();
}
Solution 2:
Try calling it like a browser :
HttpClient httpClient = new HttpClient();
string url = "https://gatewayt.whatever.com/chkt/request/request.php";
string end_point = "/offers?";
string api_key = "key here";
string page_query = "page_number=" + 10 + "&page_size=" + 20;
string full_url = url + end_point + page_query;
httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Accept", "text/html,application/xhtml+xml,application/xml");
httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Accept-Encoding", "gzip, deflate");
httpClient.DefaultRequestHeaders.TryAddWithoutValidation("User-Agent", "Mozilla/5.0 (Windows NT 6.2; WOW64; rv:19.0) Gecko/20100101 Firefox/19.0");
httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Accept-Charset", "ISO-8859-1");
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Key", api_key);
var response = await httpClient.GetAsync(url);
response.EnsureSuccessStatusCode();
await response.Content.ReadAsStringAsync();
source: Request like browser Link1 Link2 Link3

Presigned PUT works from PostMan, but 403 Forbidden from C# HttpClient

I have generated a pre-signed url from S3 using the following .Net code (in a service that has the appropriate IAM role/permission for the bucket)
var key = GenerateKey(jobId, batchId);
var linkExpiresAt = _dateTimeService.Now().AddMinutes(_expiryTime);
var request = new GetPreSignedUrlRequest
{
BucketName = _bucketName,
Key = key,
Verb = HttpVerb.PUT,
ContentType = "application/json",
Expires = linkExpiresAt,
ServerSideEncryptionMethod = ServerSideEncryptionMethod.None
};
var url = _s3Client.GetPreSignedURL(request);
I can use this url in Postman to do a PUT with content 'JSON', but when I try to use it from code, I get 403
var content = new StringContent(mooStr, Encoding.ASCII, "application/json");
var fileStreamResponse = await httpClient.PutAsync(
url,
content);
Is there anything that stands out as wrong with the .Net attempt to PUT to the url?
If anyone comes across the same issue, I found the solution.
When I ran Fiddler, I captured the successful request from Postman and the failing request from .Net code. The only difference I could spot was that the successful one had this header (I'd changed to text/plain since my first post, but the problem remained):-
Content-Type: text/plain
and the failing one from .Net had:-
Content-Type: text/plain; charset=utf-8
A bit of a search around StackOverflow found me these posts
How to remove charset=utf8 from Content-Type header generated by HttpClient.PostAsJsonAsync()?
How do I not exclude charset in Content-Type when using HttpClient?
I edited the captured request in Fiddler and removed the charset and it worked. Altering my original code to the following worked (note - setting text/plain on the StringContent didn't work):-
var content = new StringContent(mooStr);
content.Headers.ContentType = MediaTypeHeaderValue.Parse("text/plain");
var fileStreamResponse = await httpClient.PutAsync(
Url,
content);
Following code worked for me (for posting a file of type IFormFile):
public async Task<bool> UploadObject(string preSignedUrl)
{
try
{
using (var client = new HttpClient())
{
StreamContent streamContent = new StreamContent(file.OpenReadStream());
var result = await client.PutAsync(preSignedUrl, streamContent);
if (result.StatusCode != HttpStatusCode.OK)
{
throw new Exception();
}
}
return true;
}
catch (Exception e)
{
....
}
return false;
}
Create the preSignedUrl with the IAmazonS3 package.

CSharp - How can I upload an image using a HTTP Request and Multipart as the Content-Type

I am using C# 4.7.2 and am using a Console and not WinForms. I am trying to get an input of a user's image path then send a post request to a ShareX Image Hoster API.
How can I keep it plain and simple using void? EX:
public static void UploadImg(string ImagePath, string UploadAPI, string UploadKey) { }
ShareX Config:
{
"Version": "13.2.1",
"Name": "host",
"DestinationType": "ImageUploader",
"RequestMethod": "POST",
"RequestURL": "https://ADDRESS/upload",
"Headers": {
"token": "name_RANDOMSTRING",
"json": "true"
},
"Body": "MultipartFormData",
"Arguments": {
"imgfile": null
},
"FileFormName": "imgfile",
"URL": "$json:url$"
}
Capturing traffic with Fiddler I can use these headers:
POST https://IMAGEHOST/api/upload HTTP/1.1
token: SPECIALKEY
json: true
Content-Type: multipart/form-data; boundary=--------------------8d8ee229124e662
User-Agent: ShareX/13.4.0
Host: IMGHOSTER
Content-Length: 7518
Connection: Keep-Alive
----------------------8d8ee229124e662
Content-Disposition: form-data; name="imgfile"; filename="851TO25E8.png"
Content-Type: image/png
Then the rest after these headers is unknown ascii bytes nonsense.
The response is:
{"url":"https://FinalShortenedURL/‌​​​‌‌​‌​‌‌​‌‌‌‌‌‌​​​‌​‌‌‌​​​​​‌​‌​‌‌‌‌‌​​‌‌‌‌​​‌‌‌‌​‌‌‌‌‌​​"}
UPDATE - .Net 4.7.2
public static async Task UploadImg(string ImagePath, string UploadAPI, string UploadKey)
{
using (var client = new System.Net.Http.HttpClient())
{
// TODO: implement auth - this example works for bearer tokens:
// client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", UploadKey);
// Or you could use simple headers:
client.DefaultRequestHeaders.Add("token", UploadKey);
// inject the JSON header... and others if you need them
client.DefaultRequestHeaders.Add("json", "true");
var uri = new System.Uri(UploadAPI);
// Load the file:
var file = new System.IO.FileInfo(ImagePath);
if (!file.Exists)
throw new ArgumentException($"Unable to access file at: {ImagePath}", nameof(ImagePath));
using (var stream = file.OpenRead())
{
var multipartContent = new System.Net.Http.MultipartFormDataContent();
multipartContent.Add(
new System.Net.Http.StreamContent(stream),
"imgfile", // this is the name of FormData field
file.Name);
System.Net.Http.HttpRequestMessage request = new System.Net.Http.HttpRequestMessage(System.Net.Http.HttpMethod.Post, uri);
request.Content = multipartContent;
var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode(); // this throws an exception on non HTTP success codes
}
}
}
The following is the original posted solution for .Net Core to upload using multi-part:
public static async Task UploadImg(string ImagePath, string UploadAPI, string UploadKey)
{
using (var client = new Windows.Web.Http.HttpClient())
{
// TODO: implement auth - this example works for bearer tokens:
client.DefaultRequestHeaders.Authorization = new Windows.Web.Http.Headers.HttpCredentialsHeaderValue("Bearer", UploadKey);
// Or you could use simple headers:
client.DefaultRequestHeaders.Add("token", UploadKey);
// Load the file:
StorageFile file = await StorageFile.GetFileFromPathAsync(ImagePath);
var uri = new System.Uri(UploadAPI);
HttpMultipartFormDataContent multipartContent = new HttpMultipartFormDataContent();
multipartContent.Add(
new HttpStreamContent(stream),
"imgfile", // this is the name of FormData field
file.Name);
Windows.Web.Http.HttpRequestMessage request = new Windows.Web.Http.HttpRequestMessage(Windows.Web.Http.HttpMethod.Post, uri);
request.Content = multipartContent;
var response = await client.SendRequestAsync(request);
response.EnsureSuccessStatusCode(); // this throws an exception on non HTTP success codes
}
}
The process is similar in .Net framework, except that you can use System.IO for file operations.
More Information
Having a quick snoop around SO will find many similar questions with similar solutions or pratical advice. This answer is specifically provided to work with OPs ShareX configuration, but if you need further information have a read over these articles:
Http MultipartFormDataContent
C# HttpClient 4.5 multipart/form-data upload
c# MultipartFormDataContent Add methods (how to properly add a file)

blazor httpClient.PostJsonAsync status code exception

When using the HTTP in Blazor client side it only works if the response is a success response, but if it is not found or bad response it gives exception and doesn't complete the code.
I want to parse the object I send in the response even if the request is not successful I mean 400 or 404, I send an object with error list so I need to get it.
It gives me error in the console that the request is not successful.
If I make the request to be (OK) then it works, but I need to send 400 status with the object "RequestResult" how I could manage this?
var result = await _httpClient.PostJsonAsync<RequestResult>("api/account/auth", authModel);
if (result.Successful)
{
await _localStorage.SetItemAsync("Token", authModel.SecurityToken);
AuthData.AuthToken= result.Token;
((ApiAuthenticationStateProvider)_authenticationStateProvider).MarkUserAsAuthenticated(result.Token);
_httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", result.Token);
return result;
}
return result;
and this is the controller code when i change BadRequest to Ok it work
public IActionResult Post([FromBody]AuthModel model)
{
var res = _authManager.SignInUser(model);
if (!res.Successful)
{
return BadRequest(new RequestResult { Successful = false, Errors = new List<string>() { res?.errors } });
}
return Ok(new RequestResult { Successful = true ,Token=res.access_token});
}
PostJsonAsync works this way. It will throw an exception if the content cannot be parsed. Here is a suggested workaround:
Required using statement: using System.Text.Json;
var response = await _httpClient.PostAsync("api/account/auth", authModel);
if (response.IsSuccessStatusCode)
{
//parse result as following
using (var sr = await response.Content.ReadAsStreamAsync())
{
var parsedResult = JsonSerializer.DeserializeAsync<RecipeDetailDto>(sr);
}
}
else
{
//If the bad request content/body is a json object
//parse error content
using (var sr = await response.Content.ReadAsStreamAsync())
{
//If the bad request content is a json
//var parsedErrorResult = JsonSerializer.DeserializeAsync<yourErroObjset>(sr);
}
//OR if the content is string
var errorResult = await response.Content.ReadAsString();
}
Did not testet it, but it should give you the context how to approach this.

Docusign REST API Call - "Boundary Terminator was not Found"

I am trying to call Docusign REST API as is outlined in the "Step 3: Send signature request on behalf of User 2" Section in this link. I get the following error below. What is the boundary supposed set to? How do I correctly set it?
{
"errorCode": "INVALID_MULTI_PART_REQUEST",
"message": "An error was found while parsing the multipart request. Boundary terminator '--BOUNDARY; charset=utf-8--' was not found in the request."
}
public static string HttpRequest(string url, List<CELPHttpHeader> headerList, EnvelopeDefinition envelopeDefination)
{
string responseString = string.Empty;
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Add("accept", "application/json");
MediaTypeHeaderValue mediaType = new MediaTypeHeaderValue("multipart/form-data");
NameValueHeaderValue item = new NameValueHeaderValue("boundary", "BOUNDARY");
mediaType.Parameters.Add(item);
JsonMediaTypeFormatter formatter = new JsonMediaTypeFormatter();
HttpRequestMessage requestMessage = new HttpRequestMessage();
requestMessage.Method = HttpMethod.Post;
requestMessage.Content = new ObjectContent<EnvelopeDefinition>(envelopeDefination, formatter, mediaType);
foreach (CELPHttpHeader header in headerList)
{
client.DefaultRequestHeaders.Add(header.Name, header.Value);
}
try
{
Task<HttpResponseMessage> webTaskResult = client.PostAsync(url, requestMessage.Content);
webTaskResult.Wait();
HttpResponseMessage response = webTaskResult.Result;
}
catch (Exception ex)
{
}
return (responseString);
}
A snippet of what the API request should look like is below:
--BOUNDARY
Content-Type: application/json
Content-Disposition: form-data
{
<JSON request here>
}
--BOUNDARY
Content-Type: application/pdf
Content-Disposition: file; filename="test1.pdf"; documentid=1
Content-Transfer-Encoding: base64
JVBERi0xLjUNJeLjz9MNCjMwMDIgMCBvYmoNPDwvTGluZWFyaXplZCAxL0wgMTM1
<snipped>
V1sxIDMgMF0+PnN0cmVhbQ0KaN5iYhRZU8PEwCDsBCQY1wMJpicAAQYAHeIDMQ0K
ZW5kc3RyZWFtDWVuZG9iag1zdGFydHhyZWYNCjEzNjA0NjUNCiUlRU9GDQo=
--BOUNDARY--

Categories

Resources