OData v4 Routing Prefix?

Xorcist picture Xorcist · Apr 7, 2015 · Viewed 12k times · Source

I have a side-by-side Web API 2.2 APIController and OData v4 ODataController. My APIController uses routing attributes internally like this (there are no predefined routing defaults):

  [RoutePrefix("api")]
  public class MyController : ApiController
  {
    [HttpGet]
    [Route("My")]
    public IHttpActionResult Get()
    {
      //Code Here
    }

    [HttpGet]
    [Route("My")]
    public IHttpActionResult Get([FromUri] String mykey)
    {
      //Code Here
    }
  }

and as such are routed to through ./api/My and ./api/My/?mykey=value

and I've tried setting up my ODataController to follow a similar suit with:

  [ODataRoutePrefix("My")]
  public class oMyController : ODataController {

    [HttpGet]
    public IHttpActionResult Get(ODataQueryOptions<FileModel> queryOptions) {
      //Code Here
    }

    [HttpGet]
    [ODataRoute("({mykey})")]
    public IHttpActionResult Get([FromODataUri] String mykey) {
      //Code Here
    }
  }

defining odata route ahead of time like this:

  ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
  builder.EntitySet<MyModel>("My");
  config.MapODataServiceRoute(
    routeName: "ODataRoute",
    routePrefix: "odata",
    model: builder.GetEdmModel()
  );

but attempts to access ./odata/My and ./odata/My(value) end up going into my APIController instead of the ODataController.

How can I route these using the different prefixes, but the same name, and have them go to the appropriate controllers. I don't want to have a different name for each route if I can prevent it, the prefixes should take care of everything, but for some reason they're not.

Answer

Xorcist picture Xorcist · Apr 7, 2015

You need to specify the ODataRoute attribute, even if it's empty:

[ODataRoutePrefix("My")]
public class oMyController : ODataController {

  [HttpGet]
  [ODataRoute()] // <---<< This was the key to proper OData routing
  public IHttpActionResult Get(ODataQueryOptions<FileModel> queryOptions) {
    //Code Here
  }

  [HttpGet]
  [ODataRoute("({mykey})")]
  public IHttpActionResult Get([FromODataUri] String mykey) {
    //Code Here
  }

}