Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WEB API .NET Action with custom endpoint names

So I've set up a backend in .NET and the basic HTTP calls are working. Now I need an alternative method that will not search by ID but by a property, so i want to make a REST call with a different property at the end.

Here are the 2 methods of my controller:

public IHttpActionResult GetCategory(int id)
{
    var category = _productService.GetCategoryById(id);

    if (category == null) return NotFound();
    var dto = CategoryToDto(category);
    return Ok(dto);
}


public IHttpActionResult GetCategoryByName(string name)
{
    var category = _productService.GetCategoryByName(name);

    if(category == null) return NotFound();
    var dto = CategoryToDto(category);
    return Ok(dto);
}

My API config is configured as follow: /api/{controller}/{action}/{id}.

So the first call works with this call: /api/category/getcategory/2

When I try the second method with this call : /api/category/getcategorybyname/Jewelry

I get an error saying that no action in my controller matches the request.

What's the problem here?

like image 343
TanguyB Avatar asked Dec 22 '16 14:12

TanguyB


2 Answers

The default routing config has an optional parameter with a restraint of type int. Passing "jewelry" does not satisfy that constraint.

The easiest fix is to apply the RouteAttribute over the action and specify the paramters that way.

[Route("api/category/getcategorybyname/{name}")]
public IHttpActionResult GetCategoryByName(string name)

Make sure your WebConfig.cs file has attribute routing enabled with line

config.MapHttpAttributeRoutes();

You can also shorten the action name in RouteAttribute by applying a RoutePrefix("api/category") to your controller and then stripping that part from the Route attribute on the action.

like image 198
Igor Avatar answered Oct 17 '22 07:10

Igor


You can also create a RoutePrefix rule that applies to all actions in the controller, and then apply the specific Route for every action:

[RoutePrefix("api/nestedSet")] //<<======
public class NestedSetController : ApiController
{
    [Route("myaction01")] //<<======
    [HttpGet]
    public async Task<int> Myaction01_differentName()
    {
       //the call will be: http://mydomain/api/nestedSet/myaction01
       //code here...
       return 0;
    }


    [Route("myaction02")] //<<======
    [HttpGet]
    public async Task<int> Myaction02_differentName()
    {
       //the call will be: http://mydomain/api/nestedSet/myaction02
       //code here...
       return 0;
    }
}
like image 35
Carlo Luther Avatar answered Oct 17 '22 07:10

Carlo Luther