MVC5 ViewModel Not Posting back to Controller
Asked Answered
R

1

5

So, I have an issue with a controller/view/viewmodel. It's similar to this issue I think. Basically, I have a viewmodel that I send to a view from my controller. There are items that display and then some additional fields for the user to manipulate before the whole mess is sent back over to a controller post action. When I get the data back in my post, all of the viewmodel is empty.

So, without further ado, here's some code to look at:

ViewModel:

public class ASideReceivingViewModel
{
    public PurchaseOrderLine poLine;
    public ReceivingItem receivingItem;

    public Dictionary<string, string> TankerOrRailcarOptions { get; set; }

    public ASideReceivingViewModel()
    {
        TankerOrRailcarOptions = new Dictionary<string, string>();
        TankerOrRailcarOptions.Add("R", "Railcar");
        TankerOrRailcarOptions.Add("T", "Tanker");

    }

}

Controller Actions:

public ActionResult Receive(string strOrdNo, short? shtLineNo)
{

    //if there isn't a selected po line, then shoot them back to the first page
    if (strOrdNo == null || !shtLineNo.HasValue) return RedirectToAction("Index");

    PurchaseOrderService poService = new PurchaseOrderService();
    ReceivingItemService s = new ReceivingItemService(p);

    ASideReceivingViewModel vm = new ASideReceivingViewModel();


    vm.poLine = poService.GetOpenPurchaseOrderLines().Where(po => po.Ord_no == strOrdNo &&
        po.Line_no == shtLineNo).FirstOrDefault();

    if (vm.poLine == null) return RedirectToAction("Index");

    vm.receivingItem = s.CreateNewReceivingItem(vm.poLine);

    return View(vm);

}

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Receive(ASideReceivingViewModel mytestvm)
{
    if (ModelState.IsValid && mytestvm.receivingItem != null)
    {
        ReceivingItemService s = new ReceivingItemService(p);
        s.Update(mytestvm.receivingItem);
        return RedirectToAction("Index");

    }

    return View(mytestvm);
}

View:

@model FSIApps.Presentation.Models.ASideReceivingViewModel
<div class="row">
    @{Html.RenderPartial("POLineDetails", Model.poLine);}
</div>

@using (Html.BeginForm("Receive", "Receiving", FormMethod.Post))
{
@Html.HiddenFor(model => model.receivingItem.Id)
<div class="row">
    <div class="col-md-8 col-md-offset-2">
        <div class="row">
            @Html.AntiForgeryToken()
            <div class="col-md-6">
                <div class="form-group">
                    <label for="receivingItem_Batch_number">Batch Number</label>
                    @Html.TextBoxFor(model => model.receivingItem.Batch_number, new { @class = "form-control" })
                    <span class="help-block">*Also the Vendor Lot Number on the BOL</span>
                </div>
            </div>

            <div class="col-md-6">
                <div class="form-group">
                    <label for="receivingItem_Qty_received">Qty Received</label>
                    @Html.TextBoxFor(model => model.receivingItem.Qty_received, new { @class = "form-control" })
                    <span class="help-block">*Qty shown on BOL</span>
                </div>
            </div>
        </div>
        <div class="row">
            <div class="col-md-6">
                <div class="form-group">
                    <label for="receivingItem_Carrier">Carrier</label>
                    @Html.TextBoxFor(model => model.receivingItem.Carrier, new { @class = "form-control" })
                </div>
            </div>
            <div class="col-md-6">
                <div class="form-group">
                    <label for="receivingItem_">Tanker or Railcar</label>
                    @Html.DropDownListFor(m => m.receivingItem.Tanker_or_railcar, new SelectList(Model.TankerOrRailcarOptions, "Key", "Value", Model.receivingItem.Tanker_or_railcar), new { @class = "form-control" })
                </div>
            </div>
        </div>
        <div class="row">
            <div class="col-md-6">
                <div class="form-group">
                    <label for="receivingItem_Railcar_number">Railcar Number</label>
                    @Html.TextBoxFor(model => model.receivingItem.Railcar_number, new { @class = "form-control" })
                </div>
            </div>
            <div class="col-md-6">
                <div class="form-group">
                    <label for="receivingItem_Manifest_number">Manifest Number</label>
                    @Html.TextBoxFor(model => model.receivingItem.Manifest_number, new { @class = "form-control" })
                </div>
            </div>
        </div>

        <div class="row">
            <div class="col-md-6">
                <div class="form-group">
                    <input type="submit" value="Save" class="btn btn-success" />
                </div>
            </div>
        </div>
    </div>
</div>
}

I don't necessarily care about the data I send to the partial view, but when I post back the regular form I get nothing set in the ViewModel. In the other post they talk about how that's an issue with naming the parameter sent back to the controller, but no combination of setting the value in my @Html.BeginForm() seems to do the trick.

Anyone have any advice for me here?

Edited:

Visual Studio Break

Fiddler Data

Rembrandt answered 6/12, 2013 at 15:5 Comment(0)
D
9

To use the automatic model binding, you should use properties instead of fields in the view model. Hopefully this does the trick:

public class ASideReceivingViewModel
{
    public PurchaseOrderLine poLine { get; set; };
    public ReceivingItem receivingItem { get; set; };
    ...
}
Dubitable answered 6/12, 2013 at 23:10 Comment(3)
That was totally it! Thanks!Rembrandt
Been looking for this for about 7 hours... Only came up when I started asking my own question :(Pandich
Perfect answer! I wish I could have found it about 3 hours earlier ;-) Thanks!Amir

© 2022 - 2024 — McMap. All rights reserved.