如何在* Application_Start之后动态添加OData Web Api路由*?

时间:2014-08-13 18:26:02

标签: dynamic asp.net-web-api routes odata

我有一个应用程序需要动态添加OData路由。我可以在Application_Start之后添加常规路由,但是使用 OData 路由时遇到了麻烦。

以下是我尝试动态添加OData Web Api路由的方法。在我的WebApiConfig中,我添加了一个Products路线:

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());
    }
}

然后在我的ProductsController中,我在Products GET方法中添加以下调用,当我转到http:/// odata / Products时成功调用(是的,有点奇怪,但它是单向的)演示在Application_Start之后添加路由:

GlobalConfiguration.Configure(WebApiConfig.AddOrderRoute);

正确调用WebApiConfig.AddOrderRoute方法并执行且没有错误:

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();
}

所以你认为我现在正确配置了Orders路线。但是当我转到http:/// odata / Orders时,我收到以下错误:

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)

请注意,我在AddOrderRoute中调用config.EnsureInitialized()

我错过了什么?

注意:如果我在WebApiConfig.Register()方法结束时调用AddOrderRoute,我的Orders路由可用并正常工作,所以我知道我的Order实体,上下文和控制器工作正常。只有在我完成应用程序初始化后才调用它才能解决问题。

2 个答案:

答案 0 :(得分:5)

好吧,我花了一些时间和好心人一起来MSDN并得到答案!

这是Orders实体路线需要注册的方式:

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);

尼斯。现在...... / odata /订单可以访问没问题。

答案 1 :(得分:0)

正如我们在评论中所说,同一路线的多个实体:

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());
}

然后你可以发出两个请求:

1. http:///odata/Products and 
2. http:///odata/Orders