C# 在运行时禁用OData V4元数据和控制器

C# 在运行时禁用OData V4元数据和控制器,c#,asp.net-web-api,asp.net-web-api2,odata,C#,Asp.net Web Api,Asp.net Web Api2,Odata,我们的软件中有几个模块作为单个产品提供。激活模块后,这些功能将可用。我们希望我们的ODataAPI遵循相同的模式。但是,我不知道如何使$metadata忽略已禁用模块的控制器。基本上,我想确定什么在任何时候都可用,而不是应用程序启动时 我们使用以下类型的cod来登记路线: static public void Register(HttpConfiguration config) { config.MapHttpAttributeRoutes();

我们的软件中有几个模块作为单个产品提供。激活模块后,这些功能将可用。我们希望我们的ODataAPI遵循相同的模式。但是,我不知道如何使$metadata忽略已禁用模块的控制器。基本上,我想确定什么在任何时候都可用,而不是应用程序启动时

我们使用以下类型的cod来登记路线:

    static public void Register(HttpConfiguration config)
    {
        config.MapHttpAttributeRoutes();
        var builder = new ODataConventionModelBuilder();
        builder.EntitySet<Module1Entity>("Module1Entities");
        builder.EntitySet<Module2Entity>("Module2Entities");
        config.MapODataServiceRoute("odata", "api", builder.GetEdmModel());
    }

    protected void Application_Start(object sender, EventArgs e)
    {
        GlobalConfiguration.Configure(Register);
    }
静态公共无效寄存器(HttpConfiguration配置)
{
config.maphttpAttribute路由();
var builder=新的ODataConventionModelBuilder();
builder.EntitySet(“模块1实体”);
builder.EntitySet(“模块2实体”);
config.MapODataServiceRoute(“odata”、“api”、builder.getedModel());
}
受保护的无效应用程序\u启动(对象发送方,事件参数e)
{
全局配置。配置(寄存器);
}
因此,如果模块已被激活,我们只希望Module1Entity显示在元数据中。我们已经有代码在模块停用时禁用相关控制器


有什么想法吗?

我最终找到了一个解决方案:

static public void Register(HttpConfiguration config)
{
    config.MapHttpAttributeRoutes();
    var builder = new ODataConventionModelBuilder();
    if (IsModule1Enabled)
    {
        builder.EntitySet<Module1Entity>("Module1Entities");
    {
    if (IsModule2Enabled)
    {
       builder.EntitySet<Module2Entity>("Module2Entities");
    }
    var conventions = ODataRoutingConventions.CreateDefault();
    conventions.Insert(0, new MyAttributeRoutingConvention("odata", config));
    config.MapODataServiceRoute("odata", "api", builder.GetEdmModel(), new DefaultODataPathHandler(), conventions);

}

public class MyAttributeRoutingConvention : AttributeRoutingConvention
{
    public MyAttributeRoutingConvention(string routeName, HttpConfiguration configuration) : base(routeName, configuration)
    {
    }

    public override bool ShouldMapController(HttpControllerDescriptor controller)
    {
       if (controller.ControllerType == typeof(Module1EntitiesController))
       {
          return IsModule1Enabled;
       }
       if (controller.ControllerType == typeof(Module2EntitiesController))
       {
          return IsModule2Enabled;
       }
       return base.ShouldMapController(controller);
    }
 }


protected void Application_Start(object sender, EventArgs e)
{
    GlobalConfiguration.Configure(Register);
}
静态公共无效寄存器(HttpConfiguration配置)
{
config.maphttpAttribute路由();
var builder=新的ODataConventionModelBuilder();
如果(IsModule1启用)
{
builder.EntitySet(“模块1实体”);
{
如果(IsModule2Enabled)
{
builder.EntitySet(“模块2实体”);
}
var conventions=ODataRoutingConventions.CreateDefault();
插入(0,新的MyAttributeRoutingConvention(“odata”,配置));
config.MapODataServiceRoute(“odata”、“api”、builder.GetEdmModel()、新的DefaultODataPathHandler()、约定);
}
公共类MyAttributeRoutingConvention:AttributeRoutingConvention
{
公共MyAttributeRoutingConvention(字符串routeName,HttpConfiguration配置):基本(routeName,配置)
{
}
公共覆盖布尔应映射控制器(HttpControllerDescriptor控制器)
{
if(controller.ControllerType==typeof(module1实体控制器))
{
返回为模块1启用;
}
if(controller.ControllerType==typeof(Module2EntitiesController))
{
返回为模块2启用;
}
返回基。ShouldMapController(控制器);
}
}
受保护的无效应用程序\u启动(对象发送方,事件参数e)
{
全局配置。配置(寄存器);
}

我终于找到了更简单的方法

此启动代码ovveride OData$禁止元数据路径和返回响应

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
            endpoints.EnableDependencyInjection();
            endpoints.Select().Filter().OrderBy().Count().MaxTop(24);
            endpoints.MapODataRoute("ODataRoute", "odata", GetEdmModel());
            endpoints.MapGet("/odata/$metadata", async context =>
            {
                context.Response.StatusCode = 403;
                await context.Response.WriteAsync("Forbidden!");
            });
            endpoints.MapGet("/", context =>
            {
                context.Response.Redirect("/swagger");
                return Task.CompletedTask;
            });
        });

您不能对API路由使用自定义路由约束吗?如果您的功能未启用,它将与url不匹配,请求将失败。我将在有时间时发布一个示例。我还想禁用odata实体的元数据。我不希望在对根odata url执行get请求时列出路由。