C# 如何使用MapRoute捕捉所有区域
我是MVC新手,正在编辑现有的应用程序。目前,我在RouteConfig.cs中看到以下内容: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",
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/