Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/296.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何使用MapRoute捕捉所有区域_C#_Asp.net Mvc_Asp.net Mvc Routing - Fatal编程技术网

C# 如何使用MapRoute捕捉所有区域

C# 如何使用MapRoute捕捉所有区域,c#,asp.net-mvc,asp.net-mvc-routing,C#,Asp.net Mvc,Asp.net Mvc Routing,我是MVC新手,正在编辑现有的应用程序。目前,我在RouteConfig.cs中看到以下内容: public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute( "Util",

我是MVC新手,正在编辑现有的应用程序。目前,我在RouteConfig.cs中看到以下内容:

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

        routes.MapRoute(
            "Util",
            "util/{action}",
            new {controller = "util"});

        routes.MapRoute(
            "Catchall",
            "{*url}",
            new {controller = "Main", action = "CatchUrl"});
    }
}
在主控制器内部有一个逻辑,它基本上执行
重定向路由
,并将称为
位置
的区域、控制器、操作和查询字符串设置为特定值

public class MainController : Controller
{
    public ActionResult CatchUrl()
    {
        var agencyId = 9;

        var routeValues = new RouteValueDictionary
        {
            {"area", "area1"},
            {"controller", "dashboard"},
            {"action", "index"},
            {"location", "testLocation"}
        };

        return RedirectToRoute(routeValues );
    }
}
这似乎很好,当您给它一个无效区域时,它会正确地进入默认区域

我还看到一个名为CustomAreaRegistration.cs的文件:

public abstract class CustomAreaRegistration : AreaRegistration
{
    public override void RegisterArea(AreaRegistrationContext context) 
    {
        context.MapRoute(
            AreaName + "Ajax",
            AreaName + "/{controller}/{action}",
            new { action = "Index" }
        );

        context.MapRoute(
            AreaName + "ShortUrl",
            AreaName + "/{controller}",
            new {action = "Index"}
            );
    }
}
我很难理解区域布线是如何工作的,以及它如何知道如何到达正确的控制器

此外,我正试图得到它,以便当你访问

/{area}/
它执行一些逻辑并将您重新分配到正确的控制器。类似于CatchUrl的工作方式

我的尝试:

    routes.MapRoute(
        "AreaIndex",
        "{module}/",
        new {controller = "Main", action = "Index"});
主控制器:

public class MainController : Controller
{
    public ActionResult Index()
    {
        var requestHost = HttpContext.Request.Url?.Host;
        var location= requestHost == "localhost" ? Request.QueryString["location"] : requestHost?.Split('.')[0];


        var routeValues = new RouteValueDictionary
        {
            {"area", ControllerContext.RouteData.Values["module"]},
            {"controller", "dashboard"},
            {"action", "index"},
            {"location", location}
        };

        return RedirectToRoute(routeValues );
    }

    public ActionResult CatchUrl()
    {
        var routeValues = new RouteValueDictionary
        {
            {"area", "area1"},
            {"controller", "dashboard"},
            {"action", "index"},
            {"location", "testLocation"}
        };

        return RedirectToRoute(routeValues );
    }
}
我得到

路由表中没有与提供的值匹配的路由


我不知道为什么CatchUrl有效,而我的无效。

我实际上没有理解你的要求,但仅仅通过查看代码,这不是在MVC 3、4和5中创建/使用
区域的标准方法

您不需要在每个控制器内编写逻辑并执行重定向

在我的
RouteConfig
中,我通常只有默认的路由映射。当您需要区域时,可以在VisualStudio中右键单击MVCWeb项目并单击“添加->区域”。这将在web项目根目录下的区域文件夹中创建一个区域名为的文件夹。在area文件夹中,您应该找到区域名称和映射的
AreaRegistration.cs

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

        routes.MapRoute(
            name: "default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "dashboard", action = "index", id = UrlParameter.Optional },
            namespaces: new[] { "Company.Project.Web.UI.Controllers" }
        );
    }
}
假设您想创建一个名为“Admin”的区域:

public class AdminAreaRegistration : AreaRegistration 
{
    public override string AreaName 
    {
        get 
        {
            return "admin";
        }
    }

    public override void RegisterArea(AreaRegistrationContext context) 
    {
        context.MapRoute(
            "admin_default",
            "admin/{controller}/{action}/{id}",
            new { action = "index", id = UrlParameter.Optional },
            namespaces: new[] { "Company.Project.Web.UI.Areas.Admin.Controllers" }
        );
    }
}
最后,我认为截图可能会有所帮助。

--更新--

