Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.NET MVC Passing models by ActionLink

Tags:

I would like to pass a model and an int to a controller upon clicking an ActionLink.

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

Does not work, instead it passes a blank instance of the model, which one would expect when using new.

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

Does work.

Controller

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

View model

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; }
}

How can I pass them together? The Lookup method's arguments match the named properties in the ActionLink.

like image 603
Lee Avatar asked Feb 03 '14 13:02

Lee


People also ask

How use ActionLink HTML in ASP NET MVC?

HTML Links The easiest way to render an HTML link in is to use the HTML. ActionLink() helper. With MVC, the Html. ActionLink() does not link to a view.


2 Answers

You can't use an ActionLink to pass properties with a Link but you can do the following to get the same behavior.

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

If you create a helper to generate these GET forms, you will be able to style them like they are regular link buttons. The only thing I caution against is that ALL forms on the page are susceptible to modification so I wouldn't trust the data. I'd rather just pull the data again when you get to where you are going.

I use the technique above when creating search actions and want to retain a search history and keep the back button working.

Hope this helps,

Khalid :)


P.S.

The reason this works.

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

Is because the parameter list of the ActionLink method is generalized to take an object, so it will take anything. What it will do with that object is pass it to a RouteValueDictionary and then try to create a querystring based on the properties of that object.

If you say that method is working above, you could also just try adding a new property to the viewmodel called Id and it will work like you wanted it to.

like image 156
Khalid Abuhakmeh Avatar answered Jan 16 '23 11:01

Khalid Abuhakmeh


You'll have to serialize your model as a JSON string, and send that to your controller to turn into an object.

Here's your actionlink:

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

In your controller, you'll need a method to turn your JSON data into a 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;
}

In your ActionResult, you turn the JSON string into an object:

public ActionResult YourAction(string JSONModel, int page)
{
  DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(Model.UserLookupViewModel));
  var yourobject =  (UserLookupViewModel)ser.ReadObject(GenerateStreamFromString(JSONModel));
}
like image 41
JKS77 Avatar answered Jan 16 '23 12:01

JKS77