I have a very simple web api controller:
public class CarrinhoController : ApiController
{
[HttpPost]
public string Adiciona([FromBody] string conteudo)
{
return "<status>sucesso</status";
}
}
Now I'm running the server and trying to test this method via curl like this:
curl --data "teste" http://localhost:52603/api/carrinho
The request is arriving in my controller. However, the parameter conteudo always comes empty.
What am I doing wrong?
Thanks.
These posts explain similar problem in detail http://encosia.com/using-jquery-to-post-frombody-parameters-to-web-api/
On asp.net site http://www.asp.net/web-api/overview/formats-and-model-binding/parameter-binding-in-aspnet-web-api
When a parameter has [FromBody], Web API uses the Content-Type header to select a formatter. In this example, the content type is "application/json" and the request body is a raw JSON string (not a JSON object).
At most one parameter is allowed to read from the message body.
Add "Content-Type: application/json" on Fiddler will work.
Depending on the Content-Type you're sending determines how ASP.NET WebAPI binds parameters.
Try sending the following instead (form encoded)
conteudo=teste
Alternatively, if you don't want the binding to happen, you remove all parameters and read the posted data
var myContent = response.Content.ReadAsStringAsync().Result;
You need to name the parameter in the POST data to match the method parameter name. Change your curl data parameter to be this format:
parameter=value
For example:
curl --data "conteudo=teste" http://localhost:52603/api/carrinho
You might have an incorrect (malformed) request. WebAPI uses JSON serializer that ignores malformed request errors and just passes null through.
As an example,
Incoming json:
-
{
"MyProp":"<ASN xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"/>"
}
public class MyRequest
{
public string MyProp { get; set; }
}
Controller action:
[HttpPost]
[Route("inbound")]
[ResponseType(typeof(InboundDocument))]
public IHttpActionResult DoPost([FromBody]MyRequest myRequest)
{
if (myRequest == null) throw new ArgumentNullException(nameof(myRequest));//this line throws!
...
}
Related
I am using Postman to test my .NET 6.0 WebAPI.
When I try to process a form-data request, the WebAPI gets the original value of "parameter"
When I try to process a raw data request, the WebAPI gets the default value of "parameter"
This is the code of my .NET 6.0 controller:
[Route("[controller]")]
public class SiteInfoController : Controller
{
[HttpGet]
[AllowAnonymous]
[Route("Test")]
public IActionResult Test(int parameter)
{
return Ok($"response: {parameter}");
}
}
I added in Headers
Content-Type application/json
Accept application/json
but it didn't help me
Please help me to find the reason why form-data works (WebAPI can parse 1) but raw data does not (WebAPI receives 0, instead of initial 1) in .NET 6.0 WebAPI controller GET request.
You are trying to read an object from the body of a request. You must define said object and tell the framework where to read it from. And HttpGet can't have a body. You must use HttpPost or any other verb that can handle it:
[Route("[controller]")]
public class SiteInfoController : Controller
{
private sealed class MyParameter
{
public int Parameter { get; set; }
}
[HttpPost]
[AllowAnonymous]
[Route("Test")]
public IActionResult Test([FromBody] MyParameter parameter)
{
return Ok($"response: {parameter.Parameter}");
}
}
Make sure you change your PostMan script to use Post and not Get.
I'm working on service using ServiceStack (5.5.0) and ProxyFeature plugin. So this one (let me call it ProxyService) will work as proxy to other services. My problem comes when I'm trying to make proxy request with "POST", URL parameter and an empty body. How can I make this to run?
If I try it with not empty body, e.g. not with URL Parameter, everything is OK.
In one of those services I have something like
[Route("/data/changeitem/{Id}", "POST")]
public class ChangeDataItemForId : IItem, IReturnVoid
{
public string Id { get; set; }
public override string ToString()
{
return $"{nameof(ChangeDataItemForId)} {Id}";
}
}
in Proxy Service AppHost.Configure
Plugins.Add(new ProxyFeature(
matchingRequests: req => req.PathInfo.StartsWith("/data", StringComparison.OrdinalIgnoreCase),
resolveUrl: req => MyHost + req.RawUrl));
I get the following Error:
HTTP Error 411. The request must be chunked or have a content length.
Below is WebAPI action. On googling about the below error:-
The requested resource does not support http method 'POST'
I got number of links & updated my api accordingly but still I am getting the same error.
Web api not supporting POST method
ASP.NET Web Api: The requested resource does not support http method 'GET'
[AcceptVerbs("POST")]
[HttpPost]
[Route("rename/{userId}/{type}/{title}/")]
public IHttpActionResult Rename([FromBody] int userId, [FromBody] string type, [FromBody] string title)
{
//my api stuff
}
But still when calling the above via post man throws the error.
How do I get rid of this error??
Also is it possible to fix this without using [FromBody] attribute in the method parameters list?
Any help/suggestion highly appreciated.
Thanks.
You have declared route which requires url parameters
[Route("rename/{userId}/{type}/{title}/")]
So when you send request to api/customer/rename it does not match this method. You should remove parameters which you are passing in request body from route parameters
[Route("rename")]
Make sure that you have appropriate RoutePrefix("api/customer") attribute on your controller.
Second problem is multiple [FromBody] parameters. You will get can't bind multiple parameters error. There is limitation - you can mark only one parameter as FromBody. See Sending Simple Types notes:
Web API reads the request body at most once, so only one parameter of
an action can come from the request body. If you need to get multiple
values from the request body, define a complex type.
You should create complex type which will hold all parameters
public class RenameModel
{
public int UserId { get; set; }
public string Type { get; set; }
public string Title { get; set; }
}
And change method signature to
[HttpPost]
[Route("rename")]
public IHttpActionResult Rename(RenameModel model)
And send request data as application/x-www-form-urlencoded
[Route("rename/{userId}/{type}/{title}/")]
public IHttpActionResult Rename([FromBody] int userId, [FromBody] string type, [FromBody] string title)
The last answer is correct, you're asking for these parameters in the route, but saying that you expect them in the post body. Also, usually the route would begin with a noun rather than a verb. What is it you're renaming? (i.e. [Route("users/rename/{userId}/{type}/{title}")]
Based on your initial post, try this instead:
[HttpPost]
[Route("rename/{userId}/{type}/{title}" Name = "RenameUser"]
public IHttpActionResult Rename(int userId, string type, string title)
{
_myServiceMethod.Rename(userId, type, title);
return new StatusCodeResult(HttpStatusCode.Created, this);
}
Or, if you wanted to do a post with the info in the body:
Declare your data contract:
public class User
{
public string Type { get; set; }
public string Title { get; set; }
}
Then on the endpoint:
[HttpPost]
[Route("rename/{userId}", Name = "RenameUserPost")]
public IHttpActionResult RenameUserPost(int userId, [FromBody] User userData)
{
return new StatusCodeResult(HttpStatusCode.Created, this);
}
Note that in both returns 'this' refers to your controller class that inherits from ApiController. Verified both of these in swagger, and they accept POSTs and return status codes.
Hope this helps.
I had this error for wrong string in Route string on top of my action.
[Route("api/TestReaderPercentStudyHomework/AddOrUpdate")]
I looked up up the documentation for ASP.NET Web API parameter binding, they seem to have either fromURI and fromBody only. Is it possible to do both?
Here is some background info. I'm creating a webhook receiver/handler, where I have control over which URL is the webhook, but I do not have control over what the payload will be like until later stage of the workflow, so I need to take it in as JSON string first.
My hope is to be able to set up the route that can take in querystring and also Json string payload from HTTP POST. For example .../api/incoming?source=A.
If I understand correctly you're trying to use both the Post data from the body and some parameters from the URI. The example below should capture your "source=a" value from the queryString.
[Route("incoming")]
[HttpPost]
public IHttpActionResult Test([FromBody] string data, string source)
{
//Do something
return Ok("my return value");
}
Or you could use as below if you formatted your route as .../api/incoming/source/A.
[Route("incoming/{source:string}")]
[HttpPost]
public IHttpActionResult Test([FromBody] string data, string source)
{
//Do something
return Ok("my return value");
}
I need to receive some string and binary data using WebApi. I have created a controller this way:
[HttpPost]
public void Post(byte[] buffer)
{
// Some code goes here
}
Here's the routtings:
routes.MapHttpRoute(
name: "CuscarD95B",
routeTemplate: "D95B/{controller}",
defaults: new { buffer = RouteParameter.Optional },
constraints: new { controller = #"Cuscar" }
Now when I try to post some data, buffer is always byte[0] (zero length array). No data is being passed to the controller.
Any help would be appreciated.
Thanks.
If you are ever struggling with deserializing a body, try and do it manually to see if you are actually sending it correctly.
[HttpPost]
public void Post()
{
string body = Request.Content.ReadAsStringAsync().Result;
}
We passed Json object by HttpPost method, and parse it in dynamic object. it works fine. this is sample code:
ajaxPost:
...
Content-Type: application/json,
data: {"name": "Jack", "age": "12"}
...
Web API:
[HttpPost]
public string DoJson2(dynamic data)
{
string name = data.name;
int age = data.age;
return name;
}
If there is complext object type, you need to parse the dynamic type by using:
JsonConvert.DeserializeObject< YourObjectType >(data.ToString());
A complex data content sample is here, it includes array and dictionary object:
{"AppName":"SamplePrice","AppInstanceID":"100","ProcessGUID":"072af8c3-482a-4b1cāā-890b-685ce2fcc75d","UserID":"20","UserName":"Jack","NextActivityPerformers":{"39āāc71004-d822-4c15-9ff2-94ca1068d745":[{"UserID":10,"UserName":"Smith"}]}}
I was able to post a byte[] in my request body, and the value was successfully model bound. Was the content-type set? Note that simple string is considered to be valid JSON here, and so it should work if your request's content-type is set to application/json...
Having said that, you can simply have your POST method that expects a string from the body instead of a byte[] and set the content-type to be application/json:
[HttpPost]
public void Post([FromBody]string buffer)
{
// Some code goes here
}
I am not sure how to send byte[] to webApi, but what you can do is to pass the binary data as Base64 string to your controller and then convert the base64 string to the byte[].
I found the solution here.
Looks like we need to create custom MediaTypeFormatter to achieve primitive type deserialization.
Did you try to use the HttpPostedFileBase without [FromBody] ?
public void Post(HttpPostedFileBase buffer)
I had a similar situation where I was using a string array and it would always come through null or I would get an exception about an improperly formatted request. I added the annotation [FromUri] in my method parameters then it worked. To give a little more context, my controller method looked like this before:
public async Task<IHttpActionResult> MyControllerName(List<string> id)
After:
public async Task<IHttpActionResult> MyControllerName([FromUri] List<string> id)