2009-05-11 7 views
24

Je tente de créer un contrôleur générique, à savoir:Dans asp.net mvc est-il possible de faire un contrôleur générique?

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

Cependant, lorsque je tente de l'utiliser, je suis en cours d'exécution dans cette erreur partout ...

Nom du contrôleur doit se terminer en 'Contrôleur' ​​

Donc, ma question, est-il possible de faire un contrôleur générique dans asp.net mvc?

Merci!

+0

Qu'essayez-vous exactement de réaliser par cela? Lorsque MyController est instancié, il doit savoir ce que T est, soit à travers une sous-classe ou son constructeur. Si vous voulez le faire de manière dynamique, vous devrez écrire une ControllerFactory – roryf

Répondre

35

Si je vous comprends bien, ce que vous essayez de faire, est la route toutes les demandes de un modèle donné via un contrôleur générique de type T.

Vous souhaitez que le T varie en fonction du modèle demandé.

Vous souhaitez /Product/Index pour déclencher MyController<Product>.Index()

Ceci peut être accompli en écrivant votre propre IControllerFactory et mettre en œuvre la méthode CreateController comme ceci:

public IController CreateController(RequestContext requestContext, string controllerName) 
{ 
    Type controllerType = Type.GetType("MyController") 
           .MakeGenericType(Type.GetType(controllerName)); 
    return Activator.CreateInstance(controllerType) as IController; 
} 
+0

Ceci est intéressant, je suis à la recherche. Merci. –

+1

np ... N'oubliez pas que la convention de nommage "Controller" est un STANDARD PAR DEFAUT .. Si vous voulez instancier d'une autre manière, faites-le! Ecrire un IControllerFactory qui applique votre norme, pas –

+1

MSFT le problème avec ceci est, vous aurez également besoin de viewmodels génériques, façon générique de liaison et de filtrage, la validation générique, cela pourrait présenter tout un exploit pour l'implémenter – mare

1

La fabrique de contrôleurs par défaut utilise la «convention» autour des noms de contrôleurs lorsqu'elle tente de trouver un contrôleur pour envoyer la requête. Vous pouvez remplacer cette fonctionnalité de recherche si vous le souhaitez, ce qui pourrait alors permettre à votre contrôleur générique de fonctionner.

Cet article MSDN ...

http://msdn.microsoft.com/en-us/magazine/dd695917.aspx

... a une bonne writeup de ce qui se passe.

0

Si j'étais vous, j'obtiendrais le MVC source et créeriez un projet de test MVC avec le code source afin que vous puissiez examiner où l'exception est générée et voir ce que vous pouvez faire à propos de votre idée générique et du "" contrôleur forcé "convention de nommage.

9

Oui, vous pouvez, c'est bien et je les ai utilisé beaucoup moi-même.

Ce que vous devez vous assurer que lorsque vous héritez de MyController vous finissez toujours le nom du type avec le contrôleur:

public class FooController : MyController<Foo> 
{ 
... 
} 
+0

Je ne veux pas de contrôleurs séparés pour chaque type ... Je veux un contrôleur générique pour gérer plusieurs types. –

+0

J'essayé, et quand je suis arrivé à « public void Modifier (Foo article) {...} », MVC ne comprenait pas le type Foo, mais le type de base que je mets dans la classe générique , donc tous les paramètres de l'objet "Item" étaient à leur valeur initiale !!! – billy

+0

Mon mauvais. J'ai oublié que la propriété dans mon ViewModel n'était pas nommée "Item" ... – billy

1

Ceci est un double de asp.net mvc generic controller qui contient en fait le bon répondre. La réponse de Jeff Fritz n'est absolument pas correcte. Créer votre propre IControllerFactory ne dépassera pas la limitation dans ExpressionHelper.GetRouteValuesFromExpression qui génère l'erreur que vous voyez. L'implémentation de votre propre IControllerFactory vous laissera toujours des erreurs chaque fois que vous appellerez RedirectToAction, BuildUrlFromExpression, ActionLink, RenderAction, BeginForm, toutes les méthodes qui les appellent. Ce qui m'intéresse, c'est que la "restriction par convention" de Microsoft est déjà imposée par la contrainte "où TController: Controller" est placée sur le type dans la méthode ExpressionHelper.GetRouteValuesFromExpression.Non générique satisfera jamais la validation de la convention:

string controllerName = typeof(TController).Name; 
if (!controllerName.EndsWith("Controller", StringComparison.OrdinalIgnoreCase)) { 
    throw new ArgumentException(MvcResources.ExpressionHelper_TargetMustEndInController, "action"); 
} 

sauf si elle est héritée par une fin de classe « Controller » parce que typeof (AnyGeneric) .Nom ne prendra jamais fin avec « Controller ».

Questions connexes