Server.TransferRequest
在 MVC中完全没有必要。这是一个过时的功能,仅在 ASP.NET 中才需要,因为请求直接到达一个页面,并且需要有一种方法将请求传输到另一个页面。现代版本的 ASP.NET(包括 MVC)有一个路由基础结构,可以自定义以直接路由到所需的资源。当您可以简单地将请求直接发送到您想要的控制器和操作时,让请求到达控制器只是将其传输到另一个控制器是没有意义的。
更重要的是,由于您正在响应原始请求,因此无需TempData
为了将请求路由到正确的位置而将任何东西放入或其他存储中。相反,您会在原始请求完好无损的情况下到达控制器操作。您也可以放心,Google 会批准这种方法,因为它完全发生在服务器端。
虽然您可以从IRouteConstraint
和做很多事情IRouteHandler
,但最强大的路由扩展点是RouteBase
子类。可以扩展此类以提供传入路由和传出 URL 生成,这使其成为与 URL 和 URL 执行的操作有关的所有事情的一站式商店。
因此,按照您的第二个示例,要从/
to获取/home/7
,您只需要一个添加适当路由值的路由。
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
// Routes directy to `/home/7`
routes.MapRoute(
name: "Home7",
url: "",
defaults: new { controller = "Home", action = "Index", version = 7 }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
但是回到你有一个随机页面的原始示例,它更复杂,因为路由参数在运行时不能改变。所以,它可以用一个RouteBase
子类来完成,如下所示。
public class RandomHomePageRoute : RouteBase
{
private Random random = new Random();
public override RouteData GetRouteData(HttpContextBase httpContext)
{
RouteData result = null;
// Only handle the home page route
if (httpContext.Request.Path == "/")
{
result = new RouteData(this, new MvcRouteHandler());
result.Values["controller"] = "Home";
result.Values["action"] = "Index";
result.Values["version"] = random.Next(10) + 1; // Picks a random number from 1 to 10
}
// If this isn't the home page route, this should return null
// which instructs routing to try the next route in the route table.
return result;
}
public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
{
var controller = Convert.ToString(values["controller"]);
var action = Convert.ToString(values["action"]);
if (controller.Equals("Home", StringComparison.OrdinalIgnoreCase) &&
action.Equals("Index", StringComparison.OrdinalIgnoreCase))
{
// Route to the Home page URL
return new VirtualPathData(this, "");
}
return null;
}
}
可以在路由中注册,例如:
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
// Routes to /home/{version} where version is randomly from 1-10
routes.Add(new RandomHomePageRoute());
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
请注意,在上面的示例中,还可以存储一个 cookie 记录用户进入的主页版本,这样当他们返回时,他们会收到相同的主页版本。
另请注意,使用这种方法,您可以自定义路由以考虑查询字符串参数(默认情况下完全忽略它们)并相应地路由到适当的控制器操作。
其他示例