ASP.NET MVC 5 自定义路由执行错误操作
ASP.NET MVC 5 custom route goes to wrong action
我在使用未正确路由的自定义路由时遇到问题。 @Html.ActionLink
和 @Html.RouteLink
都创建了正确的 url fantasy/1/fantasyleague1/matchups
,点击时不会触及 Matchups Action 并且错误地路由到 fantasy/1/fantasyleague1/settings?round=3
RouteDebugger 显示:
Matched Route: Fantasy/{leagueID}/{leagueSlug}/Settings
Generated URL: /fantasy/11/fantasyleague1/matchups/3 using the route "Fantasy/{leagueID}/{leagueSlug}/Matchups/{round}"
RouteConfig.cs
routes.MapRoute(
name: "Fantasy League Matchups",
url: "Fantasy/{leagueID}/{leagueSlug}/Matchups/{round}",
defaults: new { controller = "Fantasy", action = "Matchups", leagueSlug = UrlParameter.Optional, round = UrlParameter.Optional },
constraints: new { leagueID = @"\d+" }
);
routes.MapRoute(
name: "Fantasy League Settings",
url: "Fantasy/{leagueID}/{leagueSlug}/Settings",
defaults: new { controller = "Fantasy", action = "Settings", leagueSlug = UrlParameter.Optional },
constraints: new { leagueID = @"\d+" }
);
FantasyController.cs
// GET: /Fantasy/{leagueID}/{leagueSlug}/Matchups/{round}
public ActionResult Matchups(int leagueID, string leagueSlug = null, int round = -1) {
var fantasyLeague = DataContext.FantasyLeagues.Where(l => l.ID == leagueID).FirstOrDefault();
if (fantasyLeague != null) {
if (string.IsNullOrEmpty(leagueSlug) || round == -1) {
return RedirectToActionPermanent("Matchups", "Fantasy", new { leagueID = leagueID, leagueSlug = fantasyLeague.Slug, round = fantasyLeague.CurrentRound });
}
var userInLeague = User != null && User.Identity != null && fantasyLeague.FantasyTeams.Any(t => t.Owner.UserName == User.Identity.Name);
var fantasyMatches = fantasyLeague.FantasyMatches.Where(fm => fm.Round == round).ToList();
return View("Matchups", new FantasyMatchupsViewModel {
FantasyLeague = fantasyLeague,
FantasyMatches = fantasyMatches,
Round = round,
UserInLeague = userInLeague
});
}
return RedirectToAction("Index");
}
// GET: /Fantasy/{leagueID}/{leagueSlug}/Settings
public ActionResult Settings(int leagueID, string leagueSlug = null) {
var fantasyLeague = DataContext.FantasyLeagues.Where(l => l.ID == leagueID).FirstOrDefault();
if (fantasyLeague != null) {
if (string.IsNullOrEmpty(leagueSlug)) {
return RedirectToActionPermanent("Settings", "Fantasy", new { leagueID = leagueID, leagueSlug = fantasyLeague.Slug });
}
var userOwnsLeague = User != null && User.Identity != null && fantasyLeague.Commissioner.UserName == User.Identity.Name;
return View("Settings", new FantasySettingsViewModel {
FantasyLeague = fantasyLeague,
UserOwnsLeague = userOwnsLeague,
Name = fantasyLeague.Name,
MaxPlayers = fantasyLeague.MaxPlayers,
LockoutPeriod = fantasyLeague.LockoutPeriod,
PasswordProtected = fantasyLeague.PasswordProtected,
Password = fantasyLeague.Password
});
}
return RedirectToAction("Index");
}
很可能,这根本不是路由问题。您正在使用 RedirectToActionPermanent
,它会产生 301 重定向。大多数浏览器都会缓存 301 重定向,因此您看到的行为很可能来自浏览器缓存的第一次命中。
您应该使用 RedirectToAction
,而不是使用 RedirectToActionPermanent
,这将生成 "normal" 302 重定向。
301 重定向是为了确保 URL 已经投入使用(也就是说,用户可能已将 and/or 搜索引擎可能已编入索引)更新到新位置。它们通常不应仅用于在您的应用程序中将用户从 URL A 转移到 URL B。
我在使用未正确路由的自定义路由时遇到问题。 @Html.ActionLink
和 @Html.RouteLink
都创建了正确的 url fantasy/1/fantasyleague1/matchups
,点击时不会触及 Matchups Action 并且错误地路由到 fantasy/1/fantasyleague1/settings?round=3
RouteDebugger 显示:
Matched Route: Fantasy/{leagueID}/{leagueSlug}/Settings
Generated URL: /fantasy/11/fantasyleague1/matchups/3 using the route "Fantasy/{leagueID}/{leagueSlug}/Matchups/{round}"
RouteConfig.cs
routes.MapRoute(
name: "Fantasy League Matchups",
url: "Fantasy/{leagueID}/{leagueSlug}/Matchups/{round}",
defaults: new { controller = "Fantasy", action = "Matchups", leagueSlug = UrlParameter.Optional, round = UrlParameter.Optional },
constraints: new { leagueID = @"\d+" }
);
routes.MapRoute(
name: "Fantasy League Settings",
url: "Fantasy/{leagueID}/{leagueSlug}/Settings",
defaults: new { controller = "Fantasy", action = "Settings", leagueSlug = UrlParameter.Optional },
constraints: new { leagueID = @"\d+" }
);
FantasyController.cs
// GET: /Fantasy/{leagueID}/{leagueSlug}/Matchups/{round}
public ActionResult Matchups(int leagueID, string leagueSlug = null, int round = -1) {
var fantasyLeague = DataContext.FantasyLeagues.Where(l => l.ID == leagueID).FirstOrDefault();
if (fantasyLeague != null) {
if (string.IsNullOrEmpty(leagueSlug) || round == -1) {
return RedirectToActionPermanent("Matchups", "Fantasy", new { leagueID = leagueID, leagueSlug = fantasyLeague.Slug, round = fantasyLeague.CurrentRound });
}
var userInLeague = User != null && User.Identity != null && fantasyLeague.FantasyTeams.Any(t => t.Owner.UserName == User.Identity.Name);
var fantasyMatches = fantasyLeague.FantasyMatches.Where(fm => fm.Round == round).ToList();
return View("Matchups", new FantasyMatchupsViewModel {
FantasyLeague = fantasyLeague,
FantasyMatches = fantasyMatches,
Round = round,
UserInLeague = userInLeague
});
}
return RedirectToAction("Index");
}
// GET: /Fantasy/{leagueID}/{leagueSlug}/Settings
public ActionResult Settings(int leagueID, string leagueSlug = null) {
var fantasyLeague = DataContext.FantasyLeagues.Where(l => l.ID == leagueID).FirstOrDefault();
if (fantasyLeague != null) {
if (string.IsNullOrEmpty(leagueSlug)) {
return RedirectToActionPermanent("Settings", "Fantasy", new { leagueID = leagueID, leagueSlug = fantasyLeague.Slug });
}
var userOwnsLeague = User != null && User.Identity != null && fantasyLeague.Commissioner.UserName == User.Identity.Name;
return View("Settings", new FantasySettingsViewModel {
FantasyLeague = fantasyLeague,
UserOwnsLeague = userOwnsLeague,
Name = fantasyLeague.Name,
MaxPlayers = fantasyLeague.MaxPlayers,
LockoutPeriod = fantasyLeague.LockoutPeriod,
PasswordProtected = fantasyLeague.PasswordProtected,
Password = fantasyLeague.Password
});
}
return RedirectToAction("Index");
}
很可能,这根本不是路由问题。您正在使用 RedirectToActionPermanent
,它会产生 301 重定向。大多数浏览器都会缓存 301 重定向,因此您看到的行为很可能来自浏览器缓存的第一次命中。
您应该使用 RedirectToAction
,而不是使用 RedirectToActionPermanent
,这将生成 "normal" 302 重定向。
301 重定向是为了确保 URL 已经投入使用(也就是说,用户可能已将 and/or 搜索引擎可能已编入索引)更新到新位置。它们通常不应仅用于在您的应用程序中将用户从 URL A 转移到 URL B。