Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Wildcard in WebAPI Route template

I have set up a route template:

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

controller's action signature:

public IEnumerable<object> Get(Int64 id,string abc)

I tried to match it with URL http://mymachine.com/api/Individuals/1?abc=4, but it gives me an exception

{"$id":"1","Message":"An error has occurred.","ExceptionMessage":"Object reference not set to an instance of an object.","ExceptionType":"System.NullReferenceException","StackTrace":" at System.Web.Http.ValueProviders.Providers.RouteDataValueProvider.d__4.MoveNext()\r\n

Strangely, http://mymachine.com/api/Individuals?id=1&abc=4 does match with the controller,action and parameters.

I thought "{id}" of "api/{controller}/{id}/{*wildcard}" will work.

Why?

like image 262
ValidfroM Avatar asked Nov 01 '13 11:11

ValidfroM


2 Answers

The answer from gooid is correct. I just want to answer the 2nd part of the question:

Strangely, http://mymachine.com/api/Individuals?id=1&abc=4 does match with the controller,action and parameters.

Since you have id = RouteParameter.Optional, if the route doesn't provide id, it still matches the route template. The placeholder {*wildcard} looks for the rest of the route and put it into the Route Dictionary under the key "wildcard". In this case, it is empty string (or null).

Remember that the query parameters also go into the Route Dictionary. Therefore, your Route Dictionary will be: { "id": "1", "abc": "4", "wildcard": ""}

For more info, you can look into http://www.asp.net/web-api/overview/web-api-routing-and-actions/routing-in-aspnet-web-api

like image 59
NXH Avatar answered Oct 17 '22 15:10

NXH


The wildcard will tell the routing engine to match the rest of the URI to a route parameter (for an example, see "Get Books By Publication Date" section in this article).

It does not mean match any arbitrary named variable to any parameter - this is something WebApi does by default with items on the querystring regardless of your route configuration (hence why you second URI worked - it didn't match any route).

It did not match {id} in your route because it was expecting a parameter called {wildcard} that was not marked as optional.

To illustrate, if you simply changed 'wildcard' to 'abc':

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

Then it would successfully match the following URI:

http://mymachine.com/api/Individual/1/a/b/c

With the values id=1, abc=a/b/c

To fix, simply remove the wildcard from your route, so that it looks like this:

config.Routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}/{id}",
    defaults: new {id = RouteParameter.Optional});
like image 39
gooid Avatar answered Oct 17 '22 14:10

gooid