gpt4 book ai didi

c# - .Net Core 覆盖通用 Controller 的 Controller 路由

转载 作者:太空狗 更新时间:2023-10-29 23:20:07 27 4
gpt4 key购买 nike

我正在编写一个 RestFramework,我正在尝试弄清楚如何允许用户为通用 Controller 创建自定义名称。我正在像这样注册我的通用 Controller :

public class GenericControllerFeatureProvider : IApplicationFeatureProvider<ControllerFeature>
{
public void PopulateFeature(IEnumerable<ApplicationPart> parts, ControllerFeature feature)
{
foreach (var entityConfig in _entityConfigurations)
{
var entityType = entityConfig.Type;
var typeName = entityType.Name + "Controller";
if (!feature.Controllers.Any(t => t.Name == typeName))
{
var controllerType = typeof(GenericController<>)
.MakeGenericType(entityType.AsType())
.GetTypeInfo();

//Normally I would expect there to be an overload to configure the controller name
//feature.Controllers.Add(controllerType, entityConfig.ControllerName);
}
}
}
}

我怎么需要想出一种方法来覆盖 Controller 的路由。文档中关于此的唯一信息显示了如何创建 Controller 约定,如下所示:

public class GenericControllerNameConvention : Attribute, IControllerModelConvention
{
public void Apply(ControllerModel controller)
{
if (controller.ControllerType.GetGenericTypeDefinition() !=
typeof(GenericController<>))
{
return;
}

var entityType = controller.ControllerType.GenericTypeArguments[0];
controller.ControllerName = entityType.Name;
}
}

这是行不通的,因为它是在编译时完成的。我需要用户能够在启动时覆盖 Controller 名称,我该如何实现?

最佳答案

根据您的评论和代码,您的实现方式几乎不相上下。请注意,我已将示例缩减了很多,以便我可以设置测试。

假设我有一个基本的通用 Controller :

public class GenericController<T> : Controller
where T: class
{

public IActionResult Get()
{
return Content(typeof(T).FullName);
}
}

我现在有一个带有 Get 操作的类型化 Controller 。现在你的大部分代码都是正确的。所以我的功能提供者为(注意我有一个静态类型数组):

public class GenericControllerFeatureProvider : IApplicationFeatureProvider<ControllerFeature>
{
public void PopulateFeature(IEnumerable<ApplicationPart> parts, ControllerFeature feature)
{
foreach (var entityConfig in ControllerEntity.EntityTypes)
{
var entityType = entityConfig;
var typeName = entityType.Name + "Controller";
if (!feature.Controllers.Any(t => t.Name == typeName))
{
var controllerType = typeof(GenericController<>)
.MakeGenericType(entityType)
.GetTypeInfo();

feature.Controllers.Add(controllerType);
}
}
}
}

接下来是 IControllerModelConvention 实现。

public class GenericControllerModelConvention : IControllerModelConvention
{
public void Apply(ControllerModel controller)
{
if (!controller.ControllerType.IsGenericType || controller.ControllerType.GetGenericTypeDefinition() != typeof(GenericController<>))
{
return;
}

var entityType = controller.ControllerType.GenericTypeArguments[0];
controller.ControllerName = entityType.Name + "Controller";
controller.RouteValues["Controller"] = entityType.Name;
}
}

最后,初创公司是所有魔法发生的地方。基本上我们将 IControllerModelConvention 注册到 MVC 约定选项中,然后注册 FeatureProvider

public void ConfigureServices(IServiceCollection services)
{
var mvcBuilder = services.AddMvc();
mvcBuilder.AddMvcOptions(o => o.Conventions.Add(new GenericControllerModelConvention()));
mvcBuilder.ConfigureApplicationPartManager(c =>
{
c.FeatureProviders.Add(new GenericControllerFeatureProvider());
});
}

在我的评论中,有两件事让我印象深刻。

  1. 我不确定您为什么将 GenericControllerNameConvention 作为属性?
  2. 您应该隐式地将 Controller 路由值设置为您的实体类型(而不是类型 + 名称)。

给定两个实体(EntityA 和 EntityB), Controller 的结果是

/Entitya/get/ 打印 WebApplication11.Infrastructure.EntityA

/Entityb/get/ 打印 WebApplication11.Infrastructure.EntityB

关于c# - .Net Core 覆盖通用 Controller 的 Controller 路由,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49291370/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com