Я, очевидно, довольно поздно отвечаю на этот вопрос, но я разработал способ изменить IValueProvider
для конкретного действия в MVC5. Я не пытался выяснить, возможно ли это в MVC3, так как этот вопрос старый, но я предполагаю, что он чем-то похож.
Отказ от ответственности: это не красиво.
Сначала мы создаем новый интерфейс, который мы можем реализовать в атрибуте для создания конфигураций, специфичных для действий:
internal interface IActionConfigurator
{
void Configure(ControllerContext controllerContext, ActionDescriptor actionDescriptor);
}
Затем мы создаем пользовательский ControllerActionInvoker
(или AsyncControllerActionInvoker
, если вы используете async
) для подключения нашего нового интерфейса:
internal sealed class CustomControllerActionInvoker : AsyncControllerActionInvoker
{
protected override ActionDescriptor FindAction(ControllerContext controllerContext, ControllerDescriptor controllerDescriptor, string actionName)
{
var actionDescriptor = base.FindAction(controllerContext, controllerDescriptor, actionName);
var configurators = actionDescriptor.GetCustomAttributes(typeof(IActionConfigurator), true).Cast<IActionConfigurator>();
foreach (var configurator in configurators)
configurator.Configure(controllerContext, actionDescriptor);
return actionDescriptor;
}
}
Теперь нам нужно реализовать пользовательский DefaultControllerFactory
для установки Controller.ActionInvoker
:
internal sealed class CustomControllerFactory : DefaultControllerFactory
{
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
var instance = base.GetControllerInstance(requestContext, controllerType);
var controller = instance as Controller;
if (controller != null)
controller.ActionInvoker = new CustomControllerActionInvoker();
return instance;
}
}
Наконец, мы устанавливаем нашу фабрику пользовательских контроллеров по умолчанию в коде запуска:
ControllerBuilder.Current.SetControllerFactory(typeof(CustomControllerFactory));
и реализуем наш IActionConfigurator
интерфейс в пользовательском атрибуте:
internal sealed class IgnoreJsonActionConfiguratorAttribute : Attribute, IActionConfigurator
{
public void Configure(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
{
// Here we can configure action-specific stuff on the controller
var factories = ValueProviderFactories.Factories.Where(f => !(f is JsonValueProviderFactory)).ToList();
controllerContext.Controller.ValueProvider = new ValueProviderFactoryCollection(factories).GetValueProvider(controllerContext);
}
}
Поскольку новый экземпляр Controller создается при каждом запросе, мы можем установить значения для конкретного действия на контроллере, чтобы изменить способ обработки действия MVC.
[AcceptVerbs(HttpVerbs.Post)]
[IgnoreJsonActionConfigurator]
public async Task<ActionResult> Foo() { ... }