MVC和OData,并排

时间:2016-12-24 14:48:55

标签: c# asp.net-mvc odata

我们已经有了一套MVC apis,但我已被要求提供OData版本。我试图在同一个应用程序中共同定位两个集合,以共享自定义角色提供程序之类的东西。我是OData的新手,到目前为止MVC课程似乎没有直接翻译。

使用MVC,我们采用了泛型初始化并使用RouteAttribute管理所有路由,我尝试使用ODataRouteAttribute进行相同的样式,但是我的所有odata路径都出现了404而$元数据查询返回500表示配置没有&# 39;已初始化。

这里是app start配置块(在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 / $ metadata的调用抛出&#34;该对象尚未初始化。确保在所有其他初始化代码之后在应用程序的启动代码中调用HttpConfiguration.EnsureInitialized()。&#34;我尝试在OData / MVC初始化结束时和OData初始化例程内调用EnsureInitialized(),它仍然会抛出相同的错误。

b)我的〜/ odata / employees / {userGuid} / tasks路径出现了404。

任何指针都将受到赞赏。

由于

编辑:〜/ odata / $元数据异常似乎与[ODataRoute]属性的使用有关。这似乎默认启用(并导致异常);当我尝试显式创建路由约定对象并对其进行DI-ing时,$ metadata异常消失了。没有产生很多用处,但例外情况消失了。

异常的堆栈跟踪如下;我尝试打破任何抛出的InvalidOperationExceptions但在调试器中没有中断

{"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)\r\n   at System.Web.Http.Routing.HttpRoute.GetRouteData(String virtualPathRoot, HttpRequestMessage request)
at System.Web.Http.WebHost.Routing.HttpWebRoute.GetRouteData(HttpContextBase httpContext)"}

编辑:至少我在$元数据调用上得到了答案。

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

表示你必须首先初始化Web Api调用。我找到了相反的结果。上面的异常是首先初始化Web Api的结果。当我翻转它们时,$ metadata调用开始返回我的Task实体集。

不幸的是,我的TasksController中的[ODataRoute]声明仍然没有被路由。

1 个答案:

答案 0 :(得分:0)

好的,问题似乎是这里的一些建议已经过时了: https://blogs.msdn.microsoft.com/davidhardin/2014/12/17/web-api-odata-v4-lessons-learned/

具体来说,$元数据异常是由于在 Web API之后设置OData 引起的(根据上述文章)。您必须在 Web Api之前初始化OData

其次,关于控制器发现路由前缀差异的观点是错误的。我做了将我的web api控制器和odata控制器隔离在不同的目录中,我确实使用RoutePrefix / ODataRoutePrefix将它们放在不同的路径上。

但是从github获取AttributeRoutingConvention的源代码并使用它进行调试后,我发现了以下内容:

如果您有2个具有相同类名的控制器(例如两者都称为TaskController),即使它们具有不同的前缀路径并且位于不同的目录中,它们也会发生冲突。两者都从处理中静默删除,因此在请求进入时找不到它们。因此404。

因此,无论前缀和路由属性如何,都需要以不同的方式命名类以包含它们。