Search code examples
c#asp.net-coreodata

ASP.NET Odata multiple sub routes


I'm trying to expose multiple databases through Odata Web API. Now I want to divide each of my databases into a seperate sub url. I already defined the necessary IEdm Models and Controllers. The API is working as intended while I'm only using a single Odata Url.

My approach for using multiple sub urls is this:

    app.UseMvc(c =>
        {
            c.EnableDependencyInjection();
            c.Expand().Select().OrderBy().Filter().Count().MaxTop(null).SetTimeZoneInfo(timeZone);
            c.MapODataServiceRoute("Database1", "api/v1/Database1", Database1.GetModel());
            c.MapODataServiceRoute("Database2", "api/v1/Database2", Database2.GetModel());
        });

But when I'm trying to access the metadata for database 2 I'm getting InvalidOperationException, because some templates are only defined in the controller for database 1 and not in the controller for database 2.

My controller for database 1 looks like this:

    public class Database1Controller : ODataController
    {
        private Database1Context Context = new Database1Context();

        [EnableQuery]
        [ODataRoute(DB1Entity1.ApiSubUrl)]
        public IQueryable<DB1Entity1> GetEntity1()
        {
            return Context.Entity1.AsQueryable();
        }

        [EnableQuery]
        [ODataRoute(DB1Entity2.ApiSubUrl)]
        public IQueryable<DB1Entity2> GetEntity2()
        {
            return Context.Entity2.AsQueryable();
        }
    } 

And my controller for database 2 looks like this:

    public class Database2Controller : ODataController
    {
        private Database2Context Context = new Database2Context();

        [EnableQuery]
        [ODataRoute(DB2Entity1.ApiSubUrl)]
        public IQueryable<DB2Entity1> GetEntity1()
        {
            return Context.Entity1.AsQueryable();
        }
    }

I can access the metadata and all controller functions for the api/v1/Database1 url, but can't access metadata or controller functions for api/v1/Database2 url.


Solution

  • The solution for multiple sub urls is to limit the odata route verification of a controller method to the specific route.

    So controller 1 would look like this:

    public class Database1Controller : ODataController
    {
        private Database1Context Context = new Database1Context();
    
        [EnableQuery]
        [ODataRoute(DB1Entity1.ApiSubUrl, RouteName = "Database1")]
        public IQueryable<DB1Entity1> GetEntity1()
        {
            return Context.Entity1.AsQueryable();
        }
    
        [EnableQuery]
        [ODataRoute(DB1Entity2.ApiSubUrl, RouteName = "Database1")]
        public IQueryable<DB1Entity2> GetEntity2()
        {
            return Context.Entity2.AsQueryable();
        }
    }