ASP.NET MVC 2 RC 2返回特定区域的指定区域时控制器 [英] ASP.NET MVC 2 RC 2 returns Area-specific controller when no area specified

查看:357
本文介绍了ASP.NET MVC 2 RC 2返回特定区域的指定区域时控制器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个基本的MVC 2(RC2)与一个基础级控制器(家),一个区域(管理)配有一个控制器(抽象)站点。当我打电话的http://网站/摘要 - 尽管我还没有指定的区域中的URL在管理领域的抽象控制器被调用。更糟糕的是 - 它似乎并不知道这是在联系,因为它无法找到相关的观点,只是返回:

I have a basic MVC 2 (RC2) site with one base-level controller ("Home"), and one area ("Admin") with one controller ("Abstract"). When i call http://website/Abstract - the Abstract controller in the Admin area gets called even though i haven't specified the Area in the URL. To make matters worse - it doesn't seem to know it's under Admin because it can't find the associated view and just returns:

The view 'Index' or its master was not found. The following locations were searched:
~/Views/Abstract/Index.aspx
~/Views/Abstract/Index.ascx
~/Views/Shared/Index.aspx
~/Views/Shared/Index.ascx

我是做错了什么?这是一个错误?一种功能?

Am i doing something wrong? Is this a bug? A feature?

推荐答案

我的朋友和我在ASP.NET MVC 2与地区遇到了同样的问题,我们发现了一个黑客,到目前为止,似乎工作。对于TL;博士版本,看到这个答案的底部

My friend and I were experiencing the same issue with Areas in ASP.NET MVC 2. We found a "hack" that, so far, seems to be working. For the tl;dr version, see the bottom of this answer.

您可能已经有类似的管理区域的AdminAreaRegistration.cs下面类的东西:

You've probably got something similar to the following in your "Admin" area's "AdminAreaRegistration.cs" class:

// Web/Areas/Admin/AdminAreaRegistration.cs

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

因此​​,应该有意义,当你做出的http://网站/摘要的要求,Admin_default路线不符合要求。因此,在设计上,MVC框架试图匹配任何其他定义的路由请求。如果使用Visual Studio中的MVC工具来创建Web项目,你必须在你的的Global.asax文件中定义的默认路线(在Web项目的根目录)。它应该类似于此:

Thus, it should make sense that when you make a request for "http://website/Abstract", the "Admin_default" route does not match the request. So, by design, the MVC framework attempts to match the request against any other defined routes. If you used the MVC tooling within Visual Studio to create your web project, you'll have a "Default" route defined in your "Global.asax" file (at the root of your web project). It should look similar to this:

// Web/Global.asax.cs

