13

我正在使用默认的 MVC 路由设置:

        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );

我的区域定义为:

public class AdministrationAreaRegistration : AreaRegistration
    {
        public override string AreaName
        {
            get
            {
                return "Administration";
            }
        }

        public override void RegisterArea(AreaRegistrationContext context)
        {
            context.MapRoute(
                "Administration_default",
                "Administration/{controller}/{action}/{id}",
                new { action = "Index", id = UrlParameter.Optional }
            );
        }
    }

我在那个区域有一个控制器:

namespace XXX.Areas.Administration.Controllers
{
    public class CountryController : Controller
    {
        public ActionResult Index()
        {
///
        }
    }
}

当我输入

/行政/国家

它工作得很好。

当我输入

/国家

尽管未找到视图,但仍会调用操作,因此出现错误。

为什么 MVC 接受

/国家

作为有效路线?我在非区域区域中没有另一个 CountryController。

4

2 回答 2

9

在默认路由的 Global.asax 文件中添加 NameSpace。

var route = routes.MapRoute(
    "Default", // Route name
    "{controller}/{action}", // URL with parameters
    new { controller = "Home", action = "Index" }, // Parameter defaults,
    new[] { "YourNameSpace.Controllers" }
);

AreaRegistration在您的课程中添加 NameSpaceArea

public class MyArea : AreaRegistration
{
    public override void RegisterArea(AreaRegistrationContext context)
    {
        context.MapRoute(
            "test",
            "Test/{controller}/{action}/{id}",
            new { action = "Index", id = UrlParameter.Optional },
            new[] { "MyProjectNameSpace.Controllers" }
        );
    }
}

解释

我的应用程序中有以下区域。所以下面突出显示的部分与控制器无关。好的。

图1

在此处输入图像描述

我输入了网址:http://localhost:2474/ActionFilterAttribute/index

在走向目的地之前。我将向您展示我是如何初始化测试的。我添加了RoureDebugger 的参考。您可以从此位置获取 Dll。然后我在Application_StartHandler 下的 Global.asax 文件中添加了一行代码。

RouteDebug.RouteDebugger.RewriteRoutesForTesting(RouteTable.Routes);

所以,最后使用上面提到的 Url,我开始调试应用程序。终于看到下图了。



图-2

在此处输入图像描述

问题

尽管未找到视图,但仍会调用操作,因此出现错误。

回答

因此,如果您注意上面突出显示的内容Route,那么,这就是Default Route. 如上所述,此模式与 Url 匹配。但是在这种情况下将找不到 View,这就是你Controller Action Method被调用的原因。


在转到下一部分之前,我为什么会得到 404。我将向您展示我在示例应用程序中所做的一些测试。

我创建了一个派生自ActionFilterAttribute下面的类。这仅包含一个Override名为OnResultExecuting. 这个处理程序在执行View对应于特定的之前执行Action

创建此类的目的只是为了验证RouteData和发生了什么DataTokens

public class MyActionFilter : ActionFilterAttribute
{
    public override void OnResultExecuting(ResultExecutingContext filterContext)
    {
        var viewResult = filterContext.Result as ViewResult;

        if (viewResult != null)
        {
            var razorEngine = viewResult
                                        .ViewEngineCollection
                                        .OfType<RazorViewEngine>()
                                        .Single();

            var viewName = !String.IsNullOrEmpty(viewResult.ViewName) ? 
                                                  viewResult.ViewName :         
                  filterContext.RouteData.Values["action"].ToString();

           var razorview = razorengine
                           .FindView
                           (
                               filtercontext.Controller.ControllerContext, 
                               viewname, 
                               viewResult.MasterName, 
                               false
                           ).View as RazorView;
        }

        base.OnResultExecuting(filterContext);
    }
}

好的。让我们回到最初的问题。为什么我得到 404?

在检查 之前,您Controller将被默认基本路由拾取,因此将在 中而不是在 中查找。{controller}/{action}Area RouteViewRoot/ViewsArea/views

为了检查这一点,我在区域内控制器的操作方法中设置了调试器,发现DataToken当请​​求的 url 为无时,没有信息Area Name。让我们DataTokenDebug模式


图 -3中查看更多详细信息

在此处输入图像描述

如果您注意ControllerContext,我列举了DataTokens,它没有显示键/值。这是因为在Root Directory

你怎么能说当前所在的目录是根目录呢?证明如下




图-4

在此处输入图像描述

值中没有提到命名空间或任何区域RouteData。正确的?

现在让我们转到与RouteData包含Area Name. 所以,这次我的 Url 是 :http://localhost:2474/mypractise/ActionFilterAttribute/index并且下面是URLRoutingModuleRouteData匹配的




图-5

在此处输入图像描述

请注意突出显示的部分,这次匹配的路由属于模式,对于属于根目录AreaName中某些的默认路由,匹配值为 false 。RouteData正确的?

DataTokens对于上述请求的 URL,我的最终详细信息。这次可以看到 Namespace 详细信息和 Area 详细信息。


图-6

在此处输入图像描述



结论

当 位于Controller区域内且您DataTokens未显示和的信息Area时。这意味着您将获得 404。如图 4 中所述,您请求的 Url 是正确的,因此您获得了and 如图 3 中所述,DataTokens 没有显示,因为请求的 Url 不包含得到了图 2 中提到的,因为它是默认的 Url 模式。最后尝试执行中的第三行代码。它将显示 null 因为未找到 View。NameSpaceUseNameSpaceFallbackDataTokensArea NameRouteDataOnResultExecuting

希望这个解释对你有所帮助。

于 2013-06-20T23:57:12.600 回答
7

核实。像这样修改Global.ascx.cs文件中的默认路由。

var route = routes.MapRoute(
    name: "Default",
    url: "{controller}/{action}/{id}",
    defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
    namespaces: new string[] { "APPLICATION_NAMESPACE.Controllers.*" }
);

route.DataTokens["UseNamespaceFallback"] = false;

编辑:

我很抱歉。似乎您希望它这样做并且知道为什么

您遇到了这样一个事实,即默认路由将查找任何控制器。即使它在一个区域内。namespaces您可以通过简单地将参数添加到路由并指定默认路由应使用控制器查找的内容来克服此默认行为。

如果您不想提供区域本身以外的区域的视图,我上面提供的解决方案只是一个解决方案。

有一篇很棒的文章说明为什么会发生这种情况

于 2013-06-20T22:42:15.217 回答