Getting related entities ASP.NET WebApi OData v4 results in “No HTTP resource was found that matches the request URI”

前端 未结 2 1057
猫巷女王i
猫巷女王i 2021-01-02 09:02

I followed this asp.net tutorial by Mike Wasson, and managed to set up the related entities just fine, but when I applied this logic to my project the more complex entity re

2条回答
  •  甜味超标
    2021-01-02 09:51

    As I mention in the question, I tried many solutions to get this to work, but none were consistent in actually solving the problem and I kept avoiding the solution laid out in this SO question/answer because the tutorial is specifically for v4 and I figured that answer must be for an older version (how unwise).

    So that answer does solve the problem, but requires some work to fit directly into OData v4 and an ODataConventionModelBuilder; this is why I have posted this question and answer; to provide a solution, specifically for OData v4 and ODataConventionModelBuilder, in the hope that others won't lose the time I have looking into this.

    First, set up your EdmModel:

    private static IEdmModel GetEdmModel()
    {
        var builder = new ODataConventionModelBuilder();
        builder.EnableLowerCamelCase();
        builder.EntitySet("Menus");
        builder.EntitySet("MenuPermissions");
        var edmModel = builder.GetEdmModel();
        AddNavigations(edmModel); //see below for this method
        return edmModel;
    }
    

    Second AddNavigations:

    private static void AddNavigations(IEdmModel edmModel)
    {
        AddMenuPermissionsNavigation(edmModel);
    }
    
    private static void AddMenuPermissionsNavigation(IEdmModel edmModel)
    {
        var menus = (EdmEntitySet) edmModel.EntityContainer.FindEntitySet("Menus");
        var menuPermissions = (EdmEntitySet)edmModel.EntityContainer.FindEntitySet("MenuPermissions");
        var menuType = (EdmEntityType) edmModel.FindDeclaredType("iiid8.cms.data.models.Menu"); //"iiid8.cms.data.models" is the C# namespace
        var menuPermissionType = (EdmEntityType)edmModel.FindDeclaredType("iiid8.cms.data.models.MenuPermission"); //as above, "iiid8.cms.data.models" is the C# namespace
        AddOneToManyNavigation("MenuPermissions", menus, menuPermissions, menuType, menuPermissionType);
        AddManyToOneNavigation("Menu", menus, menuPermissions, menuType, menuPermissionType);
    }
    
    private static void AddOneToManyNavigation(string navTargetName, EdmEntitySet oneEntitySet, EdmEntitySet manyEntitySet,
        EdmEntityType oneEntityType, EdmEntityType manyEntityType)
    {
        var navPropertyInfo = new EdmNavigationPropertyInfo
        {
            TargetMultiplicity = EdmMultiplicity.Many,
            Target = manyEntityType,
            ContainsTarget = false,
            OnDelete = EdmOnDeleteAction.None,
            Name = navTargetName
        };
        oneEntitySet.AddNavigationTarget(oneEntityType.AddUnidirectionalNavigation(navPropertyInfo), manyEntitySet);
    }
    
    private static void AddManyToOneNavigation(string navTargetName, EdmEntitySet oneEntitySet, EdmEntitySet manyEntitySet,
        EdmEntityType oneEntityType, EdmEntityType manyEntityType) {
        var navPropertyInfo = new EdmNavigationPropertyInfo {
            TargetMultiplicity = EdmMultiplicity.One,
            Target = oneEntityType,
            ContainsTarget = false,
            OnDelete = EdmOnDeleteAction.None,
            Name = navTargetName
        };
        manyEntitySet.AddNavigationTarget(manyEntityType.AddUnidirectionalNavigation(navPropertyInfo), oneEntitySet);
    }
    

    Finally, call GetEdmModel from WebApiConfig.Register

    config.MapODataServiceRoute("odata", null, GetEdmModel());
    

    Now call your OData service's one-to-many and many-to-one navigations from your client and all should be good with your world. In my case the calls look like this:

    One-to-many:

    http://localhost:19215/Menus(c94f7f98-6987-e411-8119-984be10349a2)/MenuPermissions
    

    Many-to-one:

    http://localhost:19215/MenuPermissions(ba0da52a-6c87-e411-8119-984be10349a2)/Menu
    

    This answer assumes you set up the rest of your project just like Mike Wasson suggests in the tutorial linked in the question (that link is to Part 3 - you will need to follow Part 1 first!).

提交回复
热议问题