最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

c# - OData Generic Controller registration - Stack Overflow

programmeradmin2浏览0评论

I upgraded to .NET 8.0 and I also updated my OData packages to 8.*, now before I used to register a generic OData controller for all my OData entities (OData entities have IODataView interface, so I used to get them all by reflection and register a controller per IODataView), I register the controller per entity like this

foreach (var type in oDataEntities)
{
    feature.Controllers.Add(typeof(GenericODataController<>).MakeGenericType(type).GetTypeInfo());
}

Then after doing this I also set the routes for the controllers like this

// OData endpoint registration
var route = $"odata/{genericType.Name.Replace("V_", "").Singularize()}";
controller.Selectors.Add(new SelectorModel
                {
                    AttributeRouteModel = new AttributeRouteModel(new RouteAttribute(route)),
                });
controller.ControllerName = genericType.Name;

This used to work fine with previous versions, but with the new OData Nuget package, I cannot get it to work. Strange thing is if I create the controller manually it works.

This is my generic controller:

// [AllowAnonymous]
public class GenericODataController<TViewEntity> : BaseODataController<TViewEntity> where TViewEntity : class
{
    public GenericODataController(IBaseSphereDbContext dbContext) 
        : base(dbContext)
    {
    }
}

This is the base class:

public abstract class BaseODataController<TViewEntity>(IBaseSphereDbContext dbContext) : ODataController
    where TViewEntity : class
{
    [EnableQuery]
    //[ODataAttributeRouting]
    [HttpGet]
    public IQueryable<TViewEntity> Get()
    {
        return dbContext.Set<TViewEntity>().AsQueryable().AsNoTracking();
    }
}

And this is the working controller:

[Route("odata/NavigationViewConfig")]
public class NavigationViewConfigODataController(IBaseSphereDbContext dbContext) : ODataController
{
    [EnableQuery]
    [HttpGet]
    public IQueryable<V_NavigationViewConfig> Get()
    {
        return dbContext.Set<V_NavigationViewConfig>().AsQueryable().AsNoTracking();
    }
}

When I try the OData debug endpoint, the generic registered OData controllers which do inherit from ODataController, do not show, while the manually created one shows NavigationViewConfigODataController as an OData endpoint.

I think something changed in the newest libraries on how a controller is linked to an OData EDM. If someone has any knowledge about how I can get this to work it would be really appreciated.

PS: I also had a look at their samples:

They have one for dynamic model but its different, they use one controller for everything. not register a controller per OData entity..

Update: this is how EDM is added (edm contains all types that inherit from ODataView)

var edmModel = GetEdmModel();
services.AddControllers(options =>
            {
                options.Conventions.Add(new GenericControllerRouteConvention());
            })
            .AddOData(opt => opt.Count().Filter().Expand().Select().OrderBy().SetMaxTop(60)
                .AddRouteComponents("odata", edmModel)
            )
            .AddApplicationPart(assembly)
            .ConfigureApplicationPartManager(m =>
                m.FeatureProviders.Add(new GenericTypeControllerFeatureProvider()))
            .AddNewtonsoftJson(opt => opt.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore);

GetEdm does this to be more detailed:

public static ODataConventionModelBuilder GetODataEdmBuilder()
{
    // 
    
    var odataBuilder = new ODataConventionModelBuilder();
    odataBuilder.EnableLowerCamelCase();
        
    var odataViews = ReflectionHelper.GetAllODataViewEntities();
    var entitySetMethod = typeof(ODataModelBuilder)
            .GetMethods()
            .First(m => m.Name == "EntitySet" && m.IsGenericMethod);

    foreach (var entityType in odataViews)
    {
        var name = entityType.Name.Replace("V_", "");
        var genericMethod = entitySetMethod.MakeGenericMethod(entityType);
        genericMethod.Invoke(odataBuilder, new object[] { name });
    }

    return odataBuilder;
}
发布评论

评论列表(0)

  1. 暂无评论