我在回答這個問題時顯然很晚,但我開發了一種方法來更改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);
}
}
以來的新控制器實例是在每個請求上創建的,我們可以在控制器上設置特定於操作的值以修改MVC處理操作的方式。
[AcceptVerbs(HttpVerbs.Post)]
[IgnoreJsonActionConfigurator]
public async Task<ActionResult> Foo() { ... }
謝謝,這個伎倆!這是一個無證的功能,還是我錯過了什麼? – 2010-12-21 19:11:15
默認情況下,MVC包含一組價值提供者工廠。使用MVC3,他們將JsonValueProviderFactory作爲默認值之一。以上所有代碼都是在應用程序啓動時找到它並將其刪除。解決這個問題的另一個方法可能不是讓你的ajax請求使用內容類型application/json,但我覺得刪除價值提供者工廠可能更正確。 – 2010-12-21 19:21:18
感謝您的解釋。我甚至不知道有提供工廠的東西,如querystrings和路線。我假設ModelBinder處理了所有這些。 – 2010-12-21 19:25:39