I have an application where I need to add OData routes dynamically. I can add regular routes after Application_Start just fine, but am having trouble doing it with OData routes.
Here's how I'm trying to dynamically add OData Web Api routes. In my WebApiConfig, I add a Products route:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
var builder = new ODataConventionModelBuilder();
builder.EntitySet<Product>("Products");
config.MapODataServiceRoute(routeName: "ProductsRoute", routePrefix: "odata", model: builder.GetEdmModel());
}
}
Then in my ProductsController, I add the following call in the Products GET method, which is successfully called when I go to http:///odata/Products (yeah, a little weird, but it's one way to demonstrate adding a route after Application_Start):
GlobalConfiguration.Configure(WebApiConfig.AddOrderRoute);
The WebApiConfig.AddOrderRoute method gets called correctly and executes without error:
public static void AddOrderRoute(HttpConfiguration config)
{
var builder = new ODataConventionModelBuilder();
builder.EntitySet<Order>("Orders");
config.MapODataServiceRoute(routeName: "OrdersRoute", routePrefix: "odata", model: builder.GetEdmModel());
config.EnsureInitialized();
}
So you'd think that now I have an Orders route correctly configured. But when I go to http:///odata/Orders, I get the following error:
ExceptionMessage=The object has not yet been initialized.
Ensure that HttpConfiguration.EnsureInitialized() is called in the
application's startup code after all other initialization code.
StackTrace= at System.Web.OData.Routing.Conventions.AttributeRoutingConvention.get_AttributeMappings()
at System.Web.OData.Routing.Conventions.AttributeRoutingConvention.SelectController(ODataPath odataPath, HttpRequestMessage request)
at System.Web.OData.Routing.ODataPathRouteConstraint.SelectControllerName(ODataPath path, HttpRequestMessage request)
at System.Web.OData.Routing.ODataPathRouteConstraint.Match(HttpRequestMessage request, IHttpRoute route, String parameterName, IDictionary`2 values, HttpRouteDirection routeDirection)
at System.Web.Http.Routing.HttpRoute.ProcessConstraint(HttpRequestMessage request, Object constraint, String parameterName, HttpRouteValueDictionary values, HttpRouteDirection routeDirection)
at System.Web.Http.Routing.HttpRoute.ProcessConstraints(HttpRequestMessage request, HttpRouteValueDictionary values, HttpRouteDirection routeDirection)
at System.Web.Http.Routing.HttpRoute.GetRouteData(String virtualPathRoot, HttpRequestMessage request)
at System.Web.Http.WebHost.Routing.HttpWebRoute.GetRouteData(HttpContextBase httpContext)
Note that I'm calling config.EnsureInitialized()
in AddOrderRoute.
What am I missing?
NOTE: If I call AddOrderRoute at the end of WebApiConfig.Register() method, my Orders route is available and working, so I know that my Order entity, context and controller are working fine. It's only when I call it once application initialization is done that I get the problem.
Well, I spent some time with the good folks over at MSDN and got an answer!
Here's the way the Orders entity route needs to be registered:
var builder = new ODataConventionModelBuilder();
builder.EntitySet<Order>("Orders");
var route = config.Routes.Where(r => r is System.Web.OData.Routing.ODataRoute).First();
var odataRoute = route as System.Web.OData.Routing.ODataRoute;
config.MapODataServiceRoute(
routeName: "OrdersRoute",
routePrefix: "odata",
model: builder.GetEdmModel(),
pathHandler: odataRoute.PathRouteConstraint.PathHandler,
routingConventions: odataRoute.PathRouteConstraint.RoutingConventions);
Nice. Now .../odata/Orders can be accessed no problem.
As we talked in the comment, multiple entities of the same route:
public static void Register(HttpConfiguration config)
{
var builder = new ODataConventionModelBuilder();
builder.EntitySet<Product>("Products");
builder.EntitySet<Order>("Orders");
config.MapODataServiceRoute(routeName: "OData", routePrefix: "odata", model: builder.GetEdmModel());
}
Then you can issue both requests:
1. http:///odata/Products and
2. http:///odata/Orders
来源:https://stackoverflow.com/questions/25293477/how-to-dynamically-add-odata-web-api-routes-after-application-start