Lee Dale
Lee Dale

Reputation: 1186

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.

Upvotes: 7

Views: 7657

Answers (3)

AechoLiu
AechoLiu

Reputation: 18368

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.

Upvotes: 3

Radim K&#246;hler
Radim K&#246;hler

Reputation: 123861

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;
}

Upvotes: 8

Tabish Sarwar
Tabish Sarwar

Reputation: 1525

In routing Action is the action name on the method that you want to route to .That action name should be in the attribute used on the method.

 [HttpGet]
 [ActionName("CustomAction")]
public HttpResponseMessage MyNewsFeed(Some params)
{ return Request.CreateResponse(); }

Now your route should look like this

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

Let me know if this helps.

Upvotes: 1

Related Questions