MVC and OData, side by side



我们已经有一组MVC API,但是我被要求添加ODATA版本。我正在尝试将这两个集合在同一应用程序中共享,以共享自定义角色提供商之类的内容。我是Odata的新手,到目前为止,MVC课程似乎并没有直接翻译。

使用MVC,我们进行了通用初始化,并用RouteatTribute管理了所有路线,我尝试使用OdatarOuteatTribute进行相同的样式,但是我所有的ODATA路径都出现了404,并且$ Metadata Query返回了500个,说配置HASN'HASN''t被初始化。

这是应用程序启动配置块(MVC之后添加了Odataapiconfig):

AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
ODataApiConfig.Configure(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
GlobalConfiguration.Configuration.EnsureInitialized();

这就是Odataapiconfig中的内容:

// OData v7 replacement for configuration.EnableCaseInsensitive(true);
configuration.MapODataServiceRoute("odata", "odata",
        builder =>
                builder.AddService<IEnumerable<IODataRoutingConvention>>(ServiceLifetime.Singleton, sp => ODataRoutingConventions.CreateDefaultWithAttributeRouting("odata", configuration))
                    .AddService<ODataUriResolver>(ServiceLifetime.Singleton, sp => new CaseInsensitiveResolver())
            );
ODataModelBuilder modeler = new ODataConventionModelBuilder();
modeler.EntitySet<Task>("Tasks");
configuration.MapODataServiceRoute(
        routeName: "ODataRoute",
          routePrefix: "odata",
          model: modeler.GetEdmModel()
);
configuration.EnsureInitialized();

这是我要连接的API的示例(获取分配给员工的任务列表):

[HttpGet]
[EnableQuery]
[ODataRoute("v0.1/employee/{userGuid}/tasks")]
[ODataAuthorize(Roles = "Assignee")]
public IHttpActionResult GetMyTasks([FromODataUri]string userGuid)
{
    ...
}

所以我很困惑为什么a)呼叫〜/odata/$元数据抛出"尚未初始化对象。确保httpconfiguration.ensureinitialization()在应用程序的启动代码中在所有其他初始化代码后都调用。"我尝试在ODATA/MVC初始化和ODATA初始化例程的末尾调用SuseInitialization(),但仍会引发相同的错误。

b)我的〜/odata/雇员/{userguid}/任务路径出现404。

任何指针都将不胜感激。

谢谢

编辑:看来〜/odata/$元数据异常与使用[odataroute]属性有关。默认情况下似乎可以启用(并导致例外);当我尝试明确创建一个路由会议对象并进行di-iping时,$元数据异常就消失了。产生太多有用,但例外消失了。

例外的堆栈跟踪在下面;我尝试闯入任何无效的脱落,但没有在调试器中休息

{"Message":"An error has occurred.","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.","ExceptionType":"System.InvalidOperationException","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)rn   at System.Web.Http.Routing.HttpRoute.GetRouteData(String virtualPathRoot, HttpRequestMessage request)
at System.Web.Http.WebHost.Routing.HttpWebRoute.GetRouteData(HttpContextBase httpContext)"}

编辑:至少我在$ Metadata调用上有一个答案。

我的初始化序列已得到本文的告知:https://blogs.msdn.microsoft.com/davidhardin/2014/2014/12/17/web-api-api-odata-v4-v4-v4-v4-lesson-lersons-learned/

说您必须先初始化Web API调用。我发现了相反的。上述例外是首先初始化Web API的结果。当我翻转它们时,$元数据电话开始返回我的任务实体集。

不幸的是,我的TaskScontroller中的[Odataroute]声明仍未被路由。

好吧,问题似乎是这里的某些建议是远面的:https://blogs.msdn.microsoft.com/davidhardin/2014/12/17/web-api-odata-v4-v4-lesson-learned/

具体来说,$元数据异常是通过在 Web API之后设置ODATA 引起的(根据上述文章)。您必须在 web api之前初始化odata

第二,关于控制器发现与路由前缀区分的要点是错误的。i did 将我的Web API控制器和ODATA控制器隔离在不同的目录中,并且我确实使用RoutePrefix/odatarouteprefix将它们放在不同的路径上。

但是,从GitHub获取了属性的源代码并将其用于调试之后,我找到了以下内容:

如果您有2个具有相同类名称的控制器(例如,两者都称为TaskController),即使它们具有不同的前缀路径并生活在不同的目录中,它们也会碰撞。两者都从处理中静静地掉下来,因此当请求进来时找不到它们。因此,404。

因此,无论前缀和路由属性如何,都需要以不同的方式命名才能包括在内。

最新更新