When I use HttpGet(...), intellisense tells me that besides the first argument, i.e. pattern, I also have name and order. While the latter is obvious to me, I got a bit uncertain on what the parameter name had as its purpose.
Heading over to the docs, I see that the constructor of HttpGet only declares a single parameter. That confused me and I suspect that I'm missing something or using the Framework's version instead of Core, or something.
As I can see the biggest advantage of the Name property of the HttpMethodAttribute (which is the base class of HttpGetAttribute) is that you can distinguish method overloads:
[HttpGet(Name="ById"]
public IActionResult GetBy(int id)
{
}
[HttpGet(Name="ByExternalId"]
public IActionResult GetBy(Guid id)
{
}
UPDATE #1: I've revised my answer
The above sample code would result in an AmbiguousMatchException, where it is stating the same Template has been registered for different action.
I had put together another sample and used the following RouteDebugger to get insight. In the Configure method I've called the app.UseRouteDebugger() method to be able to see the registered routes in json format under the /route-debugger url.
[Route("api/[controller]")]
[ApiController]
public class TestController : ControllerBase
{
[HttpGet()]
public IActionResult GetA(string a)
{
return Ok(nameof(GetA));
}
[HttpGet(template: "GetB")]
public IActionResult GetB(string b)
{
return Ok(nameof(GetB));
}
[HttpGet(template: "GetC", Name= "GetD")]
public IActionResult GetD(string d, string e)
{
return CreatedAtRoute(routeName:"GetC", routeValues: new { c = "v"}, value: null);
}
[HttpGet(template: "GetC/{c}", Name = "GetC")]
public IActionResult GetC(string c)
{
return Ok(nameof(GetC));
}
}
The route table would look like this:
[
{
"Action":"GetA",
"Controller":"Test",
"Name":null,
"Template":"api/Test",
"Contraint":[{}]
},
{
"Action":"GetB",
"Controller":"Test",
"Name":null,
"Template":"api/Test/GetB",
"Contraint":[{}]
},
{
"Action":"GetD",
"Controller":"Test",
"Name":"GetD",
"Template":"api/Test/GetC",
"Contraint":[{}]
},
{
"Action":"GetC",
"Controller":"Test",
"Name":"GetC",
"Template":"api/Test/GetC/{c}",
"Contraint":[{}]
}
]
As you seen the following happened:
GetA methodTemplate has been specified.Name so you can't refer to this route via its name inside ActionLink or CreatedAtRoute, etc.GetB methodapi/test/getb, because the controller's and the action's Template properties are combined.Name so you can't refer to this route via its name inside ActionLink or CreatedAtRoute, etc.GetC methodapi/test/getc/{c}, because the controller's and the action's Template properties are combined. The c parameter can accept any value. If it is not provided then GetD will be called, because that was registered first.Name (GetC) so you can refer to this route via its name inside ActionLink or CreatedAtRoute, etc. Like as we did it inside GetDGetD methodapi/test/getc, because the controller's and the action's Template properties are combined. Because it was registered prior GetC method's route that's why it will called if no further path is provided.Name (GetD). In the CreatedAtRoute we are referring to GetC via its name not through its route. If we are replacing the Name to GetC then it would throw the following exception at runtime:InvalidOperationException: The following errors occurred with attribute routing information:
Error 1: Attribute routes with the same name 'GetC' must have the same template: Action: 'Controllers.TestController.GetD ()' - Template: 'api/Test/GetC' Action: 'Controllers.TestController.GetC ()' - Template: 'api/Test/GetC/{c}
Template it will throw an AmbiguousMatchException at runtime when you make a call against that route. (So, other routes will work perfectly fine)Name it will throw an InvalidOperationException at runtime when you make any call. (So, other routes will not work)Name provides the ability to refer them easily without knowing the exact Template. This separation allows us to change the Template without affecting referring links.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With