Error using HttpClient in dotnet function - c#

I am trying to create an advert but everytime it gives an error at this line:
var response = await _client.PostAsync(new Uri($"{_baseAddress}/Create"),
new StringContent(jsonModel, Encoding.UTF8, "application/json")).ConfigureAwait(false);
I Added a breakpoint and it stops creating the response. Bellow is my function that i use
var advertApiModel = _mapper.Map<AdvertModel>(model);
var jsonModel = JsonConvert.SerializeObject(advertApiModel);
var response = await _client.PostAsync(new Uri($"{_baseAddress}/Create"),
new StringContent(jsonModel, Encoding.UTF8, "application/json")).ConfigureAwait(false);
var createAdvertResponse = await response.Content.ReadAsAsync<CreateAdvertResponse>().ConfigureAwait(false);
var advertResponse = _mapper.Map<AdvertResponse>(createAdvertResponse);
return advertResponse;
The error that terminal outputs is:
info: System.Net.Http.HttpClient.IAdvertApiClient.LogicalHandler[100]
Start processing HTTP request POST http://localhost:5000/adverts/v1/Create
System.Net.Http.HttpClient.IAdvertApiClient.LogicalHandler: Information: Start processing HTTP request POST http://localhost:5000/adverts/v1/Create
info: System.Net.Http.HttpClient.IAdvertApiClient.ClientHandler[100]
Sending HTTP request POST http://localhost:5000/adverts/v1/Create
System.Net.Http.HttpClient.IAdvertApiClient.ClientHandler: Information: Sending HTTP request POST http://localhost:5000/adverts/v1/Create
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
Request starting HTTP/1.1 POST http://localhost:5000/adverts/v1/Create application/json; charset=utf-8 76
Microsoft.AspNetCore.Hosting.Diagnostics: Information: Request starting HTTP/1.1 POST http://localhost:5000/adverts/v1/Create application/json; charset=utf-8 76
Microsoft.AspNetCore.Hosting.Diagnostics: Information: Request finished in 5.2898000000000005ms 404
When I hover over var response after it passes it it shows this error:
{StatusCode: 404, ReasonPhrase: 'Not Found', Version: 1.1, Content: System.Net.Http.HttpConnectionResponseContent, Headers:
{
Date: Fri, 17 Jan 2020 13:30:02 GMT
Server: Kestrel
Content-Length: 0
}}

Related

Jira API Help C# HttpClient

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.

Authorizing AD Group\User With HttpClient

