2
votes

I have a lot of different entities that I want to enable OData for. These entities are categorized into different groups based on their type. Currently, the default is to match the EntitySet with the controller name, but I don't want a controller for every entity type that I'll have. Is there a way I can map multiple EntitySets to one controller.

I've tried having the types I'm interested in implement a common interface and specified that interface as my entity set type. I also tried having two entities within one controller and with their own get requests, but no luck. I also tried defining my own routing class that extends EntitySetRoutingConvention, but haven't gotten that to work.

WebApiConfig

    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // Web API configuration and services

            ODataConventionModelBuilder builder = new ODataConventionModelBuilder();

            builder.EntitySet<MyEntity1>("MyEntity1");
            builder.EntitySet<MyEntity2>("MyEntity2");
            config.Routes.MapODataServiceRoute("odata", "odata", builder.GetEdmModel());
            // Web API routes
            config.MapHttpAttributeRoutes();
        }

This looks for controllers named MyEntity1Controller and MyEntity2Controller. What I want is something like:

    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // Web API configuration and services

            ODataConventionModelBuilder builder = new ODataConventionModelBuilder();

            builder.EntitySet<MyEntity1>("Generic");
            builder.EntitySet<MyEntity2>("Generic"); // Throws an error since Generic is already registered to MyEntity1
            config.Routes.MapODataServiceRoute("odata", "odata", builder.GetEdmModel());
            // Web API routes
            config.MapHttpAttributeRoutes();
        }

GenericController.cs

// GET: odata/myentity1
        [EnableQuery]
        public IQueryable<MyEntity1> GetMyEntity1()
        {
            return db.MyEntity1.AsQueryable();
        }

        // GET: odata/myentity2
        [EnableQuery]
        public IQueryable<myentity2> GetMyEntity2()
        {
            return db.MyEntity2.AsQueryable();
        }

The expected results would be I can go to myurl/Generic/MyEntity1 and that would hit a GET request in my Generic Controller. I should also be able to perform odata operations such as myurl/Generic/MyEntity1?$select=Id.

1
I think that violates the concept of OData. But you can more or less achieve what you want if entities have a common parent, something like url/parents(1)/entities1, url/parents(1)/entities2, etc. - Gert Arnold

1 Answers

0
votes

Add the ODataRoute Attribute

/// MyController.cs

// GET: odata/myentity1
[EnableQuery]
[ODataRoute("myentity1")]
public IQueryable<MyEntity1> GetMyEntity1() => db.MyEntity1.AsQueryable();

// GET: odata/myentity2
[EnableQuery]
[ODataRoute("myentity1")]
public IQueryable<MyEntity2> GetMyEntity2() => db.MyEntity2.AsQueryable();