public static void RegisterRoutes(RouteCollection routes) {
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

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

默认的路线成功匹配的请求HTTP://网站/摘要,用控制=摘要,行动=索引(默认值),ID= UrlParameter.Optional(默认值)。这是正确的,并打算,行为......至今。

The "Default" route succeeds in matching the request for "http://website/Abstract", with "controller" = "Abstract", "action" = "Index" (default value), and "id" = UrlParameter.Optional (default value). This is the correct, and intended, behavior... so far.

现在,MVC框架将尝试加载摘要控制器。在设计上,MVC将寻找一个叫做扩展控制器Web项目的文件/命名空间层次结构中的任何地方在AbstractController级。要注意的是一个控制器的文件的位置和名称空间不影响MVC的找到它的能力是很重要的;换句话说,只是因为你已经放置在一个AbstractController一个名为区域\\管理\\控制器文件夹中,改变了命名为Web.Areas.Admin.Controllers,而不是,比方说,Web.Controllers ,并不意味着MVC不会使用它。

Now, the MVC framework will attempt to load the "Abstract" Controller. By design, MVC will search for a class called "AbstractController" that extends "Controller" anywhere within the web project's file/namespace hierarchy. It is important to note that a Controller's file location and namespace do not affect MVC's ability to find it; in other words, just because you've placed the "AbstractController" within a folder called "Areas\Admin\Controllers" and changed the namespace to be "Web.Areas.Admin.Controllers" instead of, say, "Web.Controllers", doesn't mean that MVC won't use it.

在MVC执行中的一个AbstractController当中,最有可能的,只是返回的查看(),然后MVC会很困惑,因为它不知道在哪里可以找到索引视图中的指数的行动。由于MVC已经匹配的非区域的路由(在Global.asax中的默认路线),它认为匹配视图应设在非区域视图文件夹。因此,你所熟悉的错误消息:

When MVC executes the "Index" action in "AbstractController" which, most likely, just returns "View()", then MVC gets confused because it doesn't know where to find the "Index" view. Because MVC has matched a non-area route (the "Default" route in Global.asax), it thinks the matching view should be located in non-area view folders. Thus you get the familiar error message:

The view 'Index' or its master was not found. The following locations were searched:
~/Views/Abstract/Index.aspx
~/Views/Abstract/Index.ascx
~/Views/Shared/Index.aspx
~/Views/Shared/Index.ascx

我们,就像你,不想为HTTP://网站/摘要请求解析到管理区的一个AbstractController;唯一的http://网站/行政/摘要应该工作。我想不出为什么有人想这种行为。

We, just as you, didn't want requests for "http://website/Abstract" to resolve to "Admin" area's "AbstractController"; only "http://website/Admin/Abstract" should work. I can't think of why anyone would want this behavior.

有一个简单的解决方法是删除在Global.asax中的默认的路线,的的,这将打破任何常规的非区域控制器/浏览次数。这可能不是大多数人的一个选项...

A simple solution is to delete the "Default" route in Global.asax, but this will break any regular non-area Controllers/Views. This is probably not an option for most people...

因此​​,我们认为我们可以限制一套MVC将使用由默认的路线在Global.asax中匹配请求控制器:

So, we thought we could restrict the set of Controllers that MVC would use for requests matched by the "Default" route in Global.asax:

// Web/Global.asax.cs

public static void RegisterRoutes(RouteCollection routes) {
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapRoute(
        "Default",
        "{controller}/{action}/{id}",
        new {controller = "Home", action = "Index", id = UrlParameter.Optional},
        new[] {"Web.Controllers"} // Added this line
    );
}

不。一种要求的http://网站/摘要会的还是的使用在AbstractController的管理区域内,即使在AbstractController的命名空间是Web.Areas.Admin.Controllers 和(显然)而不是Web.Controllers。这是彻底的混乱;好像这个白名单已没有dicernable对MVC的控制器解决影响。

Nope. A request for "http://website/Abstract" will still use "AbstractController" within the "Admin" area, even though the "AbstractController"'s namespace is "Web.Areas.Admin.Controllers" and (clearly) not "Web.Controllers". This is thoroughly confusing; it seems like this white-list has no dicernable affect on MVC's Controller resolution.

- TL;博士答案从这里开始 -

一些黑客攻击之后,我们想出了如何强制MVC白上市的命名空间(S)内只使用控制器。

After some hacking, we figured out how to force MVC to only use Controllers within the white-listed namespace(s).

// Web/Global.asax.cs

public static void RegisterRoutes(RouteCollection routes) {
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapRoute(
        "Default",
        "{controller}/{action}/{id}",
        new {controller = "Home", action = "Index", id = UrlParameter.Optional},
        new[] {"Web.Controllers"}
    ).DataTokens["UseNamespaceFallback"] = false; // Added this line
}

设置DataTokens的UseNamespaceFallback密钥词典上虚假的默认的路子。现在,当我们做一个请求的http://网站/摘要,默认的路线仍将匹配(这是有效的行为!),但MVC会的的使用任何控制器,没有定义的命名空间(S)内;在这种情况下,只有Web.Controllers命名空间内控制器是有效的。最后,这就是我们正在寻找的功能!我们想不通为什么这是不是默认的行为。奇怪,是吧?

Set the "UseNamespaceFallback" key of the DataTokens dictionary on the "Default" route to false. Now, when we make a request for "http://website/Abstract", the "Default" route will still be matched (this is valid behavior!) but MVC will not use any Controller that is not within the defined namespace(s); in this case, only Controllers within the "Web.Controllers" namespace are valid. Finally, this is the functionality we were looking for! We can't figure out why this isn't the default behavior. Weird, huh?

希望这有助于。

这篇关于ASP.NET MVC 2 RC 2返回特定区域的指定区域时控制器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