The model is not passed in the post method, which should update objects from changed form input values

My model contains two lists of entity type Order

, but differs only in the value of the property Status

. When Orders

created, the state property is automatically set to In Progress

and at AdminOrders view

, placed in Orders In Progress table

. AdminOrders view

has two tables: Orders In Progress table

and Orders Dispatched table

, which will be filled with lists accordingly Model

.

When the value of Status

new orders changes from the dropdown to dispatched

, and when the button is clicked update

in the view, a submit request should be triggered - passing the model to it. However, when I debug the post method AdminOrders

, the model parameter is null.

Here's the Model class:

public class AdminOrdersViewModel
{
    public List<Order> OrdersInProgress { get; set; }
    public List<Order> OrdersDespatched { get; set; }
}

      

These are the controller actions:

[HttpGet]
[Authorize(Roles = "Admin")]
public ActionResult AdminOrders()
{
    var model = db.Orders.Where(o => o.Status == "In Progress").ToList();
    var model2 = db.Orders.Where(o => o.Status == "Despatched").ToList();

    return View(new AdminOrdersViewModel { OrdersInProgress = model, OrdersDespatched = model2 });
}

[HttpPost]
[Authorize(Roles = "Admin")]
public async Task<ActionResult> AdminOrders([Bind(Include = "OrdersInProgress, OrdersDespatched")] AdminOrdersViewModel model)
{
    if (ModelState.IsValid)
    {
        foreach (var item in model.OrdersDespatched)
        {
            db.Entry(item).State = EntityState.Modified;
        }

        foreach (var item2 in model.OrdersInProgress)
        {
            db.Entry(item2).State = EntityState.Modified;
        }

        await db.SaveChangesAsync();

        var ordersInProgress = db.Orders.Where(o => o.Status == "In Progress").ToList();
        var ordersDespatched = db.Orders.Where(o => o.Status == "Despatched").ToList();

        return View(new AdminOrdersViewModel { OrdersDespatched = ordersDespatched, OrdersInProgress = ordersInProgress });
    }

    return View(model);
}

      

In the Get

request AdminOrders

method of the method, AdminOrders

each model list object is updated and a new model is provided to the View when the view is returned, so the page has to be refreshed and Orders are moved to the correct table based on the status. However, the model remains empty.

The form in the view assigns the View Model to the Post model parameter:

@using (Html.BeginForm("AdminOrders", "Manage", new { model = Model }, FormMethod.Post, new
    {
        enctype = "multipart/form-data"
    }))
    {
   }

      

I also tried to pass two new lists in the Post method with model lists that are individually assigned in the form request but accept errors. How do I ensure that the Post request passes the updated model to the post method AdminOrders

?

The full view page code looks like this:

@model ValueVille.Models.AdminOrdersViewModel

@{
    ViewBag.Title = "Orders";

}

<div class="main-content-container">

    <h1>New Orders In Progress</h1>
@using (Html.BeginForm("AdminOrders", "Manage", new { model = Model }, FormMethod.Post, new
{
    enctype = "multipart/form-data"
}))
{
        @Html.AntiForgeryToken()

        <table class="panel panel-default table cart-table">
            <tr>
                <th>
                    Order ID
                </th>
                <th>
                    Total
                </th>
                <th>
                    Date
                </th>
                <th>
                    Status
                </th>
            </tr>
            @foreach (var item in Model.OrdersInProgress)
            {
                <tr>
                    <td>
                        <a href="@Url.Action("OrderDetails", "Home", new { id = item.OrderId })">
                            @item.OrderId
                        </a>
                    </td>
                    <td>
                        £@item.Total
                    </td>
                    <td>
                        @item.OrderDate
                    </td>
                    <td>
                        @{
                            List<SelectListItem> listItems = new List<SelectListItem>();
                            listItems.Add(new SelectListItem
                            {
                                Text = item.Status,
                                Value = "Option1"
                            });
                            listItems.Add(new SelectListItem
                            {
                                Text = "Despatched",
                                Value = "Option2",

                            });

                        }

                        @Html.DropDownListFor(m => item.Status, listItems, item.Status)
                    </td>
                </tr>
                            }

        </table>

        <h1>Orders Despatched</h1>

        <table class="panel panel-default table cart-table">
            <tr>
                <th>
                    Order ID
                </th>
                <th>
                    Total
                </th>
                <th>
                    Date
                </th>
                <th>
                    Status
                </th>
            </tr>
            @foreach (var item in Model.OrdersDespatched)
            {
                <tr>
                    <td>
                        <a href="@Url.Action("OrderDetails", "Home", new { id = item.OrderId })">
                            @item.OrderId
                        </a>
                    </td>
                    <td>
                        £@item.Total
                    </td>
                    <td>
                        @item.OrderDate
                    </td>
                    <td>
                        @{
                            List<SelectListItem> listItems = new List<SelectListItem>();
                            listItems.Add(new SelectListItem
                            {
                                Text = item.Status,
                                Value = "Option1"
                            });
                            listItems.Add(new SelectListItem
                            {
                                Text = "Despatched",
                                Value = "Option2",

                            });

                        }

                        @Html.DropDownListFor(m => item.Status, listItems)
                    </td>
                </tr>
                            }

        </table>

        <div class="panel-body form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Update" class="btn btn-success" />
            </div>
        </div>

                            }



