Colm Prunty
Colm Prunty

Reputation: 1620

Post subset of the Model to the Controller from Razor view

I have a Razor view that looks like this:

@model Namespace.Namespace.SupplierInvoiceMatchingVm

@using(Html.BeginForm("MatchLines", "PaymentTransaction"))
{
    <table class="dataTable" style="width: 95%; margin: 0px auto;">
    <tr>
        <th></th>
        <th>PO Line</th> 
        <th>Description</th> 
    </tr>
    @for (var i = 0; i < Model.Lines.Count; i++)
    {
        <tr>
            <td>@Html.CheckBoxFor(x => x.Lines[i].Selected)</td>
            <td>@Html.DisplayFor(x =>x.Lines[i].LineRef) @Html.HiddenFor(x => x.Lines[i].LineRef)</td>
            <td>@Html.DisplayFor(x =>x.Lines[i].Description) @Html.HiddenFor(x => x.Lines[i].Description)</td>
        </tr>
    }

    </table>
    <input type="submit" value="Submit"/>
}

Where Lines is a list of SupplierInvoiceMatchingDto objects, and the MatchLines method signature looks like

public ActionResult MatchLines(IEnumerable<SupplierInvoiceMatchingDto> list)

When I hit the submit button on this view, the list comes through to the controller as null.

However, if I change the Model to be List<SupplierInvoiceMatchingDto>, and all the table rows to be x => x[i].Whatever instead, it posts all the information fine.

My question is: How do I get it to post the list to the controller while keeping the model as SupplierInvoiceMatchingVm as I need some other stuff from the model in this view (that I've taken out for brevity's sake).

Note: there are a few user input fields that I've taken out, it's not just posting the same data that it gets given.

Upvotes: 1

Views: 627

Answers (2)

Belogix
Belogix

Reputation: 8147

Your Post action is not taking in the model correctly (should be your ViewModel)? Shouldn't it be:

[HttpPost]
public ActionResult MatchLines(SupplierInvoiceMatchingVm viewModel)
{
    var list = viewModel.Lines;
    // ...
}

Upvotes: 1

Darin Dimitrov
Darin Dimitrov

Reputation: 1038930

You could use the [Bind] attribute and specify a prefix:

[HttpPost]
public ActionResult MatchLines([Bind(Prefix="Lines")] IEnumerable<SupplierInvoiceMatchingDto> list)
{
    ...
}

or even better use a view model:

public class MatchLinesViewModel
{
    public List<SupplierInvoiceMatchingDto> Lines { get; set; }
}

and then have your POST controller action take this view model:

[HttpPost]
public ActionResult MatchLines(MatchLinesViewModel model)
{
    ... model.Lines will obviously contain the required information
}

Upvotes: 2

Related Questions