加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > asp.Net > 正文

asp.net-mvc – ASP.NET MVC 4,如何在将视图模型对象用作动作方

发布时间:2020-12-16 07:18:57 所属栏目:asp.Net 来源:网络整理
导读:ASP.NET MVC(MVC4)中是否有任何有用的钩子可以让您在调用操作方法之前访问Action方法参数(View模型),然后还可以(例如,取决于您在操作方法中检查的内容的值)参数)让你阻止调用动作方法,即将视图模型对象(动作方法参数)转发到另一个动作方法或直接转发到某个视
ASP.NET MVC(MVC4)中是否有任何有用的钩子可以让您在调用操作方法之前访问Action方法参数(View模型),然后还可以(例如,取决于您在操作方法中检查的内容的值)参数)让你阻止调用动作方法,即将视图模型对象(动作方法参数)转发到另一个动作方法或直接转发到某个视图(即动作方法中没有任何进一步处理)?

如果你不理解这个问题,请参阅下面的代码示例,它应该说明我正在寻找的代码类型……
(虽然我不知道是否存在这样的接口以及将实现挂钩到MVC框架的可能性)

如果这确实可行,我想看一个关于如何做到的代码示例的答案(而不仅仅是对某人声称例如“尝试使用方法’ActionFilterAttribute.OnActionExecuting’或’IModelBinder.BindModel’的响应”,因为我已经尝试过这些并且无法使其工作).
另外,请尊重我不希望这个帖子成为关于为什么这样做的讨论,但是想看看如何做到这一点.
(即我不想与诸如“你真正想要实现的目标是什么?”或“你想做什么可能更好的事情……”这样的回答进行讨论.)

这个问题可以分为三个子问题/代码示例,下面我自己的代码示例试图说明:
(但希望他们使用真实的现有类型“重构”为真实代码)
(显然,下面包含子字符串“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)如何防止执行正常动作方法的示例,而是将视图模型对象直接转发到视图而不进行任何进一步处理.

该示例将是上面第一个示例的扩展,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); }

解决方法

您可以使用操作过滤器并覆盖OnActionExecuting事件:

public class MyActionFilterAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        ...            
    }
}

现在让我们看看您可以从传递给此方法的filterContext参数中提取哪些有用信息.您应该查找的属性名为ActionParameters,表示IDictionary< string,object>.顾名思义,此属性包含通过名称和值传递给控制器??操作的所有参数.

所以我们假设您有以下控制器操作:

[MyActionFilter]
public ActionResult Index(MyViewModel model)
{
    ...
}

以下是在模型绑定后检索视图模型的值的方法:

public class MyActionFilterAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var model = filterContext.ActionParameters["model"] as MyViewModel;
        // do something with the model
        // You could change some of its properties here
    }
}

现在让我们看看你问题的第二部分.如何将控制器动作短路并重定向到另一个动作?

这可以通过为Result属性赋值来完成:

public class MyActionFilterAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext) 
    {
        ... some processing here and you decide to redirect:

        var routeValues = new RouteValueDictionary(new
        {
            controller = "somecontroller",action = "someaction"
        });
        filterContext.Result = new RedirectToRouteResult(routeValues);
    }
}

或者例如,您决定短路控制器操作的执行并直接呈现视图:

public class MyActionFilterAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var viewResult = new ViewResult
        {
            ViewName = "~/Views/FooBar/Baz.cshtml",};
        MyViewModel someModel = ... get the model you want to pass to the view
        viewResult.ViewData.Model = model;
        filterContext.Result = viewResult;
    }
}

或者您可能决定呈现JSON结果:

public class MyActionFilterAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        MyViewModel someModel = ... get the model you want to pass to the view
        filterContext.Result = new JsonResult
        {
            Data = model,JsonRequestBehavior = JsonRequestBehavior.AllowGet
        };
    }
}

因此,您可以看到可能性无限的可能性.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读