NPadrutt
NPadrutt

Reputation: 4257

asp.net MVC parameter not passed

In my controller I do have this endpoint:

async Task<FileResult> DownloadSelection(AssignedDatabaseSelection selection)

And my HTML looks like:

@if (Model.AssignedDatabaseSelections.Any())
{
    <table>
        @foreach (var selection in Model.AssignedDatabaseSelections)
        {
            <tr>
                <td>@selection.DisplayName</td>
                <td width="10%">
                    @Html.ActionLink(Strings.CsvLabel, "DownloadSelection", "Home", selection, null)
                </td>
            </tr>
        }
    </table>
}

Now I wanted to add another parameter to my controller method:

async Task<FileResult> DownloadSelection(AssignedDatabaseSelection selection, DownloadFormat format)

And

@if (Model.AssignedDatabaseSelections.Any())
{
    <table>
        @foreach (var selection in Model.AssignedDatabaseSelections)
        {
            <tr>
                <td>@selection.DisplayName</td>
                <td width="10%">
                    @Html.ActionLink(Strings.CsvLabel, "DownloadSelection", "Home", new {selection = selection, Format = DownloadFormat.CSV}, null)
                </td>
                <td width="10%">
                    @Html.ActionLink(Strings.ExcelLabel, "DownloadSelection", "Home", new  { selection = selection, Format = DownloadFormat.CSV }, null)
                </td>
            </tr>
        }
    </table>
}

When I make an inspect elements I got this:

<a href="/Home/DownloadSelection?selection=System.Data.Entity.DynamicProxies.AssignedDatabaseSele_D02B1D7B1220921CC4150FAA016EB8BFD5692B52C49949B0ECB80AA2F98E7355&amp;Format=CSV">Excel</a>

Now, the format is filled, but the selection is always null. What am I missing?

Upvotes: 0

Views: 327

Answers (2)

user3559349
user3559349

Reputation:

In you first example, the 3rd parameter is a complex object (typeof AssignedDatabaseSelections) and the method will correctly serialize each property of your object to a query string. Note that it only works because your object contains only simple properties.

In the second example, your creating a new object containing a complex object. The ActionLink() method (and all methods that generate route/query string values) call the .ToString() method on each property in the object (hence you get the name of the class) and do not do recursion.

If you want to pass back all properties of the AssignedDatabaseSelections object plus another property, you need to generate a new object containing each property of AssignedDatabaseSelections, for example (assuming it contains properties ID and Name)

@Html.ActionLink(Strings.CsvLabel, "DownloadSelection", "Home",
    new { ID = selection.ID, Name = selection.Name, ......, Format = DownloadFormat.CSV }, null)

Note that if AssignedDatabaseSelections contains a lot of properties and/or larger values, you risk exceeding the query string limit and throwing an exception. A better approach is just to pass the ID property of the AssignedDatabaseSelection and get the object again in the GET method if you need other properties of it.

@Html.ActionLink(Strings.CsvLabel, "DownloadSelection", "Home",
    new { ID = selection.ID, Format = DownloadFormat.CSV }, null)

Upvotes: 1

CodingYoshi
CodingYoshi

Reputation: 26989

Here is an example of how to create a link with properties from an object. I am including the code of creating a new Employee within the view but this can/should be in the model:

@{ var emp = new Employee { Name = "Tom", Age = 44 }; }
@Html.ActionLink("Test", "Test2", "Account", new {Name = emp.Name, Age = emp.Age }, null)

Please note how I am passing each property of the Employee into the anonymous object for the route values.

The above link will work with this action. The DefaultModeBinder will take the names from the query string in the link and assign it to the properties of the Employee and pass it to the action below:

public ActionResult Test2(Employee emp)
{
    return null;
}

Upvotes: 1

Related Questions