ASPNET MVC:我可以将位于给定区域(而不是根结构)的页面设置为默认吗?

发布于 2024-09-18 13:22:18 字数 727 浏览 6 评论 0原文

如何以及在哪里配置我的应用程序,以便在启动时,操作(即要显示的页面)不在根结构中,而是在我选择的给定区域中?

比方说,Action =“IndexOfArticles”,Controller =“Articles”,Area =“News”。我希望启动应用程序时此设置成为默认设置。

我研究了 NewsAreaRegistration 类并设置了上述配置。现在我怀疑,为了使其工作,我还需要对 Global.asx.cs 做一些事情,但我不知道该怎么做。

编辑

这就是我的意思

routes.MapRoute(
            "Default", // Route name
            "{controller}/{action}/{id}", // URL with parameters
            new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
        );

例如,上面的代码将导致应用程序以位于 Home 控制器中的 Index 操作启动。那不是我想要的。 谢谢你的帮助。

How and where do I configure my application so that, when it launches, the action (thus the page to be displayed) be, not in the root structure, but rather in a given area of my choice?

Let's say, Action = "IndexOfArticles", Controller = "Articles", Area = "News". I want this setting to be the default when I launch the application.

I've worked on the NewsAreaRegistration class and set up the above configuration. now I suspect that, to make it work, I need to do something with Global.asx.cs as well, but I don't know what to do.

EDIT

This is what I mean

routes.MapRoute(
            "Default", // Route name
            "{controller}/{action}/{id}", // URL with parameters
            new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
        );

The above code, for instance, will cause the application to start with Index action located in Home controller to execute. That's not what I want.
Thanks for helping.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

三生池水覆流年 2024-09-25 13:22:18

考虑到您所问问题的性质,我想推荐一个我认为您会真正喜欢的资源。 Steven Sanderson 的书“Pro ASP.NET MVC 2 Framework(第二版)”,作者:apress。第 8 章特别介绍了有关路由和区域的大量细节。这本书本身非常优秀而且内容丰富;我读过的开发/编程书籍的最佳示例之一。它以 Kindle 形式提供,如果您直接从 apress 订购,您可以获得 PDF 电子书形式。当然,它也以纸质形式提供:

Amazon 链接

直接来自 Apress

关于区域,您可能想要了解的具体内容是它们基于名称空间。当您创建一个区域时,该区域的命名空间是 MVC 定位它们并决定什么在“区域”以及什么不在“区域”的方式。一般来说,这意味着路由到区域是通过将区域名称作为 URL 中第一个文件夹的 URL 完成的,但这映射到控制器的命名空间,不一定是物理文件夹名称(尽管如果您想保留您的文件夹名称,它们应该匹配)理智)。

Manaf 示例中的路线更多地是“偶然”而不是故意,这可能就是为什么您不太明白它的作用的原因。在“根区域”(即不在区域中的控制器文件夹)中存在一个不明确的控制器名称的怪癖。对于通向根区域的路线,但它在那里找不到控制器,它将扫描所有区域寻找匹配项。在这种情况下,它会在您的新闻命名空间中找到匹配项,并且可以正常工作。但这种扫描仅在只有一个匹配的控制器时才有效。因此,如果您要在另一个区域中创建具有相同名称的另一个控制器,它将失败并出现“找到多种类型”类型的异常。

您有两种好方法可以使这项工作更加可靠。通过优先考虑路由中的新闻区域,或者通过重定向:

重定向:

您可以将浏览器重定向到您希望它们启动的区域的 URL,而不是将根请求路由到特定区域中的控制器。因此,它们从“yoursite.com/”开始,并将被重定向到“yoursite.com/news/articles”URL。为此,您创建一个根级别控制器并使用默认路由。因此,在根控制器文件夹中(而不是在某个区域中)创建 HomeController。在该控制器上创建一个名为 Index 的操作方法。在该 Index 方法中,将它们重定向到您真正希望它们启动的控制器。

在 global.asax 中,您可以依赖一个相当标准的默认路由,如下所示:

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

在 Home 控制器上的 Index 操作中,只需使用 RedirectToAction 并将客户端重定向到新闻区域中的正确控制器并指定区域:

return RedirectToAction("IndexOfArticles", "Articles", new { area = "News" });

第二种技术是优先考虑路线,以便它知道要使用哪个区域。这不需要任何根级控制器。只需添加一个看起来有点像这样的路由条目:

