Post using HttpClient & Read HttpResponseMessage status - c#

I am posting to an API using HttpClient and getting back the HttpResponseMessage.
I am reading the status code from the reply but I it's always 200
Posting:
var json = JsonConvert.SerializeObject(loginDto);
var stringContent = new StringContent(json, Encoding.UTF8, "application/json");
var client = new HttpClient();
var response = await client.PostAsync("http://localhost:57770/api/Account/Login", stringContent);
I am replying from API the HttpResponseMessage:
return new HttpResponseMessage(HttpStatusCode.Unauthorized);
But when I read the response, it's always 200
How can I achieve this?

Asp.Net Core no longer recognizes HttpResponseMessage as part of the pipeline. This means it will be treated like any other returned model and serialized as content. Hence the 200 OK status.
The API controller action should return IActionResult derived result.
[HttpPost]
public IActionResult SomeAction(...) {
//...
return StatusCode((int)HttpStatusCode.Unauthorized); //401
//...
}
Or just use
return Unauthorized();
which is derived from StatusCodeResult and is used a short hand to replace the code shown above.
Reference ControllerBase.Unauthorized.

Related

Receiving json as string always null

With an endpoint like this:
[HttpPost("[action]")]
public async Task<ActionResult> Import([FromBody]string request)
{
var list = JsonConvert.DeserializeObject<List<RequestQuote>>(request);
return NoContent();
}
request always seems to be null. It worked for a little while earlier today but not sure what changed.
Here is the client side where I do the call.
var json = JsonConvert.SerializeObject(payload);
var data = new StringContent(json, Encoding.UTF8, "application/json");
var response = client.PostAsJsonAsync($"{endpoint}/api/v1.0/BatchImport/Import", data);
Payload is a List
Even when using
Import([FromBody] List<RequestQuote> request)
I get the same issue.
There is a bug in the code, the data is serialized twice, the second time when you use PostAsJsonAsync. Try this
var json = JsonConvert.SerializeObject(payload);
var data = new StringContent(json, Encoding.UTF8, "application/json");
var response = await client.PostAsync($"{endpoint}/api/v1.0/BatchImport/Import", data);
if (response.IsSuccessStatusCode)
{
var stringData = await response.Content.ReadAsStringAsync();
var result = JsonConvert.DeserializeObject<object>(stringData);
}
and action should be
public async Task<ActionResult> Import([FromBody] List<RequestQuote> request)
If your controller has the [ApiController] attribute, you can put the data type you want to parse as the parameter of the method. I believe what is happening is that your program is trying to parse the JSON to a string type, which isn't what you want. You can try the code below, which should achieve what you're looking for.
[HttpPost("[action]")]
public async Task<ActionResult> Import([FromBody]List<RequestQuote> list)
{
// The parsed object should now be available here as "list"
return NoContent();
}
Alternatively, this post suggests pulling the body of the request directly. Either solution should be valid.

API HTTP client returning data

I am working on this helper method that will call an API using the body section. I am passing in the url and data in the model. Then I SerializeObject the model, but I am not sure what to return I get the error message about the response.Content is not found.
public static async System.Threading.Tasks.Task<HttpResponse> HttpClientHandlerAsync(string url, object model)
{
var fullUrl = apiUrl + url;
var json = JsonConvert.SerializeObject(model);
var data = new StringContent(json, Encoding.UTF8, "application/json");
Client.DefaultRequestHeaders.Add("Accept", "*/*");
Client.DefaultRequestHeaders.Authorization
= new AuthenticationHeaderValue("Bearer", "token");
var response = await Client.PostAsync(fullUrl, data);
return response;
}
Add await in front of your
await Client.PostAsync(fullUrl, data);
Because you're trying to get content of Task
I am not sure what to return I get the error message about the response.Content is not found.
Set a breakpoint and hover over the response to see the status code. You could have a 500 server error, authentication error etc.
Furthermore
using (var client = new HttpClient())
Do not do this. It doesn't work the way you think it does, it will starve your connection pool and eventually throw an exception. You need to define the HttpClient somewhere and continue to reuse the same instance.
Further reading if you care https://aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/

c# webapi post() and post([FromBody])

