1

I want to add a new route to my Web Api, which will read various ids and then filter a bunch of books.

So the final url should read something like http://localhost/api/books/1/1/1/1

Now I have added a route to my RouteConfig as follows :-

    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapRoute(
            name: "BookFilter",
            url: "api/books/{author}/{title}/{genre}/{isbn}",
            defaults: new { controller = "Books", action = "BookFilter" }
        );

        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );

    }

I also added the following in my BooksController:-

    [HttpGet]
    public IQueryable<BookDTO> BookFilter(int authorId, int titleId, int genreId, int isbn)
    {
        //filter books here
        return db.Books.ProjectTo<BookDTO>();
    }

However when I try to reach the page, I get a 404.

What do I need to do to reach my page?

Thanks for your help and time

2
  • any idea of attribute routing? Commented Jun 1, 2016 at 12:58
  • yes I do have an idea, its just I have not done this for a while Commented Jun 1, 2016 at 13:37

2 Answers 2

2

Web API and MVC are independent frameworks which each have separate types. The likely reason your route is not working is that you are confusing the two. Specifically, for it to work as you configured, you would need an MVC controller (that is, a controller that inherits System.Web.Mvc.Controller).

So, assuming you want to go with Web API as your question would indicate, you first need to ensure the correct definition of your controller. It should inherit from System.Web.Http.ApiController.

public class BooksController : ApiController
{
    [HttpGet]
    public IHttpActionResult BookFilter(string author, string title, string genre, string isbn)
    {
        return Ok("Successful result");
    }
}

Next, you need to put your routing in the WebApiConfig.cs file, not in the RouteConfig.cs file. Don't forget to remove your route from the RouteConfig.cs file.

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        // Web API configuration and services

        // Web API routes
        config.MapHttpAttributeRoutes();

        config.Routes.MapHttpRoute(
            name: "BookFilter", 
            routeTemplate: "api/books/{author}/{title}/{genre}/{isbn}", 
            defaults: new { controller = "Books", action = "BookFilter" });

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

You also need to ensure that the call to GlobalConfiguration.Configure(WebApiConfig.Register); is in your application startup path (by default in Global.asax).

public class MvcApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
        GlobalConfiguration.Configure(WebApiConfig.Register);
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);
    }
}
Sign up to request clarification or add additional context in comments.

Comments

0

Make sure to use the same parameter name in your action (eg. change author to authorId):

Optionally, you can also specify default values for these parameters at your RouteConfig, as follows:

    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapRoute(
            name: "BookFilter",
            url: "api/books/{authorId}/{titleId}/{genreId}/{isbn}",
            defaults: new { controller = "Books", action = "BookFilter", authorId= UrlParameter.Optional, titleId = UrlParameter.Optional, genreId = UrlParameter.Optional, isbn = UrlParameter.Optional }
        );

        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );

    }

Controller:

    [HttpGet]
    public IQueryable<BookDTO> BookFilter(int authorId, int titleId, int genreId, int isbn)
    {
        //filter books here
        return db.Books.ProjectTo<BookDTO>();
    }

2 Comments

tried your changes but still not reaching the page. Still getting a 404
1) You don't need to specify defaults for every parameter. When you don't specify defaults, it makes the URL parameters required (which is likely preferable in this case). 2) UrlParameter.Optional can only be used 1 time per route and it must be the right-most parameter. 3) This is the wrong place to configure Web API routes. See my answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.