</div>

      

+3


source to share


2 answers


Change ViewModel to:

public class AdminOrdersViewModel
{
    public List<Order> OrdersInProgress { get; set; }
    public List<Order> OrdersDespatched { get; set; }
    public List<Status> OrderStatuses { get; set; }
}

      

Your opinion should now look like this:

@model ValueVille.Models.AdminOrdersViewModel
@{
    ViewBag.Title = "Orders";
}

<div class="main-content-container">
    <h1>New Orders In Progress</h1>
    @using (Html.BeginForm("AdminOrders", "Manage", FormMethod.Post, new { enctype = "multipart/form-data" }))
    {
        @Html.AntiForgeryToken()

        <table class="panel panel-default table cart-table">
            <thead>
                <tr>
                    <th>Order ID</th>
                    <th>Total</th>
                    <th>Date</th>
                    <th>Status</th>
                </tr>
            </thead>
            <tbody>
                @for (int i = 0; i < Model.OrdersInProgress.Count(); i++)
                {
                    <tr>
                        <td>
                            <a href="@Url.Action("OrderDetails", "Home", new { id = Model.OrdersInProgress[i].OrderId })">@Model.OrdersInProgress[i].OrderId</a>
                            @Html.HiddenFor(x => x.Model.OrdersInProgress[i].OrderId)
                        </td>
                        <td>
                            £@Model.OrdersInProgress[i].Total
                            @Html.HiddenFor(x => x.Model.OrdersInProgress[i].Total)
                        </td>
                        <td>
                            @Model.OrdersInProgress[i].OrderDate
                            @Html.HiddenFor(x => x.Model.OrdersInProgress[i].OrderDate)
                        </td>
                        <td>
                            @Html.DropDownListFor(m => Model.OrdersInProgress[i].Status, new SelectList(Model.OrderStatuses, "Id", "StatusName"))
                        </td>
                    </tr>
                }
            </tbody>
        </table>

        <h1>Orders Despatched</h1>
        <table class="panel panel-default table cart-table">
            <thead>
                <tr>
                    <th>Order ID</th>
                    <th>Total</th>
                    <th>Date</th>
                    <th>Status</th>
                </tr>
            </thead>
            <tbody>
                @for (int i = 0; i < Model.OrdersDespatched.Count(); i++)
                {
                    <tr>
                        <td>
                            <a href="@Url.Action("OrderDetails", "Home", new { id = Model.OrdersDespatched[i].OrderId })">@Model.OrdersDespatched[i].OrderId</a>
                            @Html.HiddenFor(x => x.Model.OrdersDespatched[i].OrderId)
                        </td>
                        <td>
                            £@Model.OrdersDespatched[i].Total
                            @Html.HiddenFor(x => x.Model.OrdersDespatched[i].Total)
                        </td>
                        <td>
                            @Model.OrdersDespatched[i].OrderDate
                            @Html.HiddenFor(x => x.Model.OrdersDespatched[i].OrderDate)
                        </td>
                        <td>
                            @Html.DropDownListFor(m => Model.OrdersDespatched[i].Status, new SelectList(Model.OrderStatuses, "Id", "StatusName"))
                        </td>
                    </tr>
                }
            </tbody>
        </table>

        <div class="panel-body form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Update" class="btn btn-success" />
            </div>
        </div>
    }
</div>

      

The controller method should look like this:

[HttpPost]
public async Task<ActionResult> AdminOrders(AdminOrdersViewModel model)
{
    // do stuff
}

      



Assuming your model Status

looks something like this:

public class Status
{
    public int Id { get; set; }
    public string StatusName { get; set; }
}

      

You can create a dropdown from the list:

@Html.DropDownListFor(m => Model.OrdersDespatched[i].Status, new SelectList(Model.OrderStatuses, "Id", "StatusName"))

      

PS: Also make sure you assign the list of statuses in the Get method.

+1


source


Okay, I see what you are doing ...

For some reason in asp.net MVC it ​​seems like this should work:

@using (Html.BeginForm("AdminOrders", "Manage", new { model = Model }, FormMethod.Post, new
{
    enctype = "multipart/form-data"
}))
{
//Form contents
}

      

Am I passing the model right? Well, I guess not, because it doesn't work.



What you need to do is something like this (add two hidden fields to the form):

@using (Html.BeginForm("AdminOrders", "Manage", new { model = Model }, FormMethod.Post, new
{
    enctype = "multipart/form-data"
}))
{
    @Html.HiddenFor(x => x.OrdersInProgress)
    @Html.HiddenFor(x => x.OrdersDespatched)
}

      

And then configure it to take two lists in controller action.

I had this problem while trying to pass complex objects (pocos or whatever) to a controller and found that you must include the objects exactly as they are named and they must match the expectations of the controller. So if you have a List<Order>

called OrdersInProgress

, then you have to pass a list of that type with that exact name to a controller that accepts a list of that type with that exact name. Hidden for control inside the form must pass this list with this name. If this list is empty, check the name is correct.

-1


source







All Articles