在asp.net mvc中是否可以制作通用控制器?

时间:2009-05-11 16:26:01

标签: asp.net asp.net-mvc generics controller

我正在尝试创建一个通用控制器,即:

public class MyController<T> : Controller where T : SomeType
{ ... }

然而,当我尝试使用它时,我到处都遇到了这个错误...

控制器名称必须以“Controller”

结尾

所以,我的问题,是否有可能在asp.net mvc中创建一个通用控制器?

谢谢!

5 个答案:

答案 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项目,这样你就可以检查生成异常的位置,看看你可以对你的通用想法做些什么以及强制执行“*控制器”命名惯例。