Currently I have 3rd party WebApi which has the following external call using Flurl builder.
await _client.Url.ToString().PostJsonAsync(data);
And I'm trying to handle the response with such endpoint:
[HttpPost]
public void HandleResponse(HttpResponseMessage response)
{
}
The response message is with status OK but has Content and Headers = null
How can I handle this properly?
This API endpoint doesn't make any sense to me:
[HttpPost]
public void HandleResponse(HttpResponseMessage response)
{
//...
}
The endpoint would be handling a request and returning a response, not the other way around. Something more like this:
[HttpPost]
public HttpResponseMessage HandleResponse(HttpRequestMessage request)
{
//...
}
When something contacts an API (or server of any kind, really), it's sending a request to that API. That API receives the request and returns a response. The semantics of these two words pretty much describe the process, it's very important to keep them straight.
Consider it like this... If someone asks you a question, what you receive is a question. Not an answer. What you send back to that person is the answer.
Related
I'm new to writing .net APIs and I'm working in Visual Studio 2017. I've been working on this for a couple of days and I'm completely stumped. I'm trying to create a simple web API that a Post call sends a cXML string passed into it via the Post Body. I then take the incoming cXML string and simply save it to a text file on a network drive. That is all I need to do, I don't need to de-serialize the xml, read any of the fields or extract any data out of the XML, I just need to grab the entire input xml string and save it to a text file. The problem I'm having is no matter what I've tried the incoming body always seems to be null. My code is simple:
[HttpPost]
[Route("api/Pass_XML_to_File")]
public HttpResponseMessage Post([FromBody] dynamic IncomingXML)
{
//do work here: take Incoming xml string and save it to a file which should be simple...
}
Unfortunately my IncomingXML variable is always null, so I have no data to save into a text file. I've been testing this from Postman and no matter what I've tried the variable is always null.
I've tried many other ways such as
Post([FromBody] XmlDocument IncomingXML)
Post([FromBody] string IncomingXML), etc.
I've tried changing in Content-Type header in Postman from application/xml, text/xml, text and a few others without any success. The funny thing is if I pass a JSON string in the body (changing the Content-Type to text/JSON) the data comes in perfectly without issue. Just when I pass xml the incoming body is always null.
Does anyone know how I can get the body xml to come in as a string so I can simply save it to a text file for later processing on a separate system? Thank you all in advance for your assistance.
Can you post the form you sent on the client side?
[HttpPost]
[Route("api/Pass_XML_to_File")]
public HttpResponseMessage Post([FromBody] dynamic IncomingXML)
{
// data is coming in correctly.
return null;
}
Postman Client Send :
{
"IncomingXML":"<note><to>Tove</to><from>Jani</from><heading>Reminder</heading><body>Don'tforgetmethisweekend!</body></note>"
}
data comes to variable successfully.
if you want to accept a xml format request, you should do the below steps:
Startup.ConfigureServices edit:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers()
.AddXmlSerializerFormatters();
}
Apply the Consumes attribute to controller classes or action methods that should expect XML in the request body.
[HttpPost]
[Route("api/Pass_XML_to_File")]
[Consumes("application/xml")]
public HttpResponseMessage Post([FromBody] dynamic IncomingXML)
{
// data is coming in correctly.
return null;
}
Note: Install the Microsoft.AspNetCore.Mvc.Formatters.Xml NuGet package.
First of all, my English is not so good, I hope you understand what I am trying to say.
I'm new with WebApi's. I created one and all seems good. In my function I return a string, but when I test the web api with Postman it returns a status code 204 no content.
I looked for this status and apparently my request was succeded, but when I look at my database nothing happend. (my function saves some data in my database and returns a string when it is succeded or not).
So, my question is, Why am I receiving this status code when my function must to return a string? Or why when I test the Web Api with Postman it returns a 204 No Content code (that means my request was succeded) when is not true (because nothing was saved in my database)?
Here is my function in my web api:
[HttpPost]
public string IncomingPO(string request)
{
//do some stuff
return "response as a string";
}
My parameter "string request" is a string that cointains a xml. I read the string as a xml and do some stuff with it. (save some nodes from the xml in a database, for example).
If all the function is succeded or not I expect the output of my string, but I'm no receiving anything. Only the status code 204 No Content. (when content should really be returned).
Any suggestion is welcome.
It can solve my problem.
The only thing I had to do was specify the route with which my Api website will be invoked.
In addition I also had to modify the data type of my parameter and my function.
Something like this:
[HttpPost]
[Route("api/Controller/IncomingPO")]
public HttpResponseMessage IncomingPO(HttpRequestMessage request)
{
//do some stuff
return new HttpResponseMessage()
{
Content = new StringContent("My response string", System.Text.Encoding.UTF8, "application/xml"),
StatusCode = HttpStatusCode.OK
};
}
I have two ASP.NET Core 2.1 apps and I'm trying to make a simple POST call from one app to the other using HttpClient.
For some reason, when I use [FromBody] to get the simple text I'm trying receive, I get a BadRequest error.
Here's my code on the sender. First, this is what's in my ConfigureServices method. I'm using the new HttpClientFactory feature in ASP.NET Core 2.1. I also created a client class named myApiCallerClient that handles my API calls:
services.AddHttpClient("myNamedClient", client =>
{
client.BaseAddress = new Uri("http://localhost:50625/api/");
client.DefaultRequestHeaders.Clear();
client.DefaultRequestHeaders.Add("Accept", "application/json");
});
services.AddScoped(x => {
var httpClientFactory = x.GetRequiredService<System.Net.Http.IHttpClientFactory>();
var myApiCallerClient = httpClientFactory.CreateClient("myNamedClient");
return new Clients.ApiCaller.ApiCallerClient(myApiCallerClient);
});
Here's the code in myApiCallerClient:
public async Task SayHello()
{
var response = await _httpClient.PostAsync("test", new StringContent("Saying hello!", System.Text.Encoding.UTF8, "text/plain"));
}
And here's my code on the receiving end which is the POST() API method in TestController:
[HttpPost]
public async Task Post([FromBody]string input)
{
// Some logic
}
My call doesn't hit this method if I use [FromBody] and I get BadRequest error on the sender. If I use [FromHeader] my request hits this API method but I'm getting a null value.
What am I doing wrong here?
ASP.NET Core doesn't support a Content-Type of text/plain out of the box, so the server is rejecting your request as it's not something that it can parse when using the [FromBody] attribute.
In the comments, you said:
Ultimately I won't be sending text. My main concern here is that I'm not hitting my API method. [...] Once I make sure everything is working, I'll be sending JSON data which will get deserialized on the receiving end.
In order to test whether the problem is due to the text/plain Content-Type, you can update your PostAsync line to something like this:
var response = await _httpClient.PostAsync(
"test",
new StringContent("\"Saying hello!\"", System.Text.Encoding.UTF8, "application/json"));
As application/json is a supported Content-Type by default, the code above uses that and wraps the value you were sending with "s in order to make it a valid JSON value.
I am testing an ASP.NET MVC application. There is a contoller with a method that looks like:
[HttpPost]
public async Task<ActionResult> Login(LoginForm loginForm)
{
// Do some work
return RedirectToAction(nameof(Admins));
}
The signature of Admins method looks like:
public async Task<ActionResult> Admins(ExtendedPagingForm form)
and I try to invoke it like this:
var url = $"{TestConfig.Instance.ServerUrl}/{actionMethod}";
var sendForm = GetFormContent(new MultipartFormDataContent(), sendData); //login and password
HttpResponseMessage response = await httpClient.PostAsync(url, sendForm);
The response contains Internal server error with info:
IOException: Unexpected end of Stream, the content may have already
been read by another component.
On MSDN it is said that RedirectToAction returns an HTTP 302 response to the browser, which causes the browser to make a GET request to the specified action. So it must not work neither in browser, nor in Postman, but it works fine there. Can I force my httpClient to send POST request with data or some mock request body?
I've solved the problem.
I changed MultipartFormDataContent to FormUrlEncodedContent and it works
In my case I was already using FormUrlEncodedContent but it was still happening. Mine was a Xamarin project.
Restarting Visual Studio and Emulator helped me.
I'm trying to figure out the new ASP.NET Web API.
So far I've been able to create this method signature and connect to it just fine and get a valid response...
[HttpPost]
public HttpResponseMessage CreateAccount()
I am able to send a request to this method with fiddler and have verified that it is receiving the request.
However, when I try to pass data is when I am running into a problem.
The first thing I tried was...
[HttpPost]
public HttpResponseMessage CreateAccount([FromBody]string email, [FromBody]string password)
And I type
email:xyz,password:abc
into the body of the request in fiddler. When I do this I get a 500 error stating
'Can't bind multiple parameters ('email' and 'password') to the request's content.'
I have also tried this as a method signature...
[HttpPost]
public HttpResponseMessage CreateAccount([FromBody]UserAccountRequestData data)
with the UserAccountRequestData being a simple POCO
public class UserAccountRequestData
{
public string Email { get; set; }
public string Password { get; set; }
}
And I put
{Email:xyz,Password:abc}
or
data:{Email:xyz,Password:abc}
into the body of the request. In both cases trying to populate the POCO I am able to reach the method while debugging, but the data object is always null.
I need to understand how to create API methods that accept both strongly typed POCOs and others that accept multiple primitive types like strings and ints.
Thanks
You need to set the Content-Type header to application/json and then provide valid JSON.
{"Email":"xyz","Password":"abc"}