I'm getting a 401 error whenever I attempt to get a response from HttpClient when I turn off Anonymous Authentication.
StatusCode: 401, ReasonPhrase: 'Unauthorized', Version: 1.1,
Content: System.Net.Http.StreamContent, Headers:
{
X-SourceFiles: =?UTF-8?B?QzpcVXNlcnNcUGFycmlzaFxEb2N1bWVudHNcJ0xSXFNvdXJjZVxBcHBzXExSUiBBRkVcTFJSX0FGLVxhcGlcYWZlXDg0QTk0NjVFQzg2QTQwQjNBNEJCNkJDOTI3MTFGRjNB?=
Cache-Control: private
Server: Microsoft-IIS/10.0
WWW-Authenticate: Negotiate
WWW-Authenticate: NTLM
X-Powered-By: ASP.NET
Date: Mon, 27 Aug 2018 18:14:05 GMT
Content-Length: 6166
Content-Type: text/html; charset=utf-8
}
For testing I have the controller Authenticating on a single user.
[Authorize(Users = #"Domain\Username")]
public class ExampleController : Controller
{
public async Task<ActionResult> Index(string exampleId)
{
var baseUrl = $"{Request.Url.Scheme}://{Request.Url.Authority}{Url.Content("~")}";
var client = new HttpClient(); // <-- This is WRONG*
var response = await client.GetAsync($"{baseUrl}api/example/{exampleId}");
var example = await response.Content.ReadAsAsync<ExampleModel>();
return View(example);
}
}
I've looked into using HttpClient.DefaultRequestHeaders.Authentication, but I don't see a way to get it to work with ActiveDirectory. I've looked here but can't understand where I'd be getting an authorization token in this case.
If I create a new controller manually and invoke it directly instead of through the API this works, but it really isn't authenticating anything in that case right?
*Edit:
As ADyson points out, my error was not initializing the HttpClient correctly. Here is how it should have been written:
var client = new HttpClient(new HttpClientHandler() { UseDefaultCredentials = true });
You need to set UseDefaultCredentials = true (in an instance of HttpClientHandler, which you pass to the HttpClient).

MultipartContent response in Web API

I want to have a possibility to return complex response for requests in Web API. For example I want to return stream with some complex object.
I tried to do it with MultipartFormDataContent:
public static HttpResponseMessage GetMultipartResponse<T>(T responseData, Stream streamToReturn)
{
return new HttpResponseMessage
{
Content = new MultipartContent
{
new StreamContent(streamToReturn),
new ObjectContent<T>(responseData, new JsonMediaTypeFormatter())
}
};
}
I've got a normal HttpResponseMessage on server side. I can see by debugger how my Web API method returns this response, but on the client side I've got an error:
StatusCode: 500, ReasonPhrase: 'Internal Server Error', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
Pragma: no-cache
X-SourceFiles: =?UTF-8?B?YzpcdXNlcnNccnVzdGFtX3NhbGFraHV0ZGlub3ZcZG9jdW1lbnRzXHZpc3VhbCBzdHVkaW8gMjAxM1xQcm9qZWN0c1xGaWxlU2VydmljZUFQSVxGaWxlU2VydmljZUFQSVxhcGlcZ2V0?=
Cache-Control: no-cache
Date: Tue, 26 Jul 2016 08:30:22 GMT
Server: Microsoft-IIS/8.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Content-Length: 1444
Content-Type: application/json; charset=utf-8
Expires: -1
}
There is no other exceptions on client or server side and i can't get some more information with turn on error detail:
config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;
UPDATE:
Try to read response on client side with:
var result = await response.Content.ReadAsMultipartAsync();
And got this exception:
Invalid 'HttpContent' instance provided. It does not have a content type header starting with 'multipart/'.
Where do I go wrong?
UPDATE 2:
I have normal response on the server side:
StatusCode: 200, ReasonPhrase: 'OK', Version: 1.1, Content: System.Net.Http.MultipartContent, Headers:
{
Content-Type: multipart/multipart; boundary="3e6d3573-9031-41a7-b7f4-d1421bc1451d"
}
I found the error. I return my multipart content inside using:
using (var stream = MyFileStream())
{
var respone = MultipartResponseHelper.GetMultipartResponse(response, stream, Request);
return respone;
}
So it returns right response, but then stream inside multipartContent will disposed which is the reason of problem.

Capture response information from (3rd party) web service on error

I have the following code, which submits XML to a 3rd party web service, which errors (intentionally, at the moment) on "req.GetResponse()" with the error, detailed below.
byte[] bytes = Encoding.ASCII.GetBytes(myXMLData);
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(myWebsite);
using (Stream os = req.GetRequestStream())
{
os.Write(bytes, 0, bytes.Length);
}
WebResponse response = req.GetResponse();
string responseStream = StringFromResponseStream(response);
Error from GetResponse()
Exception thrown: 'System.New.WebExtension' in System.dll
Additional information: The remote server returned an error: (400) Bad Request
When I trace this call in Fiddler, I can see that the response from the service, also includes a far more useful error (below; RAW view), which I am trying to get to:
HTTP/1.1 400 Bad Request
Date: Thu, 16 Jun 2016 10:42:26 GMT
Cache-Control: private
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
Content-Type: text/plain; charset=UTF-8
Content-Length: 54
Caseprovider-Credentials: <snip>
Caseprovider-Credentialshash: <snip>
Caseprovider-Apiversion: 15
Connection: close
No supported action 'SomeName' available for 'SomeValue'
Having a 'watch' on the variables doesn't seem to show where I might obtain this from (and quite possibly something simple that I have overlooked)
Have eventually found a resolution for the; where 'result' contains the content from the process; there's more to do, but this is the basics of what I needed.
using (var httpClient = new HttpClient())
{
httpClient.BaseAddress = new Uri(myWebSite);
httpClient.DefaultRequestHeaders.Accept.Clear();
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("text/xml"));
StringContent stringContent = new StringContent(myXMLData);
stringContent.Headers.ContentType = new MediaTypeHeaderValue("text/xml");
HttpResponseMessage httpResponseMessage = httpClient.PostAsync(httpClient.BaseAddress, stringContent).Result;
string result = httpResponseMessage.Content.ReadAsStringAsync().Result;
}

