【发布时间】:2013-01-22 08:53:26
【问题描述】:
在 ASP.NET MVC (MVC4) 中是否有任何有用的钩子可以让您在调用操作方法之前访问操作方法参数(视图模型),然后(例如,取决于您签入的内容的值) action 方法参数)让您阻止调用 action 方法,即,将视图模型对象(action 方法参数)转发到另一个 action 方法或直接转发到某个视图(即在 action 方法中没有任何进一步处理)?
如果您不理解问题,请参阅下面的代码示例,该示例应该说明我正在寻找的代码类型... (虽然我不知道是否真的存在这种接口以及将实现挂钩到 MVC 框架的可能性)
如果这确实是可能的,我希望看到有关如何执行此操作的代码示例的答案(而不仅仅是有人声称“尝试使用方法 'ActionFilterAttribute.OnActionExecuting' 或 'IModelBinder.BindModel' “因为我已经尝试过这些并且无法使其工作)。 另外,请尊重我不希望这个帖子成为关于 WHY 这样做的讨论,而是希望看到 HOW 这样做。 (即,我对与诸如“您实际上想要实现什么目标?”或“做您想做的事情可能更好的事情......”之类的回答进行讨论不感兴趣)
这个问题可以分为三个子问题/代码示例,下面我自己的代码示例试图说明: (但希望将它们“重构”为 REAL 代码并使用真实的现有类型) (很明显,下面每一个类型包含子串“Some”都是我自己编出来的,我正在寻找对应的真实的东西……)
(1) 在使用视图模型对象参数调用实际操作方法之前,如何在通用位置访问(并可能修改)视图模型对象(操作方法参数)的示例。
我正在寻找的代码示例可能与下面类似,但不知道要使用哪种接口以及如何注册它才能执行以下操作:
public class SomeClass: ISomeInterface { // How to register this kind of hook in Application_Start ?
public void SomeMethodSomewhere(SomeActionMethodContext actionMethodContext, object actionMethodParameterViewModel) {
string nameOfTheControllerAboutToBeInvoked = actionMethodContext.ControllerName;
string nameOfTheActionMethodAboutToBeInvoked = actionMethodContext.MethodName;
// the above strings are not used below but just used for illustrating that the "context object" contains information about the action method to become invoked by the MVC framework
if(typeof(IMyBaseInterfaceForAllMyViewModels).IsAssignableFrom(actionMethodParameterViewModel.GetType())) {
IMyBaseInterfaceForAllMyViewModels viewModel = (IMyBaseInterfaceForAllMyViewModels) actionMethodParameterViewModel;
// check something in the view model:
if(viewModel.MyFirstGeneralPropertyInAllViewModels == "foo") {
// modify something in the view model before it will be passed to the target action method
viewModel.MySecondGeneralPropertyInAllViewModels = "bar";
}
}
}
}
(2) 如何阻止目标操作方法被执行,而是调用另一个操作方法的示例。 该示例可能是上述示例的扩展,如下所示:
public void SomeMethodSomewhere(SomeActionMethodContext actionMethodContext, object actionMethodParameterViewModel) {
... same as above ...
if(viewModel.MyFirstGeneralPropertyInAllViewModels == "foo") {
actionMethodContext.ControllerName = "SomeOtherController";
actionMethodContext.MethodName = "SomeOtherActionMethod";
// The above is just one example of how I imagine this kind of thing could be implemented with changing properties, and below is another example of doing it with a method invocation:
SomeHelper.PreventCurrentlyTargetedActionMethodFromBecomingExecutedAndInsteadExecuteActionMethod("SomeOtherController", "SomeOtherActionMethod", actionMethodParameterViewModel);
// Note that I do _NOT_ want to trigger a new http request with something like the method "Controller.RedirectToAction"
}
(3) 示例如何阻止执行正常的操作方法,而是将视图模型对象直接转发到视图而不进行任何进一步处理。
该示例将是上面第一个示例的扩展,如下所示:
public void SomeMethodSomewhere(SomeActionMethodContext actionMethodContext, object actionMethodParameterViewModel) {
... same as the first example above ...
if(viewModel.MyFirstGeneralPropertyInAllViewModels == "foo") {
// the below used razor view must of course be implemented with a proper type for the model (e.g. interface 'IMyBaseInterfaceForAllMyViewModels' as used in first example above)
SomeHelper.PreventCurrentlyTargetedActionMethodFromBecomingExecutedAndInsteadForwardViewModelToView("SomeViewName.cshtml", actionMethodParameterViewModel);
}
【问题讨论】:
标签: asp.net-mvc asp.net-mvc-4 model-binding