在运行时禁用 OData V4 元数据和控制器
Disabling OData V4 meta data and controllers at runtime
我们的软件中有多个模块作为单个产品提供。当一个模块被激活时,这些功能就可用了。我们希望我们的 OData API 遵循相同的模式。但是我不知道如何让 $metadata 忽略已禁用模块的控制器。基本上我想确定什么是随时可用的,而不是应用程序启动时间。
我们使用以下类型的鳕鱼来注册路线:
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);
}
因此,如果模块已激活,我们只希望 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);
}
终于找到更简单的方法了。
此启动代码 ovveride OData $元数据路径和 return 禁止响应。
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;
});
});
我们的软件中有多个模块作为单个产品提供。当一个模块被激活时,这些功能就可用了。我们希望我们的 OData API 遵循相同的模式。但是我不知道如何让 $metadata 忽略已禁用模块的控制器。基本上我想确定什么是随时可用的,而不是应用程序启动时间。
我们使用以下类型的鳕鱼来注册路线:
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);
}
因此,如果模块已激活,我们只希望 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);
}
终于找到更简单的方法了。
此启动代码 ovveride OData $元数据路径和 return 禁止响应。
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;
});
});