Batch request - Dynamics CRM

All,
I am trying to implement a batch request to Dynamics CRM with the following source code:
public async Task<HttpResponseMessage> HttpPatchCrmApi(string resource, string data)
{
string uniq = Guid.NewGuid().ToString();
MultipartContent content = new MultipartContent("mixed", "batch_" + uniq);
HttpRequestMessage batchRequest = new HttpRequestMessage(HttpMethod.Post, CrmBaseUrl + "/api/data/v8.0/$batch");
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, CrmBaseUrl + resource);
request.Content = new StringContent(data, Encoding.UTF8, "application/json");
HttpMessageContent query = new HttpMessageContent(request);
content.Add(query);
batchRequest.Content = content;
HttpResponseMessage response = await RbWebApi.SendAsync(batchRequest);
return response;
}
The problem is that I am getting "400 Bad request"
EDIT:
As suggested in the comments here is the stack trace of the request from fiddler:
POST https://Hidden.api.crm4.dynamics.com/api/data/v8.0/$batch HTTP/1.1
Authorization: Bearer eyJ0eXAiOiJKV.... very long string
Content-Type: multipart/mixed; boundary="batch_7b6e3c60-1284-4958-a39a-4653af21833c"
Host: Hidden.api.crm4.dynamics.com
Content-Length: 313
Expect: 100-continue
--batch_7b6e3c60-1284-4958-a39a-4653af21833c
Content-Type: application/http; msgtype=request
POST /api/data/v8.0/my_recurringgifts HTTP/1.1
Host: Hidden.api.crm4.dynamics.com
Content-Type: application/json; charset=utf-8
{"my_name":"slavi"}
--batch_7b6e3c60-1284-4958-a39a-4653af21833c--
While writing the code I was inspiring myself from here and here
I think your request is wrong.
You must build the request Body EXACTLY like defined by Microsoft
This means the Blank lines must be there at the right place all the attributes must exist in the body (like "--changeset_XXX" for example) and as I see you dont meet this requirements.
I just build a Request in Postman against my CRM and it worked:
URL
https://yourTenant.api.crm.dynamics.com/api/data/v8.0/$batch
Headers
OData-MaxVersion:4.0
OData-Version:4.0
Accept:application/json
Authorization:Bearer aVeryLongStringTokenHere
Content-Type: multipart/mixed;boundary=batch_1234567
Body
--batch_1234567
Content-Type:multipart/mixed;boundary=changeset_555666
--changeset_555666
Content-Type:application/http
Content-Transfer-Encoding:binary
Content-ID:1
POST https://yourTenant.api.crm.dynamics.com/api/data/v8.0/accounts HTTP/1.1
Content-Type:application/json;type=entry
{name: 'BatchJobTest788'}
--changeset_555666
Content-Type:application/http
Content-Transfer-Encoding:binary
Content-ID:2
POST https://yourTenant.api.crm.dynamics.com/api/data/v8.0/accounts HTTP/1.1
Content-Type:application/json;type=entry
{new_name: 'BatchJobTest348'}
--changeset_555666--
--batch_1234567--
Additional Remarks:
The Content-Type of your Header holds your BatchId
The Content-Type of your Batch holds your ChangesetId (if it is a change to data)
Before starting to programm REST calls try to define them in a REST tool like POSTMAN and make them work. Then build the working request in your code.
Here a good explanation-source for the batching in CRM

Categories

Resources