简体   繁体   English

模型没有在post方法中传递,后者应该从更改的表单输入值更新实体

[英]Model not being passed in post method which should update entities from changed form input values

My model contains two lists of the Order entity type, but differentiating only by the value of the Status property. 我的模型包含两个Order实体类型列表,但仅区分Status属性的值。 When Orders are created, the status property is automatically set to In Progress and in the AdminOrders view , placed in the Orders In Progress table . 创建Orders ,status属性将自动设置为In Progress并在AdminOrders view ,放置在Orders In Progress table The AdminOrders view has two tables: Orders In Progress table and Orders Dispatched table which will be filled by the Model 's lists respectively. AdminOrders view有两个表: Orders In Progress tableOrders Dispatched table ,它们将分别由Model列表填充。

When the Status value of new orders is changed from the drop down list to dispatched , and when the update button in the view is clicked, the post request should be triggered - passing the model to it. 当新订单的Status值从下拉列表更改为已dispatched ,并且单击视图中的update按钮时,应触发帖子请求 - 将模型传递给它。 However when I debug the AdminOrders post method, the model parameter is null. 但是,当我调试AdminOrders post方法时,model参数为null。

Here's the Model class: 这是Model类:

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, each Model list's entity is updated and a new Model is given to the View when the View is returned, so the page should update and Orders moved to the correct table depending on the status property. Get request AdminOrders方法中,每个Model列表的实体都会更新,并且在返回View时会向View提供一个新Model,因此页面应该更新,Orders会根据status属性移动到正确的表。 However the model is left null. 但是模型保留为null。

The form in the View assigns the View's Model to the Post method model parameter: 视图中的表单将View的模型分配给Post方法模型参数:

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

I have also tried to pass in two new lists in the Post method with the Model's lists individually assigned in the form request, but receive errors. 我还试图在Post方法中传入两个新列表,并在表单请求中单独分配模型列表,但是接收错误。 How do I ensure the Post request passes the updated model to the AdminOrders post method? 如何确保Post请求将更新的模型传递给AdminOrders post方法?

The full View Page code is the following: 完整的View页面代码如下:

@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>

Modify your ViewModel to: 将ViewModel修改为:

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

Your view should look now like: 你的观点现在看起来像:

@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: 控制器方法应如下所示:

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

Assuming your Status model is somethig like: 假设您的Status模型类似于:

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

You can create the dropdownlist from your above list: 您可以从上面的列表中创建下拉列表:

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

PS: Also make sure your assign a list of statuses in the Get method. PS:还要确保在Get方法中指定状态列表。

Okay, I see what you're doing... 好的,我看到你在做什么......

For some reason, in asp.net MVC is seems like this should work: 出于某种原因,在asp.net中,MVC似乎应该可行:

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

I'm passing the model right? 我正在通过模型吗? Well, I guess not, because it doesn't work. 好吧,我猜不是,因为它不起作用。

What you have 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 set it up to take the two lists in the controller action. 然后将其设置为在控制器操作中获取两个列表。

I've had this issue when trying to pass complex objects (pocos or whatever) to the controller and found that you have to include the objects exactly as they are named and it must match what the controller expects. 尝试将复杂对象(pocos或其他)传递给控制器​​时,我遇到了这个问题,发现必须完全按照命名包含对象,并且必须与控制器所期望的完全匹配。 So if you have a List<Order> called OrdersInProgress then you have to pass a list of that type with that exact name to the controller that accepts a list of that type with that exact name. 因此,如果您有一个名为OrdersInProgressList<Order>那么您必须将具有该确切名称的该类型的列表传递给控制器​​,该控制器接受具有该确切名称的该类型的列表。 The hidden for control inside the form should pass that list with that name. 表单内隐藏的控件应该使用该名称传递该列表。 If that list turns up empty check that it's name is correct. 如果该列表变为空,请检查其名称是否正确。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM