Server.TransferRequest
es complètement inutile en MVC . Il s'agit d'une fonctionnalité archaïque qui n'était nécessaire dans ASP.NET que parce que la demande arrivait directement sur une page et qu'il fallait trouver un moyen de transférer une demande vers une autre page. Les versions modernes de ASP.NET (y compris MVC) disposent d'une infrastructure de routage qui peut être personnalisée pour acheminer les requêtes vers directement à la ressource souhaitée. Il est inutile de laisser la demande atteindre un contrôleur pour ensuite la transférer à un autre contrôleur alors que vous pouvez simplement faire en sorte que la demande aille directement au contrôleur et à l'action que vous souhaitez.
De plus, puisque vous répondez à la original demande, il n'y a pas besoin de rentrer quoi que ce soit dans la TempData
ou autre stockage juste pour acheminer la demande au bon endroit. Au lieu de cela, vous arrivez à l'action du contrôleur avec la requête originale intacte. Vous pouvez également être sûr que Google approuvera cette approche, car elle se déroule entièrement du côté du serveur.
Bien que vous puissiez faire beaucoup de choses à partir des deux IRouteConstraint
y IRouteHandler
le point d'extension le plus puissant pour l'acheminement est l'outil de routage. RouteBase
sous-classe. Cette classe peut être étendue pour fournir à la fois des routes entrantes et la génération d'URL sortantes, ce qui en fait un guichet unique pour tout ce qui concerne l'URL et l'action qu'elle exécute.
Donc, pour suivre votre deuxième exemple, pour passer de /
a /home/7
vous avez simplement besoin d'une route qui ajoute les valeurs de route appropriées.
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 }
);
}
}
Mais pour en revenir à votre exemple initial où vous avez une page aléatoire, c'est plus complexe car les paramètres de la route ne peuvent pas changer au moment de l'exécution. Donc, cela pourrait être fait avec un RouteBase
comme suit.
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;
}
}
Qui peut être enregistré dans le routage comme :
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 }
);
}
}
Notez que dans l'exemple ci-dessus, il pourrait être judicieux de stocker également un cookie enregistrant la version de la page d'accueil sur laquelle l'utilisateur est arrivé, de sorte que lorsqu'il revient, il reçoit la même version de la page d'accueil.
Notez également qu'en utilisant cette approche, vous pouvez personnaliser le routage pour prendre en compte les paramètres des chaînes de requête (il les ignore complètement par défaut) et le diriger vers une action de contrôleur appropriée.
Exemples supplémentaires
0 votes
Qu'est-ce qu'un
ServerTransferAction
que vous essayiez de reproduire ? Est-ce une chose réelle ? (je n'ai trouvé aucune information à ce sujet... merci pour la question, d'ailleurs, la réponse ci-dessous est superbe).1 votes
Recherchez Server.Transfer(...). C'est un moyen de faire une 'redirection' du côté du serveur où le client reçoit la page redirigée sans redirection du côté du client. En général, ce n'est pas recommandé avec le routage moderne.
1 votes
Le "transfert" est une fonctionnalité ASP.NET désuète qui n'est plus nécessaire dans MVC en raison de la possibilité de aller directement à l'action correcte du contrôleur en utilisant le routage. Voir cette réponse pour les détails.
0 votes
@NightOwl888 oui, sans aucun doute - mais parfois aussi, en raison de la logique commerciale, c'est nécessaire/plus facile. J'ai regardé en arrière pour voir où j'avais fini par l'utiliser (heureusement, ce n'était qu'à un seul endroit). J'avais une page d'accueil que je voulais dynamique pour certaines conditions complexes et donc, en coulisses, elle affichait un itinéraire différent. Je veux vraiment éviter cela autant que possible en faveur des conditions de routage ou d'itinéraire, mais parfois un simple
if
La déclaration est une solution trop tentante.0 votes
@Simon_Weaver - Et qu'est-ce qui ne va pas avec la sous-classification ?
RouteBase
pour que vous puissiez mettre votreif
déclaration là au lieu de se plier en quatre pour passer d'un contrôleur à l'autre ?