Multiple Get methods in Rest API controller - asp.net

Hello I have added an extra get method in a API controller.
original Get
[HttpGet]
[Route("GetParticipants")]
public IActionResult GetParticipants([FromQuery] Guid conversationId, [FromQuery] ContextServiceModel context)
{
... stuff ...
}
New Get
[HttpGet]
[Route("GetThreadParticipants")]
public IActionResult ThreadParticipants([FromQuery] Guid parentMessageId)
{
... stuff ...
}
My question is does this follow Rest? Is it okay to route them this way and have different parameters?

You can have as many Action methods as you want in your controller until and unless no action methods have same routes.
Routing
Conventional Routing
Defined in WebAPI.config
Attribute Routing
Directly defined on action method
More on attribute routing
Attribute routing Web API's

Related

.Net: Does controller have to have file name corresponding to URL?

I'm following this tutorial on .Net controllers, and it says "imagine that you enter the following URL into the address bar of your browser: http://localhost/Product/Index/3. In this case, a controller named ProductController is invoked."
What I Want To Know:
In order to successfully hit http://localhost/Product/Index/3, do you need a controller called ProductController specifically?
No, it is not necessary. You can use Route Attribute.
[Route("new-name-for-product")]
public class ProductController{
}
now you have to use http://localhost/new-name-for-product/Index/ this URL to invoke ProductController.
If you want to use one or more parameters with this URL you have to use different route templates for ActionMethod. Example below.
[Route("new-name-for-product")]
public class ProductController
{
// http://localhost/new-name-for-product/3/ will show product details based on id
// http://localhost/new-name-for-product/Index/3/ will show product details based on id
[HttpGet]
[Route("/{id}")]
public IActionResult Index(int id)
{
// your code
}
// you can use a different action method name.
// http://localhost/details/3/ will show product details based on id
// but parameter name (Ex: id) and the id inside route template the spelling must be the same.
[HttpGet]
[Route("details/{id}")]
public IActionResult GetById(int id)
{
// your code
}
}
It depends. In ASP.Net Core, routing can be configured either as conventional routing or as attribute routing.
Conventional routing is configured as below:
routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");
Here, the first path segment maps to the controller name,
the second maps to the action name,
the third segment is used for an optional id used to map to a model entity.
As a convention, controller file name is usually same as controller class name.
Hence, In conventional routing, url will match with filename.
The URL http://localhost/Products/Index matches below action method in ProductsController.
[Route("[controller]")]
public class ProductsController : Controller
{
[HttpPost("Index")] // Matches 'Products/Index'
public IActionResult Index()
{
return View();
}
}
Attribute Routing
With attribute routing the controller name and action names play no role in which action is selected.
Hence, it is independent of file name.
The URL http://localhost/Items/All matches below action method in ProductsController.
public class ProductsController : Controller
{
[Route("Items/All")]
public IActionResult Index()
{
return View();
}
}
Similarly, [Route] attribute can be added at both Controller and action methods. The same URL http://localhost/Items/All matches the action method shown below:
[Route("Items")]
public class ProductsController : Controller
{
[Route("All")]
public IActionResult Index()
{
return View();
}
}
For more details, you can refer to microsoft docs at https://learn.microsoft.com/en-us/aspnet/core/mvc/controllers/routing?view=aspnetcore-3.1

What's the difference between [HttpGet] and [HttpGet("{id}")]?

What are the differences between HTTPGET method and HTTPGET("{id}") method?
What is the API method that is used to update table columns?
[HttpGet]
public IActionResult Get()
{
return new JsonResult(users);
}
// GET api/values/5
[HttpGet("{id}")]
public IActionResult Get(string id)
{
return new JsonResult(response);
}
You should take a look at Attribute Routing in Web API.
The first method is routing to a clean api:
/api/controller
The second specifies route value in the attribute and will be called via the following url:
/api/controller/5
The second one is normally used to update existing queries, as you specify specific value in the route whilst the first specifies nothing.

Route all Web API requests to one controller method

