不需要为每个视图解决方案单独的控制器或操作 - 理解代码

No need for separate controllers or actions for each view solution - understanding the code

this article中有两点我无法掌握。它解释了使用 ASP.NET MVC 的方式,而不需要为每个视图单独的控制器或操作。

1) 在DispatchRequest方法中:

private void DispatchRequest(IControllerFactory controllerFactory, string controller, string action)
    {
        var route = GetRoute(controller, action);
        _requestContext.RouteData.Values["x-action"] = action;
        _requestContext.RouteData.Values["x-controller"] = controller;

        if (route != null)
        {
            _requestContext.RouteData.Values["controller"] = route.Controller;
            _requestContext.RouteData.Values["action"] = route.Action;

            if (route.Area != string.Empty)
            {
                _requestContext.RouteData.DataTokens["area"] = route.Area;
            }

            controller = route.Controller;

操作和控制器字符串存储在 "x-action" 和 "x-controller" 键下。控制器和操作下方的几行存储在 "controller" 和 "action" 键下。

两对(控制器和动作)都是字符串,这些对不一样吗?在我看来他们就是这样。为什么要复制不必要的数据?

2) 在控制器中,ControllerLessController :

public virtual ActionResult Index()
    {
        var action = RouteData.Values["x-action"].ToString();
        var controller = RouteData.Values["x-controller"].ToString();
        RouteData.Values["action"] = action;
        RouteData.Values["controller"] = controller;
        if (RouteData.Values["area"] != null)
        {
            RouteData.DataTokens["area"] = RouteData.Values["area"].ToString();
        }

        return View(action);
    }
}

注意正文中的前两行。为什么要在字符串对象上调用 toString?此外,为什么有人决定将它们存储在动作和控制器变量中并覆盖 "action" 和 "controller" 键下的数据(第 3,4 行)?

  1. Both pairs (controller and action) are strings, aren't these pairs the same? It looks to me like they are. Why duplicate the data unnecessarily?

没有。目的是将原始请求值存储在 "x-action"、"x-controller" 中,然后根据需要覆盖 "action"、"controller",同时仍然可以在稍后阶段访问原始值加工。 "x-action"、"x-controller" 只是用作临时变量。它们存储在 RouteData 中,因为一旦分派方法完成,任何本地变量都将超出范围。

  1. Notice the first two lines in the body. Why invoke toString on string objects?

RouteData.Values return 通过字符串索引器生成一个对象,因此 ToString。 IE。 RouteData.Values["MyValue"] return 对象不是字符串。

Moreover, why somebody decided to store them in action and controller variables and overwrite the data under "action" and "controller" keys (line 3,4)?

这可以追溯到 1 中的 TempData 想法。一个动作请求进来了。通常在 MVC 中,它会转换为具有视图的控制器,但在这个无控制器示例中,无控制器动作需要映射到无控制器处理程序。

因此在 DispatchRequest 中,这些被覆盖以指向无控制器处理程序 class ControllerLessController : Controller

注意这是在选择控制器之前发生的

然后 MVC 以正常方式处理请求,但由于 Dispatch 中的切换,MVC 不会去寻找最初请求的控制器(因为没有控制器),而是使用注入的无控制器控制器:

_requestContext.RouteData.Values["action"] = _configuration.DefaultAction;
controller = _configuration.DefaultController;

于是正常的请求处理在controllerless controller中进行并落地。那时我们需要返回并找到最初请求的视图。

public virtual ActionResult Index()
    {
        var action = RouteData.Values["x-action"].ToString();
        var controller = RouteData.Values["x-controller"].ToString();
        RouteData.Values["action"] = action;
        RouteData.Values["controller"] = controller;
        if (RouteData.Values["area"] != null)
        {
            RouteData.DataTokens["area"] = RouteData.Values["area"].ToString();
        }

        return View(action);
    }

此信息存储在 "x-action" 路由值中,因此他们将其提取出来并 return 原始请求的视图:

return View(action);

其中

var action = RouteData.Values["x-action"].ToString();

基本上你只有一层re-direction/interception。我们将没有控制器的所有操作重定向到某个处理程序,在本例中为 ControllerLessController。在我们这样做之前,我们需要将原始请求参数存储在 "x-action" 变量中。然后在 ControllerLessController 处理程序中,我们将这些原始值拉回,以便我们可以为原始控制器请求生成一个视图。