Lukas
Lukas

Reputation: 613

WebAPI - routes

I am new into WebAPI and I don't understand how routing in WebAPI v2 works.

I've created simple test controller:

public class TestController : ApiController
{
    public List<string> GetAll()
    {
        return new List<string>();
    }

    public string Get(int id)
    {
        return string.Empty;
    }

    public string GetSmthByParam1(int param)
    {
        return string.Empty;
    }

    public string GetSmthByParam2(int param)
    {
        return string.Empty;
    }

    public List<string> GetAllByParam(int param)
    {
        return new List<string>();
    }
}

I would like to reach each method by:

/Api/Test/GetAll
/Api/Test/Get/3
/Api/Test/GetSmthByParam1/1
/Api/Test/GetSmthByParam2/1
/Api/Test/GetAllByParam/1

and I don't know how to achieve it. I changed routes in WebApiConfig.cs to:

config.Routes.MapHttpRoute("DefaultApiWithAction", "Api/{controller}/{action}/{id}", new { id = RouteParameter.Optional }, new { id = @"\d+" });

Upvotes: 1

Views: 1249

Answers (9)

Guptesh
Guptesh

Reputation: 1

Attribute routing is something which you should look for. It simplifies your Api in a much better way and you never have to keep guessing looking at your route map in ApiConfig that which route is getting resolved. There are discussions around whether you should opt for Attribute routing or not, but in my opinion it really depends on how simple and readable you want your API to be. Happy coding.

Upvotes: 0

Yuriy A.
Yuriy A.

Reputation: 752

  1. Install Nuget-Package AttributeRouting.WebAPI

  2. Do not touch default route in a WebApiConfig

  3. Add "config.MapHttpAttributeRoutes();" into Register method of the WebApiConfig class, so it would be:

    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // Web API routes
            config.MapHttpAttributeRoutes();
    
            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
            ...
        }
    }
    
  4. Now you could add a RouteAttrubute to any webapi action like this:

    [HttpGet]
    [AllowAnonymous]
    [Route("api/test/get/{id}")]
    public string Get(int id)
    {
        return string.Empty;
    }
    

These links will be useful: first & second

Upvotes: 3

Alex Terry
Alex Terry

Reputation: 2092

You do not need to use attribute routing. Just add an http verb attribute to your methods and change 'param' to 'id' on a few of the methods.

public class TestController : ApiController
{
    [HttpGet]
    public List<string> GetAll()
    {
        return new List<string>();
    }

    [HttpGet]
    public string Get(int id)
    {
        return string.Empty;
    }

    [HttpGet]
    public string GetSmthByParam1(int id)
    {
        return string.Empty;
    }

    [HttpGet]
    public string GetSmthByParam2(int id)
    {
        return string.Empty;
    }

    [HttpGet]
    public List<string> GetAllByParam(int id)
    {
        return new List<string>();
    }
}

https://learn.microsoft.com/en-us/aspnet/web-api/overview/web-api-routing-and-actions/routing-in-aspnet-web-api

Upvotes: 0

Eitan Revach
Eitan Revach

Reputation: 11

The default routing mechanism in WebAPI try to play the CRUD attitude. This is all about this..

When it fits your needs - go for it. Usually, better approach would be to you the Attributes

  • [RoutePrefix("Test")]
  • [Route("Get")]

(like Rakesh wrote).

It arranges your controllers in better way and much easier to expect the URLs..

Upvotes: 0

Mysterion
Mysterion

Reputation: 384

To be very short, webapi will go for the signature rather than just a name of the action like mvc routing works, so to solution for this dilemma would be

1) MVC5 comes with attribute routing so one can define it at the action or the controller level to make it more easy

2) make your signature unique to eachother along with the reqeust type with normal routing but if your routing has same signature then do something like this

define your routing like this,

 config.Routes.MapHttpRoute(
           name: "Defaultapi",
           routeTemplate: "api/{controller}/{action}/{id}",
           defaults: new { id = RouteParameter.Optional }
       );

Upvotes: 0

NullHypothesis
NullHypothesis

Reputation: 4516

Although I know that this is a basic example you put forward, I'm interested in your actual business case a little more. Why does your controller many GETS? There is nothing wrong with that, keep in mind, i'm simply curious. Oftentimes I've been able to avoid multiple gets with concepts such as ODATA queries, strategy patterns, or services that are able to retrieve what is needed. Route attributes are a great solution to this as others mentioned, however as someone else mentioned it could potentially be a problem where you have to start using a route prefix on the controller coupled with route attributes to sometimes make the route more clear, and it can get a little messy fast (i've had my teams sometimes do that where they didn't follow convention correctly and their controller routes weren't intuitive)

Finally, what are the return types that you'll have for these - are they really all string?

Thanks!

Upvotes: 0

out-of-memory
out-of-memory

Reputation: 1

So it is nice to use Attribute routes, but i'll suggest don't do it right now, as it encapsulates lot of logic which you have to learn right now. Plus I don't think attribute route is good practice every time. Some times routes from config is better choice, when you are building really huge application. Now see you route config your parameter is "id" so when route will hit it will extract your parameter and it will inject it to your method. in your last 3 methods you have used "param", as your method parameter, which is something route will not be able to inject. as names don;t match in route param and method param. further more, if you will create another route similar to previous one and change the route parameter to "param", it will still don't work, because route mapping works on first come first basis. I hope you would have got little start on this and you will understand the importance of learning routing basics along with the using attributes.

Upvotes: 0

Rakesh
Rakesh

Reputation: 157

below code should work for you,

[RoutePrefix("Test")] public class TestController : ApiController { [Route("GetAll")] public List<string> GetAll() { return new List<string>(); } [Route("Get")] public string Get(int id) { return string.Empty; } [Route("GetSmthByParam1/{param}")] public string GetSmthByParam1(int param) { return string.Empty; } [Route("GetSmthByParam2/{param}")] public string GetSmthByParam2(int param) { return string.Empty; } [Route("GetSmthByParam/{param}")] public List<string> GetAllByParam(int param) { return new List<string>(); } }

Your config should be config.MapHttpAttributeRoutes();

Upvotes: 4

Radin Gospodinov
Radin Gospodinov

Reputation: 2323

You should use Route attribute see the article here: http://www.asp.net/web-api/overview/web-api-routing-and-actions/attribute-routing-in-web-api-2

Upvotes: 0

Related Questions