OData / ODataSamples

Samples: For ODataLib, OData Web API, RESTier, etc.
http://odata.github.io/
Other
293 stars 222 forks source link

Possible to use different EdmModels in OData routes? #73

Open wierzba3 opened 5 years ago

wierzba3 commented 5 years ago

We have a need to restrict a certain subset of our OData API surface for one route prefix. We wish to return 404 when an API is accessed that is not supported for that route. We need to know how we can (and how we should) accomplish this.

  1. Option: use a second EdmModel that defines subset of operations, and map the model to one route prefix.

See the code below. This does not work. When we swap in the old model, we see errors that appear to indicate that OData expects ALL OData functionality to be mapped in the model. The error is

"The path template 'products' on the action 'GetProducts' in controller 'Products' is not a valid OData path template. Resource not found for the segment 'products'.)"

Where products are intentionally excluded from the model. We desire a 404 response for this api "/api/subset/products", but instead, the service crashes on startup due to the error above.

protected override void Register(HttpConfiguration config)
{
    base.Register(config);

    // Map route 1 to model
    var model = GetModel();
    var modelConventions = ODataRoutingConventions.CreateDefaultWithAttributeRouting(config, model);
    config.MapODataServiceRoute(
        routeName: "full",
        routePrefix: "api",
        model: model, // use standard full model
        pathHandler: new MyCustomBIODataPathHandler(), 
        routingConventions: conventions);

    // Map route 2 to a different model 
    var subsetModel = GetSubsetModel(); // different EdmModel
    var subsetModelConventions = ODataRoutingConventions.CreateDefaultWithAttributeRouting(config, subsetModel);
    config.MapODataServiceRoute(
        routeName: "partial",
        routePrefix: "api/subset", 
        model: partialModel, // using the different EdmModel
        pathHandler: new MyCustomBIODataPathHandler(), 
        routingConventions: subsetModelConventions);
}

Is this not supported?

If not, what other options are there to accomplish this? Must we explicitly return 404 in the controller API function? (this would require analyzing the path for "api/subset" in the API function, which seems to me like a hack)

phatcher commented 5 years ago

I do this on my models but you have to introduce another layer e.g. /api/assets, /api/workflow etc rather than having an implicit default of /api.

To my mind this makes discovery easier and also implies the separation between the two parts of the API