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.
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); } }
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) })%>
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; }
}
精彩评论