I'm building an webapi in c# to be called by an outside server.
let's say my API address is www.server.com/webapi/service1
when I set the address above in the app that will use it, it sends a simple POST with an empty body to service1 and waits for a specific KEY as response (in body), like an authentication. ok.
the same service1 can be called, using POST too, passing a raw JSON in the body, and I'm using the [FromBody] attribute to get the body and process.
I tried this to manage the empty POST call and the call with body data:
[HttpPost]
[Route("webapi/service1")]
public HttpResponseMessage Post()
{
var resp = new HttpResponseMessage(HttpStatusCode.OK);
resp.Content = new StringContent(TokenKey.ToString(), System.Text.Encoding.UTF8, "text/html");
return resp;
}
[HttpPost]
[Route("webapi/service1")]
public async Task<HttpResponseMessage> Post([FromBody] RetornoChat retornoChat)
{
await closedChat(retornoChat); //process body
return resp;
}
but it was not working.I manage a workaround like the code below, I check if the class in [FromBody] is empty, if this is the case return the special string to validate and finish, if there is a body then get the data validate and process. I'm wondering if there is a better solution.
I really thought that the solution was to double the post method and when there was a body it would call the post with the [frombody] and when there is no body it would go to the empty post.
[HttpPost]
[Route("webapi/service1")]
public async Task<HttpResponseMessage> Post([FromBody] RetornoChat retornoChat)
{
var resp = new HttpResponseMessage(HttpStatusCode.OK);
resp.Content = new StringContent(TokenKey.ToString(), System.Text.Encoding.UTF8, "text/html");
if (retornoChat == null)
{
}
else
{
//get the body data and process
}
return resp;
}
Thanks in advance for your time!

How to set HttpResponse to HttpResponseMessage in Web API

I have a asp.net web API application hosted using OWIN. The web API application uses an external library which depends on System.Web and writes its response on System.Web.Response object. I have set a dummy object to HttpContext.Current and after that the I expect the external library would set the response at HttpRequest. Then I need to know how I could transfer the result from HttpRequest to HttpRequestMessage so that the web API method could process the result.
Here is some sample code:
public HttpResponseMessage GetTest()
{
HttpResponseMessage responseMessage = new HttpResponseMessage();
HttpResponse httpResponse = new HttpResponse(new StreamWriter(new MemoryStream()));
httpResponse.Write("From HttpResponse");
return responseMessage;
}
I have written some text using the HttpResponse.Write() method, now I need to move the result from HttpResponse to HttpResponseMessage.
I believe what you are looking for is IHttpActionResult see link:
https://learn.microsoft.com/en-us/aspnet/web-api/overview/getting-started-with-aspnet-web-api/action-results
Here is an example of how to create a HttpResponseMessage:
public IHttpActionResult Get()
{
HttpResponseMessage responseMessage = "From HttpResponse";
return new ResponseMessageResult(responseMessage);
}
Try:
return Request.CreateResponse(HttpStatusCode.OK, "{data to return here}")
You can try like below:
if (yourCondition)
{
return Request.CreateResponse<Employee>(HttpStatusCode.OK, obj);
}
else
{
return Request.CreateErrorResponse(HttpStatusCode.NotFound, "Not Found");
}

Making an async HttpClient post request with data from FormCollection

I am doing an Asp.Net MVC 4 project and am looking to an internal request (like a proxy) to our api service.
This is what the index method looks like in my controller. I'm stuck at the PostAsync part.
[HttpPost]
public async Task<ActionResult> Index(FormCollection body){
HttpClient httpClient = new HttpClient();
httpClient.BaseAddress = new Uri("http://myapi.com");
// posts to http://myapi.com/users
var response = await httpClient.PostAsync("users", body);
if(response.isSuccessStatusCode) return Json(new {
status = true,
url = response.Content.Url
});
}
I want to pass my "application/x-form-urlencoded" "body" content to the PostAsync POST method. However, I get an error reading "body is not of type HttpContent".
I can't cast or convert. What now?
Let me know what I'm doing incorrectly here.
Erik
I'm not entirely sure what you're trying to do, but possibly converting the FormCollection to a dictionary and using the FormUrlEncodedContent class is what you're looking for.
e.g.:
var response = await httpClient.PostAsync("users",
new FormUrlEncodedContent(
body.
AllKeys.ToDictionary(
k => k, v => body[v])));

Categories

Resources