API with optional query string is losing the route value - c#

I want to have a WebAPI path that takes an Id, but also, an optional query.
So, usually, the client will send:
http://localhost:49487/api/template/5b31b31c-ecd9-4e7a-bcdb-1c263399c86f
But sometimes, I need to return a bit of extra details in the payload. So I want them to send:
http://localhost:49487/api/template/5b31b31c-ecd9-4e7a-bcdb-1c263399c86f?IncludePreview=true
My .Net Web API Controller enpoint is defined like this, and handles the first case.
[Route("{Id}"), HttpGet]
public IActionResult GetTemplate(Guid Id, bool IncludePreview = false)
But as soon as I sent the second version, with the query string, the api controller fires (I have a breakpoint on it), but, Id is always Guid.Empty.
How can I have my API method accept both versions? Or do I need to create a separate endpoint for both versions?

You are assigning the Include Preview Boolean value as a fixed value. So event though your call catches the IncludePreview=true in GetTemplate method ,it get reassign. Please try to use a nullable Boolean with 'null' as assigned value.
public IActionResult GetTemplate(Guid Id, bool? IncludePreview=null)

Related

HttpPost [FromBody] parameter null when set to a specific object, but is not null when set to string and can be converted to that object in method

I have the following method:
[HttpPost]
public SearchDocumentRequest GetData([FromBody] SearchDocumentRequest request)
{
}
When I try to get data from one specific place in the app, request in this method is always null. However, I can retrieve request as a string, convert to SearchDocumentRequest and get the correct documents with this search query without any errors, like so:
[HttpPost]
public SearchDocumentRequest GetData([FromBody] string request)
{
var test = JsonConvert.DeserializeObject<SearchDocumentRequest>(request);
...
}
Why? What could possibly be the issue in the first case? Why is request null if it can be converted to the object?
Furthermore, this (first) method is used in many places throughout the app (at least 12 places), and only in one place there is an issue. I have checked the other jsons that make up the incoming requests, compared to json in this case, but I cannot find any difference or any issue. It's the exact same json, only two string values are different.

ASP.NET Webapi with parameter

I am building a webapi to getBalance of a customer from Db.It works well and i can retrieve the data.But the problem is in the parameter part.
For eg. In ASP.NET webservice when we request the service it gives us a page where according to the the service we get to enter the parameters in the textbox and upon
firing up the service we get the data.
I have my webapi up and running and the uri looks like this --- http://localhost/api/accounts/balance/cs-001
AccountsController
public class AccountsController : ApiController
{
[HttpGet]
[ActionName("balance")]
public string Getbalance(string accountNumber)
{
var data = BusinessLayer.Api.AccountHolderApi.GetBalance(accountNumber);
return data;
}
}
And my route
RouteTable.Routes.MapHttpRoute("OfficeApi", "api/{controller}/{action}/{accountNumber}");
So the accountNumber is the paramater here.Now one of my mobile app dev friend to is going to use this api suggests me to move account number in parameter rather than url.Like in my case we append the parameter in the url to retrieve the balance from the db.I want to know how to move the account number (the param) from the url to parameter in asp.net webapi.
I am new to webapi.Help needed.Thank You.
All you have to do is change the route since account number is already a parameter on the function:
RouteTable.Routes.MapHttpRoute("OfficeApi", "api/{controller}/{action}");
Then you'll be able to do:
http://localhost/api/accounts/balance?accountNumber=cs-001
#Avitus's answer is correct. Here is some belabor in case you are interested.
If someone requests this URL: http://localhost/api/accounts/balance?accountNumber=cs-001
ASP.NET routing will figure out the controller and action based on your routing configuration. Once the controller and action have been discovered, then it will try to bind the parameters in the action like this:
By default, Web API uses the following rules to bind parameters:
If the parameter is a "simple" type, Web API tries to get the value from the URI. Simple types include the .NET primitive types (int, bool, double, and so forth), plus TimeSpan, DateTime, Guid, decimal, and string, plus any type with a type converter that can convert from a string. (More about type converters later.)
For complex types, Web API tries to read the value from the message body, using a media-type formatter.
Here is the full article.

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.

How to make sure I have a "blank" request for home page in mvc

In MVC there is a whole fancy routing engine, which works very well and directs requests to /home/index (for "empty") requests.
I need to support some horrible legacy code and sometimes I need to do special things when QueryString and/or path is not empty.
How do I know (When I'm in /home/index) that the actual request is:
To the root of the website
Without any kind of parameters?
My attempt:
if (Request.QueryString.HasKeys() || Request.Path.Length > 1)
In your Controller for the given method that is returning the view you want to be redirected to, if there are query string parameters that you need to reference, include them as parameters:
public ActionResult Index(int someValue, string someText)
{
return View();
}
If you need to go to Index whether these query string parameters have been included, either
Make the parameters optional.
Overload the method with no parameters specified.

Categories