routes.MapRoute(
    "Default",
    "{controller}/{acion}/{id}",
    new {controller = "Articles", action = "IndexOfArticles", id = UrlParameters.Optional},
    new[] {"YourApplication.News"}
);

这样做的缺点是第四个参数(命名空间)将应用于所有请求,因此可能会导致更多内容被重定向到您的特定新闻区域,而不是您想要的。最好对第二个参数更具体,这样该路由就不会捕获其他请求...也许将第二个参数设置为空字符串,以便它只捕获站点根请求。

Considering the nature of the questions you've been asking, I want to recommend a resource that I think you'll REALLY love. Steven Sanderson's book "Pro ASP.NET MVC 2 Framework (second edition)" by apress. Chapter 8 in particular goes into a LOT of detail about routing and areas. The book itself is excellent and thourough; one of the best examples of dev/programming books I've ever read. It is available in Kindle form, and if you order from apress directly you can get it in PDF e-book form. It is of course available in paper form too:

Amazon Link

or

Direct from Apress

The specific thing you might want to understand about areas are that they are based on namespaces. When you create an area, the namespace of that area is how MVC locates them and decides what is "in" and area and what isn't. Generally this means that routing to areas is done via the URLs that have the area's name as the first folder in the URL, but this maps to the controller's namespace, not necessarily the physical folder names (though they should match if you want to preserve your sanity).

The route in Manaf's example is working "by accident" more than by intent, which is probably why you aren't quite getting what it does. There is a quirk with ambiguous controller names in the "root area" (that is, the controller's folder that isn't in an area). For a route leads to the root area, but it can't find a controller there, it will scan all areas looking for a match. In this case it finds a match in your news namespace, and works. But this scanning only works if there is only one controller that matches. So if you were to create another controller in another area with the same name, it will fail with a "multiple types found" kind of exception.

You have two good ways to make this work more reliably. Either by prioritizing the news area in the routes, or by redirection:

Redirection:

Instead of routing root requests to a controller in a specific area, you can redirect the Browser to the URL of the area you want them to start on. So they start at "yoursite.com/" and will be redirected to the "yoursite.com/news/articles" URL. To do this, you create a root level controller and use the default route. So, create HomeController in the root controllers folder (not in an area). On that controller create an action method called Index. And in that Index method, redirect them to the controller you really want them to start on.

In global.asax, you can rely on a pretty standard default route like this:

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

In your Index action on the Home controller, just redirect the client to the correct controller in the news area using RedirectToAction and specifying the area:

return RedirectToAction("IndexOfArticles", "Articles", new { area = "News" });

The second technique is to prioritize the route so it knows which area to use. This doesn't require any root level controllers. Just add a route entry that looks a little like this:

routes.MapRoute(
    "Default",
    "{controller}/{acion}/{id}",
    new {controller = "Articles", action = "IndexOfArticles", id = UrlParameters.Optional},
    new[] {"YourApplication.News"}
);

The drawback to this is that the 4th parameter (namespaces) is going to apply to all requests, so it may cause more to be redirected to your specific news area than you wanted. It might be better to be more specific about the second parameter so this route doesn't catch other requests... perhaps set the second parameter to an empty string so it only catches a site root request.

平安喜乐 2024-09-25 13:22:18

到您的区域的自定义路由应该在您的 AreaRegistration 类中注册,而不是在 Global.asx.cs 中

添加路由,修改您的 NewsAreaRegistration 并在区域路由之后添加到您的服务器的新默认路由。 (这里的顺序很重要!)

默认路由应始终位于路由表的底部,以便可以匹配更具体的路由。

RegisterArea 方法中的路线应如下所示:

        context.MapRoute(
            "News_default",
            "News/{controller}/{action}/{id}",
            new { action = "Index", id = UrlParameter.Optional }
        );

        context.MapRoute(
            "DefaultStart",
            "",
            new { controller = "Articles", action = "IndexOfArticles"}
        );

更新:忘记提及您需要确保在 Application_Start 中注册您的区域> Global.asx.cs 文件中的方法。

AreaRegistration.RegisterAllAreas();

更新 2:路由在 ASP.NET MVC 中的工作原理

我理解您的担忧。让我简要解释一下路由的工作原理。

在 ASP.NET MVc 中,有一个路由表用于匹配所有 url 请求。

