В asp.net mvc возможно ли сделать универсальный контроллер? - PullRequest
27 голосов
/ 11 мая 2009

Я пытаюсь создать универсальный контроллер, то есть:

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

Однако, когда я пытаюсь использовать его, я везде сталкиваюсь с этой ошибкой ...

Имя контроллера должно заканчиваться на 'Controller'

Итак, мой вопрос, возможно ли сделать универсальный контроллер в asp.net mvc?

Спасибо!

Ответы [ 5 ]

37 голосов
/ 11 мая 2009

Если я правильно вас понимаю, то, что вы пытаетесь сделать, это направлять все запросы для данной модели через универсальный контроллер типа 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;
}
9 голосов
/ 11 мая 2009

Да, можно, все в порядке, и я сам много их использовал.

Необходимо убедиться, что когда вы наследуете от MyController, вы все еще заканчиваете имя типа контроллером:

public class FooController :  MyController<Foo>
{ 
 ...
}
1 голос
/ 22 октября 2012

Это дубликат универсального контроллера asp.net mvc , который на самом деле содержит правильный ответ. Ответ Джеффа Фрица абсолютно неверен. Создание собственного IControllerFactory не обойдёт ограничение в ExpressionHelper.GetRouteValuesFromExpression, которое генерирует ошибку, которую вы видите. Реализация собственной IControllerFactory по-прежнему будет вызывать ошибки при вызове RedirectToAction, BuildUrlFromExpression, ActionLink, RenderAction, BeginForm, любых любых методов, которые их вызывают.

Что меня интересует, так это то, что «ограничение по соглашению» Microsoft уже применено ограничением «где 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".

1 голос
/ 11 мая 2009

Фабрика контроллеров по умолчанию использует «соглашение» вокруг имен контроллеров, когда пытается найти контроллер для отправки запроса. При желании вы можете переопределить эту функцию поиска, что позволит вашему универсальному контроллеру работать.

Эта статья MSDN ...

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

... есть хорошая запись того, что происходит.

0 голосов
/ 11 мая 2009

Если бы я был вами, я бы взял исходный код MVC и создал бы тестовый проект MVC с исходным кодом, чтобы вы могли проверить, где генерируется исключение, и посмотреть, что вы можете сделать с общей идеей. и принудительное соглашение об именовании "* controller".

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...