根据注释,如果您希望路由
/apple?location=home
转到苹果控制器及其home方法,而路由
/orange?location=dashbard
转到orange控制器及其仪表板方法,最好在
RouteConfig
中定义路由

理想情况下,您希望在
RouteConfig
中有这样的功能:

        routes.MapRoute(
            name: "Area-CatchAll",
            url: "{area}?location={controller}"
        );
但这是不可能的,因为MVC会错误地说“路由URL不能以“/”或“~”字符开头,并且不能包含“?”字符。”

相反,您可以将流量定向到控制器,并将区域和位置定义为参数

routes.MapRoute(
    name: "Area-CatchAll",
    url: "{area}",
    defaults: new { controller = "Area", action = "Translate" }
);

public class AreaController : Controller
{
    // The {area} from route template will be mapped to this area parameter.
    // The location query string will be mapped to this location parameter.

    public ActionResult Translate(string area, string location)
    {
        // This also assumes you have defined "index" method and
        // "dashboard" controller in each area.

        if (String.IsNullOrEmpty(location))
        {
            location = "dashboard";
        }
        return RedirectToAction("index", location, new { area = area });
    }
}
再说一次,如果不需要的话,我不会创建这样的路线来将流量重定向到其他区域

我正在设法弄到它,这样当你来访时

/{area}/它执行一些逻辑并将您重新分配到正确的控制器。类似于CatchUrl的工作方式

首先,让我们弄清楚这一点。“全部捕获”路由不是路由,而是重定向。它向浏览器发出HTTP 302响应,通知浏览器在服务器上查找新位置。这类事情效率不高,因为它需要额外的网络往返,但这是从服务器端更改浏览器中URL的唯一方法(如果您打算这样做的话)

另一方面,路由是接收初始请求并将其直接发送到特定资源(控制器操作),而无需通过网络进行额外的往返,也无需更改浏览器中的URL

您的路由已设置为使用

/Area/Controller
要在此处路由到正确的控制器:

public abstract class CustomAreaRegistration : AreaRegistration
{
    public override void RegisterArea(AreaRegistrationContext context) 
    {
        context.MapRoute(
            AreaName + "Ajax",
            AreaName + "/{controller}/{action}",
            new { action = "Index" }
        );

        context.MapRoute(
            AreaName + "ShortUrl",
            AreaName + "/{controller}",
            new {action = "Index"}
        );
    }
}
(假设每个区域都有一个子类来设置
AreaName

如果确实要将
/module/
URL路由(而不是重定向)到相应区域中的
仪表板控制器.Index
方法,请更改
ShortUrl
,使
控制器成为可选的,并将其默认为
仪表板控制器

public abstract class CustomAreaRegistration : AreaRegistration
{
    public override void RegisterArea(AreaRegistrationContext context) 
    {
        context.MapRoute(
            AreaName + "Ajax",
            AreaName + "/{controller}/{action}",
            new { action = "Index" }
        );

        context.MapRoute(
            AreaName + "ShortUrl",
            AreaName + "/{controller}",
            new { controller = "Dashboard", action = "Index" }
        );
    }
}
这会将URL
/Foo/
发送到Foo区域的
仪表板控制器.Index
方法,但会将URL
/Foo/Bar/
发送到Foo区域的
BarController.Index
方法

以上假设您足够勤奋,以确保您的
AreaName
s与项目非区域部分中的控制器名称不相同。如果是,如果没有一些额外的配置(如路由约束),您将永远无法到达这些非区域控制器


根本不需要使用
MainController.Index
方法(除非您有特定的原因想在浏览器中更改URL)。

全面捕获的相关部分似乎是通配符组件
{*URL}
,我在
{module}/
路由中没有看到任何类似的内容。也许可以看看下面的相关信息:不让我编辑:我已经有工作区域了。我想通过
/area/
找到一个一应俱全的控制器,让他们有机会知道应该去哪个控制器。每个区域有两个主控制器,仪表板和详图。相反,特定人员获取仪表板或详细信息取决于发送到
/area/
/Apple/?location=foo
的get参数将转到
苹果
区域和仪表板控制器,而
/Apple/?location=bar
将转到
苹果
区域和详细信息控制器。举个例子,你可以为它创建路线。不需要控制器来处理这个问题看看我的更新,看看这是否就是你想要实现的@CuriousDeveloper@DavidLiang-
MapRoute
不能用于指定URL参数。但是,您可以通过子类化
RouteBase
Route
来实现。坦白地说,如果一个重定向是CuriousDeveloper真正想要的,我会为它创建一个全局过滤器,而不是创建一个只用于重定向的琐碎的控制器。我已经有了工作区域。我想要路线t的
/area/