当您在 Global.asx.cs 或 AreaRegistration 中注册路由时,这些路由将按其注册顺序添加到路由表中(这就是顺序很重要的原因,我们应该将更具体的路由推到顶部,以便它们可以匹配)。

当涉及到区域路由(在 AreaRegistration 类中注册的路由)时。这些总是添加到路由表顶部的 Global.asx.cs 文件中注册的任何路由之前(区域路由是第一个要匹配的路由),因为否则您将错过匹配名为 News 的区域名为 News 的控制器。

如果您有多个区域,首先检查哪个区域的路线?我不是 100% 确定,但通过实验我发现它们是按创建时间排序的,旧区域首先出现在路由表的顶部。 (这并不重要,因为您不会有 2 个同名的区域)

示例:

假设您已经创建了以下区域。 NewsDashboardApi

并将以下路由添加到您的 NewsAreaRegistration 以匹配上面示例中的根路由

context.MapRoute(
        "DefaultStart",
        "",
        new { controller = "Articles", action = "IndexOfArticles"}
    );

您的路由表将看起来像这样像这样:

No   Route Name                        URL                               Explanation 
1   News_default         News/{controller}/{action}/{id}          Default For News Area
2   DefaultStart         (empty)                                  Root Route (match root url)
3   Dashboard_default    Dashboard/{controller}/{action}/{id}     Default For Dashboard Area
4   Api_default          Api/{controller}/{action}/{id}           Default For Api Area
5   Default              {controller}/{action}/{id}               Default (No Areas)

现在当您的应用程序收到请求时。它将一条一条地遍历路线并寻找匹配项。在我们的例子中,当您请求根 URL 时。将匹配第二条路线。因为我们设置了controller =“Articles”和action =“IndexOfArticles”的默认值,所以请求将被相应地重定向。

希望这有帮助。

Custom Routes to your Areas should be registered in your AreaRegistration class Not in Global.asx.cs

to add the route modify your NewsAreaRegistration and add the new default route to your server after the area route. (the order is important here !)

Default routes should always be in the bottom of the routing table so that more specific routes can be matched.

Your routes in the RegisterArea method should look something like this :

        context.MapRoute(
            "News_default",
            "News/{controller}/{action}/{id}",
            new { action = "Index", id = UrlParameter.Optional }
        );

        context.MapRoute(
            "DefaultStart",
            "",
            new { controller = "Articles", action = "IndexOfArticles"}
        );

Update : Forgot to mention that you need to make sure you registered your areas in the Application_Start method in the Global.asx.cs file.

AreaRegistration.RegisterAllAreas();

Update 2: How Routing Works In ASP.NET MVC

I understand your concern. Let me explain briefly how routing works.

In ASP.NET MVc there's one routing table that is used to match all url requests.

When you register a route in the Global.asx.cs or in AreaRegistration those routes are added to the routing table by the order they were registered by (that's why the orders is important and we should push our more specific routes to the top so they can get matched).

When it comes to Areas routes (those that are registered in the AreaRegistration class). Those are always added to he top of the routing table before any of the routes registered in the Global.asx.cs file ( Areas routs are the first ones to be matched) which make since because otherwise you will miss match an Area called News for a Controller named News.

If you have more than one area, which Area's routes get checked first ? I'm not 100% sure, but by experiment i found out that they are ordered by the creation time, old areas comes first at the top of the routing table. ( it doesn't really matter because you won't have 2 areas with the same name)

Examples:

Suppose you have created the following areas. News, Dashboard, Api

and added the following route to your NewsAreaRegistration to match the root route as in your example above

context.MapRoute(
        "DefaultStart",
        "",
        new { controller = "Articles", action = "IndexOfArticles"}
    );

Your routing table will look something like this:

No   Route Name                        URL                               Explanation 
1   News_default         News/{controller}/{action}/{id}          Default For News Area
2   DefaultStart         (empty)                                  Root Route (match root url)
3   Dashboard_default    Dashboard/{controller}/{action}/{id}     Default For Dashboard Area
4   Api_default          Api/{controller}/{action}/{id}           Default For Api Area
5   Default              {controller}/{action}/{id}               Default (No Areas)

Now when you application receives a request. It will go through the routes one by one and look for a match. In our case when your request the root url. The second route will be matched. and because we set the default values for controller = "Articles" and action ="IndexOfArticles" the request will be redirected accordingly.

Hope that was helpful.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文