Jeff Borden
Jeff Borden

Reputation: 1429

MVC 3 Web API Routing Not Working

I'm fighting issues with routing in an MVC 3 Web API. It seems like it should be pretty simple, but I'm not making any headway.

My error is:

  <Error>
     <Message>The request is invalid.</Message>
       <MessageDetail>
           The parameters dictionary contains a null entry for parameter 'id' of non-nullable type 'System.Int32' for method 'Boolean NewViolationsPublished(Int32)' in 'BPA.API.Controllers.CacheManagementController'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter.
       </MessageDetail>
   </Error>

My RegisterRoutes is such:

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

            routes.MapHttpRoute(
              name: "NukeAllItemsFromCache",
              routeTemplate: "api/CacheManagement/NukeAllItemsFromCache");


            routes.MapHttpRoute(
                 name: "ControllerAndAction",
             routeTemplate: "api/{controller}/{action}"
             );

            routes.MapHttpRoute(
                 name: "ControllerAndActionAndId",
                 routeTemplate: "api/{controller}/{action}/{id}",
                    defaults: new { id = RouteParameter.Optional, action = "Get" },
              constraints: new { id = @"^\d+$" } // Only integers 
             );

            routes.MapHttpRoute(
                name: "ControllerAndId",
                routeTemplate: "api/{controller}/{id}",
                  defaults: new { id = RouteParameter.Optional },
          constraints: new { id = @"^\d+$" } // Only integers 
            );
        }

And my controller is (i took out the code for ease of reading):

 public class CacheManagementController : ApiController
    {
        public CacheManagementController()        

        [HttpGet]
        public bool NewViolationsPublished(int id)

        [HttpGet]
        public bool IsCached(CachedItemLabels label, int clientId)

        [HttpGet]
        public void RemoveItemFromCache(int clientId, CachedItemLabels cacheLabel, string test)

        [HttpGet]
        public string NukeAllItemsFromCache()    
    }

I get the error when I try to call:

http://localhost/api/CacheManagement/NukeAllItemsFromCache

TIA

Upvotes: 1

Views: 4136

Answers (5)

Ryan M
Ryan M

Reputation: 2112

Are you sure you're defining your routes in the right place? Web API routes should be configured using System.Web.Http.GlobalConfiguration.Configuration.Routes.MapHttpRoute (normally in a WebApiConfig.cs file in App_Start), as shown on http://www.asp.net/web-api/overview/extensibility/configuring-aspnet-web-api, which is different from the route configuration used by vanilla MVC.

I think you may just be hitting the default Web API route, which is api/{controller}/{id}, with ID optional. The action is determined by the HTTP verb, which in this case is GET, and all of your methods match that by virtue of the [HttpGet].

Edit: example

Global.asax

 protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();

        WebApiConfig.Register(GlobalConfiguration.Configuration);
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);

        GlobalModifiers.ApplyGlobalConfiguration(this, true);
    }

WebApiConfig.cs

public static class WebApiConfig
{
   public static void Register(HttpConfiguration config)
   {
        config.Routes.MapHttpRoute(
            name: "action-specific",
            routeTemplate: "api/{controller}/{action}/{id}",
            defaults: new { id = RouteParameter.Optional }
    );
}

Upvotes: 5

Karl Glennon
Karl Glennon

Reputation: 3210

Double check that your controller extends ApiController rather than Controller

 public class CacheManagementController : ApiController

rather than

 public class CacheManagementController : Controller

Upvotes: 0

Jonas
Jonas

Reputation: 1

You tried to put parameter id as nullable like:

[HttpGet]
public bool NewViolationsPublished(int? id)

or

    [HttpGet]
    public bool NewViolationsPublished(Nullable<Int32> id)

Maybe this works...

Upvotes: 0

Rolfvm
Rolfvm

Reputation: 336

You are missing the default action for the route you configured:

routes.MapHttpRoute(
          name: "NukeAllItemsFromCache",
          routeTemplate: "api/CacheManagement/NukeAllItemsFromCache");

should be

routes.MapHttpRoute(
          name: "NukeAllItemsFromCache",
          routeTemplate: "api/CacheManagement/NukeAllItemsFromCache",
          defaults: new { action = "NukeAllItemsFromCache" }
);

Upvotes: 0

Dima
Dima

Reputation: 6741

I beleave your problem is in this route:

routes.MapHttpRoute(
  name: "ControllerAndActionAndId",
  routeTemplate: "api/{controller}/{action}/{id}",
  defaults: new { id = RouteParameter.Optional, action = "Get" },
  constraints: new { id = @"^\d+$" } // Only integers 
);

You specify id as an optional parameter and at the same time constrain it to actually be a non-nullable number. If /api/CacheManagement/NukeAllItemsFromCache is an exception, then add additional route for it, otherwise ease a constraint to something like @"^\d*$" if possible.

Upvotes: 0

Related Questions