2009-06-14 7 views
2

J'ai une page de connexion. Dans mon web.config je configure un loginUrl de sorte que si un utilisateur essaye d'aller à une page "autorisée" et ne soit pas autorisé ils seront redirigés vers la page de connexion.Avoir des problèmes avec Asp.net MVC passant dans un querystring comme paramètre

Maintenant, j'ai remarqué que lorsque cela se produit et que l'utilisateur est redirigé depuis une page "Autorisé", l'URL de la page à laquelle il est redirigé est ajoutée à l'URL de connexion.

Ainsi, quand ils se connectent, je peux les utiliser pour les renvoyer à la page qu'ils essayaient d'obtenir.

Voilà donc comment l'URL regarderait:

http://localhost:2505/CMS_Account/LogOn?ReturnUrl=%2fCMS_Home%2fIndex

Je suis en train de capturer le ReturnUrl querystring partie en tant que paramètre à mon avis.

Mais je n'arrive pas à le faire fonctionner.

Je suis donc trouvé si je change mon formulaire pour la connexion à ceci:

<% using (Html.BeginForm()) ........ 

Ensuite, je peux saisir l'ReturnUrl pour une raison quelconque aucun problème.

Mais comment je l'ai, j'ai en ce moment ceci:

<% using (Html.BeginForm("Login","Authentication",FormMethod.Post,new { id = "frm_Login"})) ..... 

Une fois que je tente de transmettre les paramètres dans le BeginForm il arrête la capture de l'ReturnUrl.

Je ne sais pas pourquoi ça s'arrête. Certaines personnes disent que c'est parce que j'utilise la route par défaut et d'une manière ou d'une autre, si vous ne mettez rien dans l'beingForm, il est possible de trouver par magie le ReturnUrl avec l'URL par défaut. Dès que vous mettez quelque chose dans BeginForm, il semble être bête et vous devez lui donner une route pour lui dire quoi faire.

Je ne sais pas comment écrire cet itinéraire. J'ai essayé pas mal de combinaisons différentes et elles ont toutes échoué, et tout le monde qui me dit juste une route ne me dit jamais à quoi cela devrait ressembler.

Donc je ne sais plus quoi essayer.

Ce que j'ai essayé

routes.MapRoute(
    "CMS_Account", // Route name 
    "CMS_Account/{action}/{ReturnUrl}", // URL with parameters 
    new { controller = "CMS_Account", action = "LogOn",} // Parameter defaults 
); 

routes.MapRoute(
    "CMS_Account", // Route name 
    "CMS_Account/{action}/{ReturnUrl}", // URL with parameters 
    new { controller = "CMS_Account", action = "LogOn", ReturnUrl = ""} // Parameter defaults 
); 

routes.MapRoute(
    "CMS_Account", // Route name 
    "{controller}/{action}/{ReturnUrl}", // URL with parameters 
    new { controller = "CMS_Account", action = "LogOn", ReturnUrl = ""} // Parameter defaults 
); 

routes.MapRoute(
    "CMS_Account", // Route name 
    "{controller}/{action}/{id}", // URL with parameters 
    new { controller = "CMS_Account", action = "LogOn", id = ""} // Parameter defaults 
); 

routes.MapRoute(
    "CMS_Account", // Route name 
    "{controller}/{action}/", // URL with parameters 
    new { controller = "CMS_Account", action = "LogOn"} // Parameter defaults 
); 

Répondre

6

Vous n'avez pas besoin de changer vos itinéraires. Ce qui est cool avec le moteur de routage, c'est que si vous ajoutez une valeur de route supplémentaire qui n'est pas déclarée dans la route elle-même, le moteur de routage la lancera à la fin en tant que variable get.

E.g. Avez-vous essayé de mettre le ReturnUrl dans BeginFrom?

Controller comme Dennis suggéré:

public ActionResult LogOn(string ReturnURL) { 
    ViewData["ReturnURL"] = ReturnURL; 
    return View(); 
} 

Alors, selon vous, vous aurez besoin d'utiliser le BeginForm (action chaîne, contrôleur de chaîne, routeValues ​​objet, méthode FormMethod, htmlAttributes objet) surcharge. Par exemple.

Html.BeginForm("Login", 
       "Authentication", 
       new { @returnUrl = ViewData["ReturnUrl"] }, 
       FormMethod.Post, 
       new { @id = "frm_Login" }) 

HTHS, Charles

EDIT: Sur une note de côté, l'inverse serait de mettre le ReturnUrl dans un champ d'entrée caché - après initial l'obtenir du querystring. Cela signifie que la valeur est alors dans votre collection de messages et que vous n'avez pas à vous soucier de la récupérer dans votre chaîne de requête.

+0

