.net - 无法在 Controller 'System.Web.Mvc.PartialViewResult Foo[T](T)' 上调用操作方法 'Controller',因为操作方法是通用方法

标签 .net asp.net-mvc generics asp.net-mvc-2

无法在 Controller “Controller”上调用操作方法“System.Web.Mvc.PartialViewResult FooT”,因为操作方法是通用方法

<% Html.RenderAction("Foo", model = Model}); %>

是否有针对 ASP MVC 2 的此限制的解决方法?我真的更喜欢使用泛型。我想出的解决方法是将模型类型更改为对象。它有效,但不是首选:
    public PartialViewResult Foo<T>(T model) where T : class
    {
      // do stuff
    }

最佳答案

在默认 ActionDescriptor 中抛出的代码:

    internal static string VerifyActionMethodIsCallable(MethodInfo methodInfo) {
        // we can't call instance methods where the 'this' parameter is a type other than ControllerBase
        if (!methodInfo.IsStatic && !typeof(ControllerBase).IsAssignableFrom(methodInfo.ReflectedType)) {
            return String.Format(CultureInfo.CurrentUICulture, MvcResources.ReflectedActionDescriptor_CannotCallInstanceMethodOnNonControllerType,
                methodInfo, methodInfo.ReflectedType.FullName);
        }

        // we can't call methods with open generic type parameters
        if (methodInfo.ContainsGenericParameters) {
            return String.Format(CultureInfo.CurrentUICulture, MvcResources.ReflectedActionDescriptor_CannotCallOpenGenericMethods,
                methodInfo, methodInfo.ReflectedType.FullName);
        }

        // we can't call methods with ref/out parameters
        ParameterInfo[] parameterInfos = methodInfo.GetParameters();
        foreach (ParameterInfo parameterInfo in parameterInfos) {
            if (parameterInfo.IsOut || parameterInfo.ParameterType.IsByRef) {
                return String.Format(CultureInfo.CurrentUICulture, MvcResources.ReflectedActionDescriptor_CannotCallMethodsWithOutOrRefParameters,
                    methodInfo, methodInfo.ReflectedType.FullName, parameterInfo);
            }
        }

        // we can call this method
        return null;
    }

因为代码正在调用“methodInfo.ContainsGenericParameters”,我认为没有办法在不创建自己的 ActionDescriptor 的情况下覆盖此行为。从查看源代码来看,这似乎很重要。

另一种选择是使您的 Controller 类通用并创建自定义的通用 Controller 工厂。我有一些创建通用 Controller 的实验代码。它的hacky,但它只是一个个人实验。
public class GenericControllerFactory : DefaultControllerFactory
{
    protected override Type GetControllerType(System.Web.Routing.RequestContext requestContext, string controllerName)
    {
        //the generic type parameter doesn't matter here
        if (controllerName.EndsWith("Co"))//assuming we don't have any other generic controllers here
            return typeof(GenericController<>);

        return base.GetControllerType(requestContext, controllerName);

        throw new InvalidOperationException("Generic Factory wasn't able to resolve the controller type");
    }

    protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType)
    {
        //are we asking for the generic controller?
        if (requestContext.RouteData.Values.ContainsKey("modelType"))
        {
            string typeName = requestContext.RouteData.Values["modelType"].ToString();
            //magic time
            return GetGenericControllerInstance(typeName, requestContext);
        }

        if (!typeof(IController).IsAssignableFrom(controllerType))
            throw new ArgumentException(string.Format("Type requested is not a controller: {0}",controllerType.Name),"controllerType");

        return base.GetControllerInstance(requestContext, controllerType);
    } 

    /// <summary>
    /// Returns the a generic IController tied to the typeName requested.  
    /// Since we only have a single generic controller the type is hardcoded for now
    /// </summary>
    /// <param name="typeName"></param>
    /// <returns></returns>
    private IController GetGenericControllerInstance(string typeName, RequestContext requestContext)
    {
        var actionName = requestContext.RouteData.Values["action"];

        //try and resolve a custom view model

        Type actionModelType = Type.GetType("Brainnom.Web.Models." + typeName + actionName + "ViewModel, Brainnom.Web", false, true) ?? 
            Type.GetType("Brainnom.Web.Models." + typeName + ",Brainnom.Web", false, true);

        Type controllerType = typeof(GenericController<>).MakeGenericType(actionModelType);

        var controllerBase = Activator.CreateInstance(controllerType, new object[0] {}) as IController;

        return controllerBase;
    }
}

关于.net - 无法在 Controller 'System.Web.Mvc.PartialViewResult Foo[T](T)' 上调用操作方法 'Controller',因为操作方法是通用方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2870116/

相关文章:

c# - 为什么 'public event EventHandler cccc' 为空?

java - <?> 是什么意思

java - 将通用 ArrayList 设置为零

c# - 在 MVC 中有条件地显示操作链接

c# - onClick 绑定(bind)到 Url.ActionLink 仅在第一次有效

javascript - 手动触发一个字段的客户端验证

java - 泛型和静态

c# - COM-Interop:将 .NET Framework 版本从 2.0 更改为 4.0 - 我是否也应该更改 Guid?

.net - 术语 - 事件可以是 "thrown"吗?

c# - BlockingCollection 和 CancellationToken 传递