开发者

ASP.NET MVC - Trouble passing model in Html.ActionLink routeValues

My View looks like this:

<%@ Control Language="C#" 
 开发者_如何学Python   Inherits="System.Web.Mvc.ViewUserControl<TMS.MVC.BusinessSystemsSupport.Models.SearchDataTypeModel>" %>


<table class="classQueryResultsTable">
   <!-- the header -->
  <tr class="headerRow">

      <td>
      <%= Html.ActionLink("Effective Startdate",
                  "SortDetails",
                  "DataQryUpdate",
                  new
                  {
                      model = Model,
                      sortBy = "EffectiveStartDate",
                  },
                  new { @class = "classLinkLogDetails" })%>
      </td>

  </tr>


</table>

My controller action:

    public ActionResult SortDetails(SearchDataTypeModel model, String sortBy)
    {

The model parameter is null. The sortBy parameter is populated. I can pass in a String property from the model to the action with no problem. I want to pass in the entire model though.

Any ideas what I'm doing wrong?


You can't pass complex objects:

new
{
    model = Model,
    sortBy = "EffectiveStartDate",
},

model = Model makes no sense and cannot be sent using GET. You might need to use a form with an editor template and/or hidden fields to send all the model properties. Remember only scalar values can be sent in the query string (key1=value1&key2=value2...). Another alternative that comes to mind is to send only the ID:

new
{
    modelId = Model.Id,
    sortBy = "EffectiveStartDate",
},

and in your controller action fetch the model given this id from your data store:

public ActionResult SortDetails(int modelId, String sortBy)
{
    var model = repository.GetModel(modelId);
    ...
}

Of course this is only true if the user is not supposed to edit the model properties in a form. Depends on your scenario.

And for the sake of completeness let me expose another option: use the Html.Serialize helper from MVC Futures to serialize the entire model into a hidden field which could be passed back to the controller action and deserialized there.


There is another way of passing model or complex objects specifically in ActionLink as RouteValues.

  1. MODEL: Make static Serialize and Deserialize methods in the class like

    public class XYZ
    { 
        // Some Fields
        public string X { get; set; }
        public string Y { get; set; }
        public string X { get; set; }
    
        // This will convert the passed XYZ object to JSON string
        public static string Serialize(XYZ xyz)
        {
            var serializer = new JavaScriptSerializer();
            return serializer.Serialize(xyz);
        }
    
        // This will convert the passed JSON string back to XYZ object
        public static XYZ Deserialize(string data)
        {
            var serializer = new JavaScriptSerializer();
            return serializer.Deserialize<XYZ>(data);
        }
    }
    
  2. VIEW: Now convert your complex object to JSON string before passing it in Action View

    <%= Html.ActionLink(Model.x, "SomeAction", new { modelString = XYZ.Serialize(Model) })%>
    
  3. CONTROLLER: Get the object as string in Action method and convert it back to object before using

    public ActionResult SomeAction(string modelString)
    {
        XYX xyz = XYX.Deserialize(modelString);
    }
    

Thats All...

Note: Techniques discussed in other answers are well enough in case of Model, But some times you need to pass some complex object (other than database model) back to the controller, as I have such specific case.

Hope this will help some...:)


One other option is to persist the data you need in TempData. This will hand it to the next request, and you can retrieve it there. You should be able to persist the entire model object if you want to.

But it's easier (and better practice) to just retrieve it again from the database, as Darin suggests.


You would have to serialize the object. The url would get ugly and risk becoming to long.

This is kind of close to what you was looking for. I use custom parameters that persist only within a controller. Just easy to maintain and they are strong typed. I don't like variable in quotes. If I use these in a form submit then all is good.

<form><%=Html.TextBox("catid.Value") %></form> 

If I use Html.ActionLink then it no worky. Basically the Url has to look something like this ?catid.Value=31f1a21a-9546-4f2f-8c26-a0273d11b233

The work around is pretty simple since I still remember how to manually write an html A tag.

<a href="?catid.Value=<%= cat.ID %>" ><%: cat.Name %></a>

 public ActionResult Index(Core.ControllerPersistence._Guid catid)
        {
            if (catid.Value.HasValue)
            {

Not all but some of the Html helpers are like a pen you would carry in your pocket that automatically signs your name so you don't have to move your wrist. If for some reason the pen one day does not work just grab a normal pen and move your wrist so you can sign your name and move on.


Jeff,

Maybe you could create a View class that has the properties SearchDataTypeModel and sortby and you pass it to the view. When you click the actionlink pass it just the Model.SearchDataTypeModel. HTH


Maybe it is too late. Got some solution. Something similar to this. Here is my example.

Url generating code:

var rv = new RouteValueDictionary();
rv["sortBy"] = currentSortColumn;
rv["ascending"] = currentSortColumn == sortBy ? !ascending : true;
rv["filter.Id"] = // some value
rv["filter.Creator"] = // some value

var url = url.Action( // url is UrlHelper
    actionName,
    controllerName,
    rv);

// as result it will output something like this: 
// http://your_host/yourController/yourAction?sortBy=name&ascending=True&filter.Id=100&filter.Creator=test

Controller code:

public ActionResult YourAction(string sortBy = "name", bool ascending = false, YourFilterModel filter = null)

Filter object class:

public class YourFilterModel 
{
    public string Id { get; set; }
    public string Creator { get; set; }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