Hmm intéressant. Donc, fondamentalement, mettre ceci dans la valeur par défaut ActionResult (j'en ai 2 pour charger sans une requête "Post" et une pour.) Pour un, je ne vous ferais pas la première chose car cela entraînerait l'échec de la validation de w3c (le formulaire n'a pas attribut returnValue) et j'ai plutôt que ça passe. Le caché Je suppose que je pourrais faire celui-là mais j'essaie toujours de comprendre pourquoi laisser BeginForm vide peut trouver par magie comment le prendre de la chaîne de requête, mais quand j'ai "Post" réglé il ne peut pas. Je trouve juste que c'est tellement bizarre. – chobo2

+0

Désolé ... fait l'erreur d'ajouter returnUrl à la collection HtmlAttributes plutôt qu'à RouteValueCollection. J'ai édité la réponse pour refléter cela. – Charlino

+0

La raison pour laquelle un BeginForm() vide fonctionne est parce que quand vous utilisez un BeginForm vide(), il prend juste l'URL courante et l'utilise pour l'attribut 'action' du formulaire/url-i.e. Et parce que l'URL actuelle contient la valeur de la chaîne de requête ReturnUrl, elle sera dans l'attribut 'action' du formulaire. Mais quand vous commencez à passer des choses dans BeginForm(), le moteur de routage prend le relais et construit lui-même l'attribut/l'action 'action' du formulaire, donc vous perdrez la chaîne de requête ReturnUrl sauf si vous la remettez dans l'attribut action/url querystring ou dans une entrée cachée. – Charlino

1

Lorsque vous configurez le formulaire dans votre état « actuel », vous obligez à POST, mais les données que vous voulez est sur la chaîne de requête.

Vous pouvez y accéder avec ControllerContext.HttpContext.Request.Querystring["ReturnURL"]

ou ...

Ajouter le ReturnURL comme un champ caché sous la forme, et assurez-vous que votre méthode de connexion que vous soit à poster:

  • Accepte ReturnURL en tant que paramètre
  • Effectue une demande.Form ["ReturnURL"]

pour obtenir la valeur d'URL à partir du formulaire HTML.

+0

Hmm Ic j'ai 2 méthodes de ActionResult qui est: // public ActionResult LogOn() {// // retour View(); //} puis une autre actionResult avec le même nom mais il a [AcceptVerbs (HttpVerbs.Post)] donc j'ai commenté le précédent et enlevé le Post et ça marche maintenant. Je ne comprends pas pourquoi si vous utilisez forcer un POST il ne peut pas attraper la chaîne de requête mais en même temps si je quitte le formulaire sans paramètres et a tout ce que je l'ai laissé (ie avoir une méthode avec attribut Post). Cela fonctionne très bien. – chobo2

+0

Donc, il n'y a pas moyen de contourner cela? Autre alors ce que vous avez posté il semble juste si stupide qu'ils ont mis un moyen d'autoriser seulement les messages et d'autres choses mais si vous le spécifiez comme ceci <% using (Html.BeginForm ("Login", "Authentication", FormMethod.Post, new {id = "frm_Login"})) ... Tout d'un coup, il n'arrive pas à comprendre. mais si ce BeginForm est vide, il peut en quelque sorte comprendre d'aller à l'ActionResult marqué "Post" et toujours récupérer le ReturnUrl. Ensuite, je ne peux pas croire que ce n'est pas comme écrit dans les livres que j'ai lus ou sur les tutoriels comme cela pour moi semble être quelque chose beaucoup de ppl ferait. – chobo2

+0

En fait, je ne comprends pas l'avantage de spécifier les choses? Comme pourquoi s'embêter à écrire tout ce truc comme je l'ai écrit? <% using (Html.BeginForm ("Connexion", "Authentification", FormMethod.Post, nouveau {id = "frm_Login"})) ... Autre alors peut-être si vous voulez lui donner un " id "ou quelque chose. On dirait que le laisser vide vous donne plus d'avantages et vous pouvez toujours étiqueter les résultats ActionResults "Post" ou "Get" et il trouve toujours. PS cette limite de caractères est vraiment gay ....... – chobo2

3

Vous n'avez pas besoin de modifier vos itinéraires.

La meilleure façon d'obtenir le paramètre ReturnURL (ou tout autre paramètre de chaîne de requête) est pour l'ajouter à votre action LogOn comme ceci:

public ActionResult LogOn(string ReturnURL) { 
    ViewData["ReturnURL"] = ReturnURL; 
    return View(); 
} 
+0

La chose est que je dois LogOn actionResult et l'un d'eux a le "post" et quand j'essaie de passer dans mon ReturnUrl comme vous l'avez, il vient juste à zéro. – chobo2

0

Avez-vous essayé d'utiliser le système intégré de FormsAuthentications?

Si vous pouvez l'utiliser, vous n'avez pas à implémenter la fonctionnalité que vous décrivez.

Je n'ai pas vérifier cela dans MVC, mais il devrait fonctionner:

FormsAuthentication.RedirectFromLoginPage(LogInAsUserName.Text, False) 

FormsAuthentications - 4guysfromrolla

+0

Je vais devoir vérifier cela techniquement quand ils sont redirigés de la page autorisée qui devrait être la dernière page d'où ils viennent afin que cela fonctionne. Je vais essayer ça. Juste suce le vous avez ce stupide BackUrl qui traîne autour qui ne fait rien. De toute façon pour m'en débarrasser si je trouve que ça fonctionne? – chobo2

+0

Plus tous les avantages d'utiliser ReturnUrl à la place comme une raison que j'ai vu les gens utilisent comme ReturnUrl est qu'ils peuvent écrire des tests unitaires pour voir si l'utilisateur obtient la redirection ou quelque chose comme ça. – chobo2

+0

Vous aurez toujours le Querystring avec la page qui a besoin d'une autorisation. Mais il n'est pas nécessaire de le gérer dans votre itinéraire et votre action. –

Questions connexes