1

I have an ASP.NET MVC program with an order/odc request form. I have a customer, order and order item model. What I want to do is allow the user to place an order for a list of items to be approved. I have the viewmodel being passed to the form/view with a few fields including a list of order item objects. I am able to dynamically add rows to the table which shows the list of order items but on submit there is nothing in the viewmodel list. What am I doing wrong? How do I pass the items entered into the table to the view so that I can submit to the database?

Controller

    public ActionResult NewOdc()
    {
        var viewModel = new NewOdcViewModel()
        {
            OdcItems = new List<tblOdcItem>() 
        };

        viewModel.OdcItems.Add(new tblOdcItem());

        return View(viewModel);
    }

I call this code from jQuery to add a new item to the list:

    public ActionResult GetView(string rowCount)
    {
        tblOdcItem item = new tblOdcItem();
        return PartialView("_OdcItemEditor", item);
    }

And on submit I call this code:

    [HttpPost]
    public ActionResult NewOdcSubmit(NewOdcViewModel viewModel)
    {
        _context.tblOdcs.Add(new tblOdc());
        ...

I'm using a foreach to go through the list and create a partial for each item.

View:

@using (Html.BeginForm("NewOdcSubmit", "Odc", FormMethod.Post))
{
            if (Model != null)
            {
                @Html.HiddenFor(m => m.OdcItems);
            }

            <div class="panel panel-info">
                <div class="panel-heading">
                    <h2 class="panel-title">Enter New ODC</h2>
                </div>
                <div class="panel-body">
                    @Html.AntiForgeryToken()
                    <div class="form-group">
                        @Html.LabelFor(model => model.User.UserName, new { @class = "col-md-2 col-sm-1 control-label" })
                        <div class="col-md-2 col-sm-3">
                            @Html.TextBoxFor(model => model.User.UserName, new { @Value = ((PM_Portal2020.Models.tblUser)Session["User"]).UserName, @readonly = true })
                        </div>
                        @Html.LabelFor(model => model.User.Phone, new { @class = "col-md-2 col-sm-1 control-label" })
                        <div class="col-md-2 col-sm-3">
                            @Html.TextBoxFor(model => model.User.Phone, new { @Value = ((PM_Portal2020.Models.tblUser)Session["User"]).Phone })
                        </div>
                    </div>
                    <div class="form-group col-md-10 col-sm-12">
                        <label>Expenses</label>
                        <table id="submissionTable" class="table table-bordered">
                            <thead>
                                <tr>
                                    <th>Qty</th>
                                    <th>Description</th>
                                    <th>Estimated Cost</th>
                                </tr>
                            </thead>
                            <tbody>
                                @foreach (PM_Portal2020.Models.tblOdcItem item in Model.OdcItems)
                                {
                                    @Html.Partial("_OdcItemEditor", item)
                                }
                            </tbody>
                        </table>
                        <p>
                            <button id="add" type="button" class="btn btn-primary">Add</button>
                        </p>
                    </div>
                    <div class="form-group col-lg-10 col-sm-12">
                        @Html.LabelFor(model => model.Details, new { @class = "col-md-2 col-sm-1 control-label" })
                        <div class="">
                            @Html.TextAreaFor(model => model.Details, new { @class = "form-control" })
                        </div>
                    </div>
                </div>
                <div class="panel-footer">
                    <div class="">
                        <button type="submit" class="btn btn-success">Save</button>&nbsp;&nbsp;
                        @Html.ActionLink("Back", "Index")
                    </div>
                </div>
            </div>
}

PartialView in Shared folder:

@model PM_Portal2020.Models.tblOdcItem

<tr @Html.Id("tablerow" + Model.ID)>
    <td>
        <div class="editor-field">
            @Html.TextBoxFor(model => model.Quantity, new { @class = "text-box single-line", name = "Quantity[" + Model.ID + "]", type = "text", value = "", required = "required" })
        </div>
    </td>
    <td>
        <div class="editor-field">
            @Html.TextBoxFor(model => model.Description, new { @class = "text-box single-line", name = "Description[" + Model.ID + "]", type = "text", value = "", required = "required", id = "itemDesc" })
        </div>
    </td>
    <td>
        <div class="editor-field">
            @Html.TextBoxFor(model => model.EstimatedCost, new { @class = "text-box single-line", name = "EstimatedCost[" + Model.ID + "]", type = "text", value = "", required = "required" })
        </div>
    </td>
    <td>
        <button type="button" class="btn btn-primary" onclick="removeTr(this);">
            <span class="glyphicon glyphicon-trash"></span>
        </button>
    </td>
</tr>

View Model

public class NewOdcViewModel
{
    public NewOdcViewModel()
    {
    }

    public IList<tblOdcItem> OdcItems { get; set; }
    public string Details { get; set; }
    public int OdcId { get; set; }
    public tblUser User { get; set; }
}

It submits to the controller but the odcitems list is always count = 0. Any help would be great. Thanks

2 Answers 2

1

Here is the javascript example, just use this function on add/delete operation to re-arrange name.

function RearangeName(){
        var i = 0;
        $("#submissionTable>tbody>tr").each(function () {
            $(this).find("input").each(function () {
                if ($(this).prop("name").indexOf('Quantity') > 0) {
                    $(this).attr('name', "OdcItems[" + i + "].Quantity");
                }
                if ($(this).prop("name").indexOf('Description') > 0) {
                    $(this).attr('name', "OdcItems[" + i + "].Description");
                }
                if ($(this).prop("name").indexOf('EstimatedCost') > 0) {
                    $(this).attr('name', "OdcItems[" + i + "].EstimatedCost");
                }
            });
            i++;
        });
    }
Sign up to request clarification or add additional context in comments.

Comments

0

the name should be matched with model property, so in partial view, you have set name as OdcItems[0].Quantity instead of Quantity[" + Model.ID + "].

@Html.TextBoxFor(model => model.Quantity, new { @class = "text-box single-line", name = "OdcItems[0].Quantity", type = "text", value = "", required = "required" })

eg. OdcItems[0].Quantity

OdcItems[1].Quantity

OdcItems[2].Quantity

....

OdcItems[n].Quantity

4 Comments

I'm adding items dynamically though. I can't hard code the number of items in because it could be different for every order
There is two ways, 1. Replace name with javascript. 2. Post row number and use it in partial view.
I can't get that to work. where do I post the number? To the Controller? Is the name of the field that important? thanks
Yes, the name field is important for the form submission.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.