Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.Net MVC 4 WebAPI Custom Routing

I have a controller called News in my WebAPI project, I have two default actions called Get that handled the following URL's:

/api/News <- this returns a list of news /api/News/123 <- this returns a specific news item by id.

All straightforward so far and obviously the default route handles these scenarios. I next want to have a URL that looks like this:

/api/News/123/Artists <- will return all artists related to the specified news item.

Now I am fairly news to ASP.Net MVC and WebAPI so this is the first time I have had to deal with routing. I have modified my default route to look like this:

routes.MapRoute(
            name: "Default",
            url: "{controller}/{id}/{action}",
            defaults: new { controller = "News", action = "Get", id = UrlParameter.Optional }

So here I have moved the {action} to the end of the URL and I have added a Artists method to my News controller. This still works with the first two scenarios but returns a 404 for the third scenario.

Obviously the routing isn't working for /api/News/123/Artists but I have no idea why.

I can't seem to find any examples of people using WebAPI like this which makes me think I am doing something fundamentally wrong.

Any help would be appreciated.

like image 711
Lee Dale Avatar asked Feb 12 '13 15:02

Lee Dale


2 Answers

The issue is, that you are trying to acces Web API but mapping the ASP.NET MVC

this is a mapping you need:

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

And it should be done in the App_Start \ WebApiConfig (if using the default template settings)

Example of the methods (in your news API controller):

// GET api/values/5
public string Get(int id)
{
  return "value " + id;
}

// GET api/values/5
[HttpGet]
public string Artist(int id)
{
  return "artist " + id;
}
like image 78
Radim Köhler Avatar answered Sep 23 '22 19:09

Radim Köhler


The AttributeRouting should be a good solution. It can be installed by Nuget, and the document is here.

Some examples

public class SampleController : Controller
{
    [GET("Sample")]
    public ActionResult Index() { /* ... */ }
                    
    [POST("Sample")]
    public ActionResult Create() { /* ... */ }
                    
    [PUT("Sample/{id}")]
    public ActionResult Update(int id) { /* ... */ }
                    
    [DELETE("Sample/{id}")]
    public string Destroy(int id) { /* ... */ }
    
    [Route("Sample/Any-Method-Will-Do")]
    public string Wildman() { /* ... */ }

    [GET("", ActionPrecedence = 1)]
    [GET("Posts")]
    [GET("Posts/Index")]
    public ActionResult Index() { /* ... */ }

    [GET("Demographics/{state=MT}/{city=Missoula}")]
    public ActionResult Index(string state, string city) { /* ... */ }
}

It works very well about custom routing.

Update

In asp.net WebApi 2, AttributeRouting is included inside by native. It has some history, the first version, asp.net WebApi 1, is weak about routing annotations.

And then, asp.net WebApi 2 is released, the AttributeRouting is included by native. So, that open project is not maintained anymore, said in GitHub page.

In microsoft blog, the section Independent Developer Profile – Tim McCall – Attribute Routing in MVC and Web API 2 said about the history too.

like image 31
AechoLiu Avatar answered Sep 19 '22 19:09

AechoLiu