Asp.Net 路由,如果未定义 url 参数,则重定向到主页



我有两条路线

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

当用户转到主页时,他必须选择两个链接:

<a href="/loc1/Products/index">Location 1</a>
<a href="/loc2/Products/index">Location 2</a>

我也有ActionFilterAttribute,我在其中检查location参数,如果 url 没有它,我会将用户重定向到主页。

public override void OnActionExecuting(ActionExecutingContext filterContext)
{
string location = (string)filterContext.RouteData.Values["location"];
if (string.IsNullOrEmpty(location) 
&& filterContext.ActionDescriptor.ControllerDescriptor.ControllerName != "Home" 
&& !filterContext.IsChildAction)
{
filterContext.Result = new RedirectToRouteResult(
new RouteValueDictionary 
{ 
{ "controller", "Home" }, 
{ "action", "Index" } 
});
}

SessionUtils.SetLocationName(location);
}

根据location变量,我将从数据库中查询不同的记录,因此当用户在 url 中不提供任何位置并尝试访问Products/index/5我希望他们被重定向到他们必须选择位置并单击其中一个链接的主页。 但是我收到错误消息:

找不到资源。

说明:HTTP 404。要查找的资源(或其依赖项之一)可能已被删除、名称已更改或暂时不可用。 请查看以下 URL 并确保拼写正确。

请求的网址:/产品/索引

我应该如何正确配置路由,以便在 url 中没有位置参数的情况下将用户重定向到主页?

您的"默认"路线(包括位置)是唯一会被击中的路线。controlleractionid参数都是可选的,因此对类似/Products/Index的请求实际上将被您的"默认"路由捕获,并且location参数将被赋予"产品",您的controller参数将被赋予"索引"作为值。action参数将是"索引"的默认值,id参数将被忽略。由于您显然没有具有Index操作的IndexController,因此您将获得404。

要区分路由,您需要使您的"默认"路由需要某种硬编码前缀,即

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

然后,/Products/Index路线将落入您的"主页"路线,并被正确解释为通往ProductsController.Index的路线。或者,您可以将路由约束应用于location参数,因此它不会匹配所有内容,即:

routes.MapRoute(
name: "Default",
url: "{location}/{controller}/{action}/{id}",
defaults: new { controller = "Products", action = "Index", id = UrlParameter.Optional },
constraints: new { location = @"^(loc1|loc2)$" }
);

然后,除非URL的第一部分与loc1loc2匹配,否则它将落入"Home"路由。

您是否考虑过硬编码的默认路由和故障安全路由?

routes.MapRoute("Home", "", new { controller = "Home", action = "Index" });
/*     Normal routing logic here     */
routes.MapRoute("FailSafe", "{*url}", new { controller = "Home", action = "Index"}); // !=Last Line=!

尝试在Default路由之前添加自定义route

routes.MapRoute(
name: "Location1Route",
url: "{location}/{controller}/{action}",
defaults: new { controller = "Home", action = "Index" }
);

这将满足您的需求。

结合所有答案,尤其是解释,我想出了这个配置

路由配置:

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

OnActionExecuting中的一些逻辑

if (string.IsNullOrEmpty(location) 
&& cookie != null
&& !string.IsNullOrEmpty(cookie.Values["location"])
&& filterContext.ActionDescriptor.ActionName == "LandingPage"
&& filterContext.ActionDescriptor.ControllerDescriptor.ControllerName == "Home")
{
filterContext.Result = new RedirectToRouteResult(
new RouteValueDictionary
{
{ "location", cookie.Values["location"]},
{ "controller", "Measurements" },
{ "action", "Index" }
}
);
}
else if (string.IsNullOrEmpty(location) 
&& filterContext.ActionDescriptor.ControllerDescriptor.ControllerName != "Home" 
&& !filterContext.IsChildAction)
{
filterContext.Result = new RedirectToRouteResult(
new RouteValueDictionary
{
{ "controller", "Home" },
{ "action", "LandingPage" }
}
}

如果仅提供位置,则它将使用第一个路由,该路由将重定向到Products控制器。

如果路由中的所有三个locationcontrolleraction参数都匹配,则将使用第二条路由。我没有提供默认controlleraction。这允许在重定向到HomeController时使用最后的路由。

第三条路线将有两个参数 -controlleraction,这使我可以在HomeController中获取默认视图。使用OnActionExecuting,如果它不指向HomeControllerLandingPage,我将重定向到此默认视图和控制器。

最新更新