Ok web api routing fun.
my web api route config is below. the geocoding and info routes are performing great. And I'm confused why the search one is not following suite.
/*
==Geocoding Endpoints==
*/
config.Routes.MapHttpRoute(
name: "v1_GeocodeApi",
routeTemplate: "api/v{version}/{controller}/{street}/{zone}",
defaults: new
{
action = "get",
controller = "Geocode",
version = "1"
});
config.Routes.MapHttpRoute(
name: "v1_GeocodeMultipleApi",
routeTemplate: "api/v{version}/{controller}/multiple",
defaults: new
{
action = "multiple",
controller = "Geocode",
version = "1"
});
/*
==Search Endpoints==
*/
config.Routes.MapHttpRoute(
name: "v1_SearchApi",
routeTemplate: "api/v{version}/{controller}/{featureClass}/{returnValues}",
defaults: new
{
action = "Get",
controller = "Search",
version = "1"
});
/*
==Info Endpoints==
*/
config.Routes.MapHttpRoute(
name: "v1_InfoApi",
routeTemplate: "api/v{version}/{controller}/FeatureClassNames",
defaults: new
{
action = "FeatureClassNames",
controller = "Info",
version = "1"
});
}
so i want to have a url like http://webapi/api/v1/search/fc/rv
. This url produces the below stack trace and resulting 404. I thought the convention was that if you had a controller with a get method it would be used by default. That seems to be what happens with the first geocoding route.
w3wp.exe Information: 0 : Request, Method=GET,
Url=http://webapi/api/v1/Search/fc/rv,
Message='http://webapi/api/v1/Search/fc/rv'
w3wp.exe Information: 0 : Message='Search',
Operation=RouteVersionedControllerSelector.SelectController w3wp.exe
Information: 0 :
Message='WebAPI.API.Controllers.API.Version1.SearchController',
Operation=DefaultHttpControllerActivator.Create w3wp.exe Information:
0 : Message='WebAPI.API.Controllers.API.Version1.SearchController',
Operation=HttpControllerDescriptor.CreateController w3wp.exe
Information: 0 : Message='Will use same 'JsonpMediaTypeFormatter'
formatter',
Operation=JsonpMediaTypeFormatter.GetPerRequestFormatterInstance
w3wp.exe Information: 0 : Message='Selected
formatter='JsonpMediaTypeFormatter', content-type='application/json;
charset=utf-8'', Operation=DefaultContentNegotiator.Negotiate w3wp.exe
Warning: 0 : Message='UserMessage='No HTTP resource was found that
matches the request URI
'http://webapi/api/v1/Search/fc/rv'.',
MessageDetail='No action was found on the controller 'Search' that
matches the request.'',
Operation=ApiControllerActionSelector.SelectAction, Status=404
(NotFound), Exception=System.Web.Http.HttpResponseException:
Processing of the HTTP request resulted in an exception. Please see
the HTTP response returned by the 'Response' property of this
exception for details. at
System.Web.Http.Controllers.ApiControllerActionSelector.ActionSelectorCacheItem.SelectAction(HttpControllerContext
controllerContext) at
System.Web.Http.Tracing.Tracers.HttpActionSelectorTracer.<>c__DisplayClass2.<System.Web.Http.Controllers.IHttpActionSelector.SelectAction>b__0() at
System.Web.Http.Tracing.ITraceWriterExtensions.TraceBeginEnd(ITraceWriter
traceWriter, HttpRequestMessage request, String category, TraceLevel
level, String operatorName, String operationName, Action`1 beginTrace,
Action execute, Action`1 endTrace, Action`1 errorTrace) w3wp.exe
Warning: 0 : Message='UserMessage='No HTTP resource was found that
matches the request URI
'http://webapi/api/v1/Search/fc/rv'.',
MessageDetail='No action was found on the controller 'Search' that
matches the request.'', Operation=SearchController.ExecuteAsync,
Status=404 (NotFound),
Exception=System.Web.Http.HttpResponseException: Processing of the
HTTP request resulted in an exception. Please see the HTTP response
returned by the 'Response' property of this exception for details.
at
System.Web.Http.Controllers.ApiControllerActionSelector.ActionSelectorCacheItem.SelectAction(HttpControllerContext
controllerContext) at
System.Web.Http.Tracing.Tracers.HttpActionSelectorTracer.<>c__DisplayClass2.<System.Web.Http.Controllers.IHttpActionSelector.SelectAction>b__0() at
System.Web.Http.Tracing.ITraceWriterExtensions.TraceBeginEnd(ITraceWriter
traceWriter, HttpRequestMessage request, String category, TraceLevel
level, String operatorName, String operationName, Action`1 beginTrace,
Action execute, Action`1 endTrace, Action`1 errorTrace) at
System.Web.Http.Tracing.Tracers.HttpActionSelectorTracer.System.Web.Http.Controllers.IHttpActionSelector.SelectAction(HttpControllerContext
controllerContext) at
System.Web.Http.ApiController.ExecuteAsync(HttpControllerContext
controllerContext, CancellationToken cancellationToken) at
System.Web.Http.Tracing.Tracers.HttpControllerTracer.<>c__DisplayClass4.<System.Web.Http.Controllers.IHttpController.ExecuteAsync>b__0()
at
System.Web.Http.Tracing.ITraceWriterExtensions.TraceBeginEndAsync[TResult](ITraceWriter
traceWriter, HttpRequestMessage request, String category, TraceLevel
level, String operatorName, String operationName, Action`1 beginTrace,
Func`1 execute, Action`2 endTrace, Action`1 errorTrace) w3wp.exe
Information: 0 : Response, Status=404 (NotFound), Method=GET,
Url=http://webapi/api/v1/Search/fc/rv,
Message='Content-type='application/json; charset=utf-8',
content-length=unknown'
Now if I were to make another route more similar to the second geocoding route with the /multiple making the route template api/v{version}/{controller}/**for**/{featureClass}/{returnValues}
the routing works and all is happy.
The controller signature is
public class SearchController : ApiController
{
[HttpGet]
public async Task<HttpResponseMessage> Get(string featureClass, string returnValues, [FromUri] SearchOptions options)
{
// ...
}
}
My hunch is that the async Task part is throwing it off somehow with the default get binding but that doesn't make sense since it works with the modified route.
Your request url
http://webapi/api/v1/search/fc/rv
is matching thev1_GeocodeApi
route which has the 'stree' and 'zone' variables. Since these variable names do not match the Search controller's Get method's parameter names, you are seeing 404. You can try modifying your routes to not accept the controller name as variable, but have something likeapi/v{version}/Geocode/{street}/{zone}
,api/v{version}/Search/{featureClass}/{returnValues}