ASP.Core ODataControllers无法识别“按键获取”操作

时间:2019-05-25 13:30:14

标签: asp.net-core odata asp.net-core-webapi

我正在研究如何在ASP.Core中使用OData。

我创建了一个BooksController的子类,ODataController的子类,在其中定义了两个动作:Get()Get(int id)

/odata/books解析为第一个Action,但是/odata/books(1)找不到第二个Action。

一旦定义了模型,便可以找到以下控制器:

[ODataRoutePrefix("Books")]
public class BooksController : ODataController
{
    private BookStoreContext _db;

    public BooksController(BookStoreContext context)
    {
        _db = context;
    }

    [ODataRoute]
    [EnableQuery]
    public IActionResult Get()
    {
        return Ok(_db.Books);
    }

    [EnableQuery]
    [ODataRoute("({key})")]
    public IActionResult Get([FromODataUri] int key)
    {
        return Ok(_db.Books.FirstOrDefault(c => c.Id == key.ToGuid()));
    }
}

该站点具有所有路由的默认“约定”规则(请参见下文)。 但是我认为这没有作用,因为BooksController[ODataRoutePrefix("Books")]装饰,动作用[ODataRoute](和[EnableQuery])装饰-我认为,这是基于属性的路由,优先(这是正确的假设吗?)。

我的dto模型是使用Reflection ...进行注册的,但是关键部分是Startup调用UseMvc(...)并定义路由的地方,最终在这里调用:

private void CreateODataRoutes(IRouteBuilder routeBuilder)
{
    // register the convention routes for MVC first...
            routeBuilder.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
    ...

    // then do the OData stuff...

    routeBuilder.Count().Expand().Filter()
        .MaxTop(100).OrderBy().Select();

    // Use method further down the page 
    // to create a Build Model by reflection, using
    // all OData Model definitions (ie, classes that implement
    // IAllModulesOdataModelBuilderConfiguration)
    var oDataConventionModelBuilder = BuildODataModelUsingReflectionAcrossAllAssemblies();

    // Use the modelBuilder as the basis of defining routes:
    RegisterRoutesToODataController(routeBuilder, oDataConventionModelBuilder);
}

BuildODataModelUsingReflectionAcrossAllAssemblies使用反射来查找各个模型定义,每个模型定义都非常简单,仅定义其ID(其余部分依赖于约定)。

请注意,我并没有按照惯例定义动作(请参阅下文)。

    public class BookODataModelBuilderConfigurationBase<T> : IAllModulesOdataModelBuilderConfiguration
        where T : class, IHasGuidId, new()
    {

        public virtual void Apply(ODataModelBuilder builder ...) 
        {
            var _controllerName = this.GetControllerNameByConvention(typeof(Book));
            var entity = builder.EntitySet<T>(this._controllerName).EntityType;
            entity.HasKey(x => x.Id);
        //Note...no Actions defined, as planning to rely on default conventions (routing by Verb to method starting with Get...)
        }
    }

创建模型后,其注册如下;

        private void RegisterRoutesToODataController(IRouteBuilder routeBuilder,
            ODataConventionModelBuilder oDataConventionModelBuilder)
        {
            string routePrefix = $"{App.Modules.Core.Shared.Constants.ModuleSpecific.Module.AssemblyNamePrefix}.";

            // Build the Edm model used to parse commands:
            var edmModel = oDataConventionModelBuilder.GetEdmModel();

            // Register the Odata paths
            routeBuilder.MapODataServiceRoute(
                routeName: $"{routePrefix}odataDefault",
                routePrefix: "odata",
                edmModel,
                pathHandler:new DefaultODataPathHandler(),
                // By convention? So that Get verb goes to Get action, etc.
                routingConventions: ODataRoutingConventions.CreateDefault()
            );
        }

路径为/odata/book(1)时返回HTTP ERROR 404,该页面不存在。

谢谢!

我尝试过的其他事情包括:

  • 评论了SwaggerAPI的配置
  • 已删除关键参数上的[FromODataUri](有必要吗?)
  • 添加/删除了[ODataRoute("({key})")]
  • 以复数/单数形式将控制器注册为BooksController
  • 将操作的名称更改为GetBook,然后再次更改为Get
  • 添加/删除了ODataRoutePrefix
  • 在注册默认约定路由之前先注册OData路由(认为应该一直如此,对吧?)。
  • ...所有这些开始看起来更像是绝望而不是编码:-( ...
  • 仍在寻找。感谢您的指导。

1 个答案:

答案 0 :(得分:0)

OMG。 (嘶哑地)解决了。 它不是Framework,Nuget,Controller基类,routeprefix,route或任何光荣的东西,而是...我。 我唯一看不到的地方是模型本身,该模型将ID定义为Guid。该Action正在使用一个int,将其转换为Guid。 ASP.Core找不到它,因为它是基于模型(而不是控制器)构建路由,因此忽略了Action,因为它对于基于int!= Guid的基于约定的路由构建没有意义。嗯。

如果您想知道为什么我使用int ...那是因为当我为Db播种时,我想要一个Guid Key,但是出于测试目的,我希望某些记录具有特定的ID,我可以参考该ID。 ,而且我很懒惰,不想输入完整的Guid。

回想起来,这是一个愚蠢的主意...:-(

但是感谢您对此进行调查!感激所花费的时间。