Is it possible to customize ASP.NET Web API's routing mechanism to route all requests to the API to one controller method?
If a request comes in to
www.mysite.com/api/products/
or
www.mysite.com/api/otherResource/7
All would be routed to my SuperDuperController's Get() method?
I ran into a case where I needed to do this. (Web API 2)
I first looked into creating custom IHttpControllerSelector and IHttpActionSelectors. However, that was a bit of a murky way around. So I finally settled on this dead simple implementation. All you have to do is setup a wildcard route. Example:
public class SuperDuperController : ApiController
{
[Route("api/{*url}")]
public HttpResponseMessage Get()
{
// url information
Request.RequestUri
// route values, including "url"
Request.GetRouteData().Values
}
}
Any GET request that starts with "api/" will get routed to the above method. That includes the above mentioned URLs in your question. You will have to dig out information from the Request or context objects yourself since this circumvents automatic route value and model parsing.
The good thing about this is you can still use other controllers as well (as long as their routes don't start with "api/").
I don't konw why you would want to do this and I certainly wouldn't recommend routing everything through one controller, however you could achieve this as follows. Assuming you are only ever going to have a resource with an optional id in your calls, add this to your WebApiConfig:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{resource}/{id}",
defaults: new { controller = "SuperDuper", id = RouteParameter.Optional }
);
}
}
Then define your controller method as follows:
public class SuperDuperController : ApiController
{
public IHttpActionResult Get(string resource, int? id = null)
{
return Ok();
}
}
You would need to decide on an appropriate IHttpActionResult to return for each different type of resource.
Alternatively using Attribute Routing, ensure that config.MapHttpAttributeRoutes() is present in your WebApiConfig and add the following attributes to your controller method:
[RoutePrefix("api")]
public class SuperDuperController : ApiController
{
[Route("{resource}/{id?}")]
public IHttpActionResult Get(string resource, int? id = null)
{
return Ok();
}
}

How to avoid repeating http method attribute in WebApi controller?

I have several ASP.NET WebApi controllers with some methods in each. All these methods should be accessible using HTTP POST only. What I'm trying to avoid is explicit [HttpPost] attribute usage for each method. Yep, I'm lazy.
My code looks like
[HttpPost]
public void Method1() { }
[HttpPost]
public void Method2() { }
...
Is there any way to configure route / base controller to access these methods via POST without setting attribute for each method? To have just like this
public void Method1() { }
public void Method2() { }
...
If I try to call method that doesn't have [HttpPost] I'm getting HTTP 405 error.
ASP.NET Web API uses convention over configuration. If you follow the convention to name your actions in the following way...
GetXXX
PostXXX
PutXXX
DeleteXXX
... you don't have to use the attributes. If the action starts with the appropriate HTTP verb Web API will take care of it.

Attribute Routing failing - Web Api

I have two actions on a controller called JobController that has this Route Prefix
[RoutePrefix("API/Job")]
1st Action (In order of precedence in controller)
[Route("{jobId}/{user}"), System.Web.Http.HttpPost]
public HttpResponseMessage AssignUser(long jobId, string user)
2nd Action
[HttpPost]
[Route("{id}/comment/")]
public HttpResponseMessage SaveComment(string commentText, long id)
Doing a post with Postman to this Route - MyDomain/API/Job/11/Comment - with a commentText value of "foo" matches against the first route, not the one i want it to.
Any ideas why this is happening?
Only guessing, but I think WebAPI cannot distinguish between route 1 and 2 because "comment" could also be a user-name. You could change the first route to something like:
[Route("{jobId}/users/{user}"), System.Web.Http.HttpPost]
public HttpResponseMessage AssignUser(long jobId, string user)
The problem here, is that both actions have the same action (POST), the same number of parameters and same type for these parameters, so which comes first that matches the route will win.
Your route need to have something unique distinguish between the two routes, so you need to change your routes to either have different actions (POST vs PUT for example) or you change one route to be something like this
[HttpPost]
[Route("{id}/comments/{comment}")]
public HttpResponseMessage SaveComment(long id, string comment)
hope this helps.
In the end I just created separate ViewModels
[HttpPost]
[Route("comment")]
public HttpResponseMessage SaveComment([FromBody] JobCommentViewModel viewModel)
public class JobCommentViewModel
{
public long JobId { get; set; }
public string Comment { get; set; }
}

Resources