I'm looking to properly configure System.Web.Handlers.TransferRequestHandler
path
attribute to handle both routes to WebApi REST actions and ODataController custom function in an ASP.NET WebApi 2 project.
My web.config
file handlers are configured as follow in order to support custom ODataController functions call (see my related question here) :
<handlers>
<clear/>
<remove name="ExtensionlessUrlHandler-Integrated-4.0"/>
<remove name="OPTIONSVerbHandler"/>
<remove name="TRACEVerbHandler"/>
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="/*" verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0"/>
</handlers>
</system.webServer>
Note that the path is set to /*
and it works well when accessing custom OData functions on our ODataControllers
Nevertheless we also have an ApiController and when we access it, IIS doesn't properly handle the request and fails with the following details :
HTTP Error 500.0 - Internal Server Error
Internal Server ErrorDetailed Error Information:
Module ManagedPipelineHandler
Notification ExecuteRequestHandler
Handler ExtensionlessUrlHandler-Integrated-4.0
Error Code 0x800703e9
If I set the TransferRequestHandler
path
to *.
as suggested here the WebApi request get properly resolved however the ODataController request ends up not beeing found with HTTP 400 :
HTTP Error 404.4 - Not Found
The resource you are looking for does not have a handler associated with it.Detailed Error Information:
Module IIS Web Core
Notification MapRequestHandler
Handler Not yet determined
Error Code 0x80070002
How can I properly configure it to handle both cases ?
++++ Edit : ++++
For the sake of clarity here is the queries I use to tests my controllers :
- Custom odata function call :
http://localhost:xxxx/myProject/odata/SomeModels/MyNamespace.MyCustomFunction(parameterA=123,parameterB=123)
- Native odata GET call :
http://localhost:xxxx/myProject/odata/SomeModels
- Native web api GET call:
http://localhost:xxxx/myProject/api/SomeOtherModel?parameterC=123
My web api controller :
public class SomeOtherModelsController : ApiController
{
public IHttpActionResult Get(int parameterC)
{
// ...
return Ok(/* some result */);
}
[HttpPost]
public IHttpActionResult Post(SomeOtherModel model)
{
// ...
return Ok(/* some result */);
}
}
My odata controller:
public class SomeModelController : ODataController
{
[EnableQuery]
public IHttpActionResult Get()
{
// ...
return Ok(/* some result*/);
}
[HttpGet]
[EnableQuery]
public IHttpActionResult MyCustomFunction(int parameterA, int parameterB)
{
// ...
return Ok(/* some result */);
}
[HttpGet]
[EnableQuery]
public IHttpActionResult AnotherCustomFunction()
{
// ...
return Ok(/* some result */);
}
}
Here is the web api configuration:
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
and the odata configuration :
var builder = new ODataConventionModelBuilder
{
Namespace = "MyNamespace"
};
builder.EntitySet<SomeModelModel>("SomeModels");
var anotherCustomFunction = builder.EntityType<SomeModelModel>().Collection.Function("AnotherCustomFunction");
anotherCustomFunction.Returns<SomeResultValue>();
var myCustomFunction = builder.EntityType<SomeModel>().Collection.Function("MyCustomFunction");
myCustomFunction.Parameter<int>("parameterA");
myCustomFunction.Parameter<int>("parameterB");
myCustomFunction.ReturnsFromEntitySet<SomeModelModel>("SomeModels");