ASP.NET MVC - Trouble passing model in Html.Action

2020-02-05 03:14发布

My View looks like this:

<%@ Control Language="C#" 
    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?

6条回答
地球回转人心会变
2楼-- · 2020-02-05 03:37

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.

查看更多
放我归山
3楼-- · 2020-02-05 03:41

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.

查看更多
冷血范
4楼-- · 2020-02-05 03:41

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...:)

查看更多
Viruses.
5楼-- · 2020-02-05 03:44

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.

查看更多
够拽才男人
6楼-- · 2020-02-05 03:54

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

查看更多
爷的心禁止访问
7楼-- · 2020-02-05 03:55

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; }
}
查看更多
登录 后发表回答