2009-08-02 9 views
4

J'ai un formulaire rendu via Html.BeginForm(), il existe en tant que composant dans la page Master afin qu'il apparaisse sur chaque page Dans l'application. Je l'ai fait en utilisant Html.RenderAction() de l'assemblage Mvc Futures. C'est un formulaire de recherche simple qui met à jour certains éléments dans le même composant sous le formulaire de recherche lui-même, et effectue un GET pour que le terme de recherche apparaisse dans la chaîne de requête.ASP.NET MVC - Obtenir Html.BeginForm() pour se rappeler des paramètres Querystring lors de la soumission via GET

<div class="sideBarContent"> 
    <h2>Search Products</h2> 

    <% using (Html.BeginForm(ViewContext.RouteData.Values["action"].ToString(), 
     ViewContext.RouteData.Values["controller"].ToString(), FormMethod.Get)) { %> 

     <fieldset> 
     <legend>Search Products</legend> 

     <div class="formRow"> 
      <label for="ProductsSearch">Search</label> 
      <%= Html.TextBox("ProductsSearch") %> 
     </div> 

     <input type="submit" value="Search" class="button" /> 
     </fieldset> 

    <% } %> 

    <ul> 
     // Products will eventually be listed here 
    </ul> 
</div> 

J'ai besoin ce formulaire pour faire ce qui suit:.

1) Il doit effectuer une requête GET à ce que la page actuelle, il est sur annexant « ProduitsRecherche » en tant que paramètre querystring (par exemple example.com/ ? ProduitsRecherche = test ou example.com/books/fiction?ProductsSearch=test)

2) Il ne faut pas oublier tous les paramètres querystring exising qui sont déjà dans le querystring, les maintenant après avoir cliqué sur le bouton Rechercher par exemple. example.com/myOrders?page=2 après la recherche cliquez devrait aller à example.com/myOrders?page=2 & ProduitsRecherche = test)

Je peux l'obtenir pour faire 1) mais ne peut pas travailler 2). Je suppose que normalement pour un de à GET et en ajoutant des paramètres querystring il doit avoir des champs de formulaire cachés, donc je pourrais écrire une fonction utilitaire qui ajoute automatiquement un tas de champs de formulaire cachés pour toutes les valeurs de chaîne de requête, mais je voulais vérifiez qu'il n'y a pas eu d'approche plus facile, ou peut-être que je m'y prends mal.

À la votre!

Répondre

9

Vous devrez utiliser la méthode du champ de formulaire caché.

Même si vous pouviez associer l'intégralité de la chaîne de requête à la fin de l'URL dans l'attribut d'action de la balise forme >, les navigateurs ne font pas attention à cela lors de la soumission de formulaires GET.

Votre méthode n'est pas trop difficile; vous voulez faire quelque chose comme ceci:

public static string QueryStringAsHidden(this HtmlHelper helper) 
{ 
    var sb = new StringBuilder(); 
    foreach (var key in HttpContext.Current.Request.QueryString.AllKeys) 
    { 
     if (! key.StartsWith("ProductSearch")) 
      sb.Append(helper.Hidden(key, HttpContext.Current.Request.QueryString[key])); 
    } 
     return sb.ToString(); 
    } 

Je mets le .StartsWith() là-bas parce que vous ne voulez pas être sur une page de recherche et soumettre la chaîne de recherche deux fois (et maintenant vous pouvez préfixer recherche de personnes et d'autres variables spécifiques à la recherche avec ProductSearch

Edit: PS:.. pour obtenir le formulaire de poster sur la page en cours, vous ne devez pas fournir explicitement l'action et contrôleur - vous pouvez également envoyer nulls

Éditer2: Pourquoi même s'embêter avec une méthode d'aide? :)

<% HttpContext.Current.Request.QueryString.AllKeys.Where(k => !k.StartsWith("ProductSearch")).ToList().ForEach(k => Response.Write(Html.Hidden(k, HttpContext.Current.Request.QueryString[k]))); %> 

James

+0

Vous pouvez également rendre cela plus réutilisable en faisant en sorte que la clé ProductSearch vérifie un paramètre. Vous pouvez aussi linq-ify, par exemple QueryString.AllKeys.Where (x =>! X.StartsWith ("ProductSearch")) –

+0

True. Et vous pouvez vous débarrasser de toute la boucle foreach() ... HttpContext.Current.Request.QueryString.AllKeys.Where (k =>! K.StartsWith (sauf)). ToList(). ForEach (k => sb. Append (helper.Hidden (k, HttpContext.Current.Request.QueryString [k]))); :) –

+0

@JamesS merci - Je ne sais pas si les choses sont toujours les mêmes depuis que vous avez posté ceci, mais j'essayais toutes sortes de choses pour que cela fonctionne, mais j'ai opté pour une approche de terrain caché selon votre réponse ci-dessus – Haroon

-1

Utilisez l'une des surcharges de BeginForm qui prend un routeValues ​​ou un dictionnaire objectera.

Les propriétés supplémentaires qui ne sont pas dans la route seront ajoutées en tant que paramètres de requête.

+1

Ce n'est pas si facile. Même si la méthode de votre tag est "/ Contrôleur/Action? A = 1 & b = 2 & c = 3", les navigateurs (au moins FF) supprimeront la chaîne de requête. –

1

Un appel direct à BeginForm() conserve vos valeurs de chaîne de requête.Toute autre surcharge a tendance à échouer. J'aime la facilité d'utilisation de BeginForm() à partir de mes formulaires, mais j'avais besoin d'un moyen de classer toutes mes formes stylées d'une certaine manière et de ne pas perdre les valeurs de chaîne de requête dans l'action.

Voici ce que je suis venu avec:

public static MvcForm BeginNormalForm<T>(this HtmlHelper<T> htmlHelper) 
{ 
    var dictionary = new Dictionary<string, object> {{"class", "normal"}}; 
    var rvd = new RouteValueDictionary(); 
    if (htmlHelper.ViewContext.HttpContext != null && htmlHelper.ViewContext.HttpContext.Request != null) 
    { 
     foreach (var key in htmlHelper.ViewContext.HttpContext.Request.QueryString.AllKeys) 
     { 
      rvd[key] = htmlHelper.ViewContext.HttpContext.Request.QueryString[key]; 
     } 
    } 
    var form = htmlHelper.BeginForm(null, null, rvd, FormMethod.Post, dictionary); 
    return form; 
} 

semble bien fonctionner et conserve mon attribut de classe.

Questions connexes