我正在尝试创建一个通用控制器,即:
public class MyController<T> : Controller where T : SomeType
{ ... }
然而,当我尝试使用它时,我到处都遇到了这个错误...
控制器名称必须以“Controller”
结尾所以,我的问题,是否有可能在asp.net mvc中创建一个通用控制器?
谢谢!
答案 0 :(得分:37)
如果我理解你正确,你要做的是通过类型为T的通用控制器路由给定模型的所有请求。
您希望T根据所要求的型号而变化。
您希望/Product/Index
触发MyController<Product>.Index()
这可以通过编写自己的IControllerFactory
并实现CreateController
方法来实现:
public IController CreateController(RequestContext requestContext, string controllerName)
{
Type controllerType = Type.GetType("MyController")
.MakeGenericType(Type.GetType(controllerName));
return Activator.CreateInstance(controllerType) as IController;
}
答案 1 :(得分:9)
是的,你可以,没关系,我自己也经常使用它们。
您需要确保的是,当您从MyController继承时,您仍然使用控制器结束类型名称:
public class FooController : MyController<Foo>
{
...
}
答案 2 :(得分:1)
默认控制器工厂在尝试查找要将请求分派到的控制器时,会在控制器名称周围使用“约定”。如果需要,您可以覆盖此查找功能,这可以允许您的通用控制器工作。
这篇MSDN文章......
http://msdn.microsoft.com/en-us/magazine/dd695917.aspx
...对正在发生的事情有一个很好的解释。
答案 3 :(得分:1)
这是asp.net mvc generic controller的副本,实际上包含正确答案。 Jeff Fritz的回答绝对不正确。创建自己的IControllerFactory不会超过ExpressionHelper.GetRouteValuesFromExpression中的限制,这会产生您看到的错误。无论何时调用RedirectToAction,BuildUrlFromExpression,ActionLink,RenderAction,BeginForm以及任何调用它们的方法,实现自己的IControllerFactory都会给你留下错误。
有趣的是,微软的“约束限制”已经通过约束“where TController:Controller”强制执行,该约束位于ExpressionHelper.GetRouteValuesFromExpression方法中的类型上。没有通用符合公约验证:
string controllerName = typeof(TController).Name;
if (!controllerName.EndsWith("Controller", StringComparison.OrdinalIgnoreCase)) {
throw new ArgumentException(MvcResources.ExpressionHelper_TargetMustEndInController, "action");
}
除非它以“Controller”结尾的类继承,因为typeof(AnyGeneric).Name永远不会以“Controller”结尾。
答案 4 :(得分:0)
如果我是你,我会得到MVC source并使用源代码创建一个测试MVC项目,这样你就可以检查生成异常的位置,看看你可以对你的通用想法做些什么以及强制执行“*控制器”命名惯例。