ASP.NET MVC passant des modèles par ActionLink

je voudrais passer un modèle et un int pour un contrôleur en cliquant sur un ActionLink.

@Html.ActionLink("Next", "Lookup", "User", new { m = Model.UserLookupViewModel, page = Model.UserLookupViewModel.curPage }, null)

ne fonctionne pas, au lieu de cela il passe une instance Vierge du model, à laquelle on s'attendrait en utilisant new.

@Html.ActionLink("Next", "Lookup", "User", Model.UserLookupViewModel, null)

Ne fonctionne pas.

Controller

[HttpGet]
public ActionResult Lookup(UserLookupViewModel m, int page = 0)
{
    return this.DoLookup(m, page);
}

modèle de Vue

public class UserLookupViewModel
{
    public int curPage { get; set; }

    [Display(Name = "Forenames")]
    public string Forenames { get; set; }

    [Display(Name = "Surname")]
    public string Surname { get; set; }

    [Display(Name = "DOB")]
    public DateTime? DoB { get; set; }

    [Display(Name = "Post code")]
    public string Postcode { get; set; }
}

Comment puis-je passer ensemble? Lookup les arguments de la méthode correspondent aux propriétés nommées dans ActionLink.

20
demandé sur Lee 2014-02-03 17:48:36

3 réponses

vous ne pouvez pas utiliser un ActionLink pour passer des propriétés avec un lien mais vous pouvez faire ce qui suit pour obtenir le même comportement.

<form action="/url/to/action" Method="GET">
  <input type="hidden" name="Property" value="hello,world" />
  <button type="submit">Go To User</button>
</form>

Si vous créez un assistant pour générer ces GET formulaires, vous serez en mesure de style comme ils sont régulièrement des boutons de lien. La seule chose que j'ai en garde contre c'est que les formulaires sur la page sont susceptibles de modification de sorte que je ne ferais pas confiance aux données. Je préfère tirer les données à nouveau quand vous arrivez à l'endroit où vous êtes aller.

j'utilise la technique ci-dessus lors de la création d'actions de recherche et je veux conserver un historique de recherche et garder le bouton arrière de travail.

j'Espère que cette aide,

Khalid :)


P. S.

La raison pour laquelle cela fonctionne.

@Html.ActionLink("Next", "Lookup", "User", Model.UserLookupViewModel, null)

est parce que la liste des paramètres de la méthode ActionLink est généralisée pour prendre un objet, donc ça prend n'importe quoi. Ce qu'il va faire avec cet objet est de passer à un RouteValueDictionary et ensuite essayer de créer un querystring basé sur les propriétés de cet objet.

si vous dites que cette méthode fonctionne ci-dessus, vous pouvez aussi juste essayer d'ajouter une nouvelle propriété au viewmodel appelé Id et il fonctionnera comme tu le voulais.

10
répondu Khalid Abuhakmeh 2014-02-03 14:09:55

vous devrez sérialiser votre model en chaîne JSON, et l'Envoyer à votre controller pour qu'il se transforme en objet.

Voici votre actionlink:

@Html.ActionLink("Next", "Lookup", "User", new { JSONModel = Json.Encode(Model.UserLookupViewModel), page = Model.UserLookupViewModel.curPage }, null)

dans votre controller, vous aurez besoin d'une méthode pour transformer vos données JSON en un MemoryStream:

private Stream GenerateStreamFromString(string s)
{
  MemoryStream stream = new MemoryStream();
  StreamWriter writer = new StreamWriter(stream);
  writer.Write(s);
  writer.Flush();
  stream.Position = 0;
  return stream;
}

dans votre résultat D'Action, vous transformez la chaîne JSON en un objet:

public ActionResult YourAction(string JSONModel, int page)
{
  DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(Model.UserLookupViewModel));
  var yourobject =  (UserLookupViewModel)ser.ReadObject(GenerateStreamFromString(JSONModel));
}
9
répondu JKS77 2014-10-30 17:23:48

alors que je vous suggère fortement d'utiliser un formulaire pour accomplir ce que vous tentez de faire ici pour des raisons de sécurité.

 @Html.ActionLink("Next", "Lookup", "User", new 
      { Forenames = Model.UserLookupViewModel.Forenames, 
        Surname = Model.UserLookupViewModel.Surname, 
        DOB = Model.UserLookupViewModel.DOB,  
        PostCode = Model.UserLookupViewModel.PostCode, 
        page = Model.UserLookupViewModel.curPage }, null)

MVC mappera les propriétés de façon appropriée; cependant, ceci utilisera votre url pour passer les valeurs au controller. Cela affichera les valeurs que le monde entier verra.

je suggère fortement d'utiliser un formulaire pour des raisons de sécurité, surtout lorsqu'il s'agit de données sensibles telles que DOB.

je ferais personnellement quelque chose comme ceci:

 @using (Html.BeginForm("Lookup", "User")
 {
     @Html.HiddenFor(x => x.Forenames)
     @Html.HiddenFor(x => x.Surname)
     @Html.HiddenFor(x => x.DOB)
     @Html.HiddenFor(x => x.PostCode)
     @Html.HiddenFor(x => x.curPage)

     <input type="submit" value="Next" />
  }

Vous pouvez avoir plusieurs de ces types de formulaires sur la page si nécessaire.

Votre contrôleur accepte alors un poste, mais fonctionne de la même manière:

 [HttpPost]
 public ActionResult Lookup(UserLookupViewModel m, int page = 0)
 {
     return this.DoLookup(m, page);
 }
5
répondu Robert 2014-02-03 14:20:41