get parameters from the request body along with a model - c#

how to get the devId from the body, even using [FromBody], it keeps identifying the devId as a query
public async Task<ActionResult<Module>> PostModule([FromBody]Module module, long devId){}

You can only have 1 argument with a FromBody applied.
From the documentation
Don't apply [FromBody] to more than one parameter per action method. Once the request stream is read by an input formatter, it's no longer available to be read again for binding other [FromBody] parameters.
If you want that devId being read from the body, you'll have to include that one as e.g. a property in your Module class.

Related

Difference between annotation and request object

I want to ask if there is a difference between the annotation [FromForm] and Request.Form. Is there a difference in the way they access the Request object? For reference this is the code
public IActionResult Test ([FromForm] IFormFile File1)
{
var File2 = Request.Form.File[0];
}
If there is a difference then how do you send the file in case of [FromForm] from a angular app.
The [FromForm] annotation merely tells the compiler that the value for argument "File1" should come from the request object's "form".
Here is the documentation:
https://learn.microsoft.com/en-us/aspnet/core/mvc/models/model-binding
FromQuery - Gets values from the query string.
FromRoute - Gets values from route data.
FromForm - Gets values from posted form fields.
FromBody - Gets values from the request body.
FromHeader - Gets values from HTTP headers.
Your action handler, "Test()", has "File1" as a parameter.
But "Test()" should also be able to read "File1" from the Request.Form object.
Different "abstractions" - same thing.

Read action parameters from JSON properties

How can I get the parameters of an ASP.NET Core MVC controller action from the properties of a JSON object that was sent in the HTTP request body?
If the request body contains form data and the content type is appropriate, the action method parameters are populated automatically as expected.
But nothing works if the POST data format is JSON and the content type is "application/json". I think this is quite common for API requests? I tried adding the [FromBody] attribute to all parameters, but the documentation says I can only apply that once. Well, I can write it multiple times and nobody complains, but neither helps. Even if I want to bind all the JSON to a single string parameter, it remains null.
Can ASP.NET Core actually handle JSON POST data? In the usual parameter binding comfort? Or are we down to the feature level of PHP (or below) when it comes to JSON requests? Should I not use such advanced technology and revert my client-side code to plain old HTTP form data instead?
I think I used this before and saw it working. But can't find out what the difference is here. Maybe it only works in controllers with the [ApiController] attribute? This case is a regular web page controller, not a separate API. But it needs to provide functions to JavaScript as well, so it does both.
I tried adding the [FromBody] attribute to all parameters
This sounds fishy to me. Are you trying to send your params as a json object and expecting them to get unwrapped into individual action params?
Consider the following data type and MVC controller endpoint:
public class Sample
{
public int Id { get; set; }
public string Name { get; set; }
}
[HttpPost]
public IActionResult Post([FromBody] Sample sample)
=> new JsonResult(sample);
This is all you need for a typical POST to an MVC controller. The key point is probably the type that I'm using to bind to the body. As you can see, I create a matching json object in Postman and it binds correctly and returns what I sent.
To get what you want, I think you'd have to rely on query params. (or some other technique I'm unaware of) Here's an example if you need it.
[HttpPost]
public IActionResult PostQuery([FromQuery] int id, [FromQuery] string name)
=> new JsonResult(new Sample {Id = id, Name = name});

What is the function of [FromBody] Attribute in C#?

Is there a function of [FromBody] attribute? I mean, when I use it for example:
public async Task SetUser([FromBody]User user)
and when I use:
public async Task SetUser(User user)
The server get the same object without problems, so, it's necessary set it, or I can remove it without worries?
Grettings!
User is a complex type, so by default the server will try to resolve it from the request body. If you had a simple type -- e.g.
public async Task SetUser(string userId)
the server would try to resolve the value via URL binding. You can override that behaviour by specifying
public async Task SetUser([FromBody] string userId)
I usually leave [FromBody] in the signature simply for the sake of readability.
There are two ways parameters can be passed to the server - via URI, or as part of the request body.
When data are passed in URI, they become query string - e.g. http://server.com/something?userId=5. This will be handled by the action method with int userId argument.
When data are passed in request body, then you cannot see them in the URI - it would be http://server.com/something, for example. Parameters are then passed as name-value pairs inside the request body.
However, in order to pass anything through body, there must be the body, and GET request normally doesn't have request body (it can have it, technically, but I'm not sure if it's used to pass parameters to GET action methods). You would usually expect arguments to be adorned with the FromBody attribute in POST action methods. Likewise, you would usually expect GET actions to receive arguments through URI, which is more in line with the purpose of the GET method.
You can specify either FromUri or FromBody to control behavior. There is also BindModel attribute which lets you define custom binding.

WebApi - UrlHelper.Route to GET with [FromUri] object parameter

I have an API action defined as the following:
[Route(Name="GetMembersTest"), HttpGet, ResponseType(typeof(MemberHeadersDto))]
public IHttpActionResult GetMembers[FromUri]MemberFilterDto filter, [FromUri]PagingOptionsDto paging)
This method works as expected, routing and all, requests are flowing through just fine. However, I'd like to supply a "NextUri" for paging so that the caller can just keep following NextUri until it is null to get all the results. I have to send back a uri to the same action, 1 page ahead, if that makes sense.
So I tried using UrlHelper.Route. This route is named "GetMembers" for the purpose of this example.
NextUri = Url.Route("GetMembers", new { filter, paging });
The problem is that instead of getting something like
/v1/members?filter.q=&filter.otherproperty=&paging.count=10&paging.startRow=11
I get
/v1/members?filter=WebApi.Models.MemberFilterDto&paging=WebApi.Models.PagingOptionsDto
It looks like UrlHelper.Route doesn't support complex types in the [FromUri] parameter of a GET Request. Is there anything I can do to get this functionality? My workaround right now is to take in all the Dto properties as individual parameters then build my Dtos from them on the server. This isn't ideal because if I ever add any more options I'd have to add more parameters to the action, which also makes the route value dictionary more fragile as well because it has to match with the method signature in UrlHelper.Route(routeName,routeValues).
Unfortunately, there is no way to pass in complex object to routing. Instead, you will need to pass in the simple properties individually.
I was not able to find a way to extend Url.Route, but that would be/have been your best option.

WebAPI routing to a function with multiple optional parameters

I have the following function header in WebAPI controller declared as route:
[Route("page/{page}/{cityfilter?}/{statefilter?}/{organizationfilter?}")]
public IEnumerable<Contact> GetContact(int page, string cityfilter = null, string statefilter = null, string organizationfilter = null)
{
...
}
The issue here is that I'd wish that every parameter is optional, so I'd want to make a request that has either a cityfilter, a statefilter, an organization filter, two of them or three of them, and then be processed and router by this function, but I have no clue about how I can build the URI so that, for instance, this route works for just the statefilter.
How can I do that in WebAPI? How should I call the resource address from, for instance, a Jquery Ajax call?
Thank you.
Since the parameters are simple types (strings), they can be bound either from the route data (URL path) or the query string. So you can move the optional parameters to the query string and have your route only match the page parameter.
[Route("page/{page}")]
Here's an example of a URL that you would use to call this action from the browser or from an AJAX call:
www.yourapidomain.com/page/1?cityfilter=aCityFilterString&statefilter=aStateFilterString&organizationfilter=anOrganizationFilter
You may of course omit any of the optional parameters or change their order.
The action method signature can remain as it is in your example.
For more information, you can have a look at parameter binding ASP.NET Web API.

Categories