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)
Related
I'm trying to pass some JSON on the querystring of a GET request to an MVC controller, but can't seem to get it to come through as anything other than null.
Ajax (through TypeScript)
$.ajax(url, {
method: 'GET',
data: { 'request': JSON.stringify(this.request) },
dataType: 'json'
})
MVC Controller
[Route("stuffAndThings/{request?}")]
public async Task<HttpResponseMessage> GetStuff(requestType request)
{
}
Because this is TypeScript, the object being passed is the TypeScript representation of the C# model, including several custom objects
TS class
class requestType {
pageData: PageData;
}
C# class
public class requestType
{
public PageData pageData { get; set; } = new PageData();
}
Looking at the request in devtools, it appears to be being passed correctly on the querystring, but always comes through on the controller as null.
What am I missing?
EDIT
To address a couple of comments, the controller method is purely for data retrieval, and does have the potential in the future to be turned into a WebAPI method, so I would like to keep it as a GET request if possible.
In MVC controller you will get the parameter as string because you have passed parameters as string through GET request
[Route("stuffAndThings/{request?}")]
public async Task<HttpResponseMessage> GetStuff(string request)
{
}
Make requestType class serializable,
now in your method you have to deserialize the json string into your object
using (var ms = new MemoryStream(Encoding.Unicode.GetBytes(request)))
{
DataContractJsonSerializer deserializer = new DataContractJsonSerializer(typeof(requestType));
requestType requestObj = (requestType)deserializer.ReadObject(ms);
//your code here
}
Json.Stringfy convert your request in string form, and in controller your are fetching with particular type. So, to get the proper result update with strin g instead of RequestType.
if still face issue you reach out to me.
I am here
Please response or like if its helpful.
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 am a newbie to C# am trying to post an array of values to a webapi POST method. Not sure how to go about this. This is what I have so far:
In the controller class:
namespace SATLyncWebService.Controllers
{
[RoutePrefix("lync")]
public class LyncController : ApiController
{
// POST: lync/search/
[HttpPost]
[Route("search")]
public void Post([FromBody]string value)
{
log.Info(value.ToString());
}
}
I get a NullReferenceException on the value field when I send a POST message as follows:
POST http://localhost:55129/lync/search
Application/json
["user1",
"user2 "
]
Thoughts?
I think that's because your signature is taking a single string as opposed to an IEnumerable (or any other sort of collection - List, []...) therefore webapi can't deserialize into that type
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 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!
...
}