在IEnumerable视图中编辑数据(订单行的项目)

时间:2014-04-09 18:10:38

标签: c# entity-framework razor ienumerable

我的模特:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace SNW.Models.CustomerOrderInfo
{
    public class MemberOrder : CustomerOrder
    {
        public new int customerOrderID { get; set; }
        [..]
        public int customerOrderLineID { get; set; }
        public int productID { get; set; }
        [..]
        public double customerOrderQtyMin { get; set; }
        public double customerOrderQtyMax { get; set; }
        [..]
    }
}

我的控制器:

[..]
using SNW.Models;
using SNW.Models.CustomerOrderInfo;

namespace SNW.Controllers
{
    public class CustomerOrderController : Controller
    {
        private DBModelContainer db = new DBModelContainer();
        [HttpPost, ActionName("SaveChanges")]
        public ActionResult SaveChanges([Bind(Include = "customerOrderQtyMax")] SNW.Models.CustomerOrderInfo.MemberOrder line)
        {
            if(ModelState.IsValid)
            {
                    db.Entry(line).State = EntityState.Modified;
                    db.SaveChanges();
                    return RedirectToAction("CustomerOrder");
            }
            return View(line);
        }
    }
}

我的观点 CustomerOrder.cshtml ):

@model IEnumerable<SNW.Models.CustomerOrderInfo.MemberOrder>
[..]
    @foreach (var MemberOrder in Model)
    {
    <tr>
        <td>@MemberOrder.productID</td>
        <td>@MemberOrder.productName</td>
        [..]
        <td>@Html.EditorFor(model => MemberOrder.customerOrderQtyMin)</td>
        <td>
            @using (Html.BeginForm("SaveChanges", "CustomerOrder", new { id = MemberOrder.customerOrderLineID }))
            {
                @Html.ValidationSummary(true)
                @Html.HiddenFor(model => MemberOrder.customerOrderLineID)
                @Html.EditorFor(model => MemberOrder.customerOrderQtyMax)
                @Html.ValidationMessageFor(model => MemberOrder.customerOrderQtyMax)
                <input type="submit" value="+" class="btn btn-default" />
            }
        </td>
    [..]
    </tr>

呈现视图

问题:

每当我更改订单行的最大值并点击&#34; +&#34;要在数据库中更新它,它不起作用。

line方法中的SaveChanges()值为0或null,包括customerOrderQtyMax值为0.0,但数据库更新也不会发生 - 以前的值正在再次显示。

所以我的问题是,如何从这个IEnumerable视图中仅将customerOrderQtyMax输入值传递给DB?我想要&#39;能够在 CustomerOrder.cshtml 页面中修改订单(或购物车,如果您愿意)。

到目前为止我尝试了什么:

  1. Updating Related Data with the Entity Framework in an ASP.NET MVC Application

  2. Various tutorials on Youtube

  3. SaveChanges()方法与数据库模型为EF Edit()实体生成的CustomerOrderLines方法进行比较。后者没有使用IEnumerables&lt;&gt;并且它拥有自己的视图( Edit.cshtml )。

  4. 在我的视图中添加了额外的HiddenFor()字段作为我的订单行&#39;主键由customerOrderLineIDcustomerOrderID属性组成。

  5. @using (Html.BeginForm("SaveChanges", "CustomerOrder", new { id = MemberOrder.customerOrderLineID })) { @Html.ValidationSummary(true) @Html.HiddenFor(model => MemberOrder.customerOrderLineID) @Html.HiddenFor(model => MemberOrder.customerOrderID) @Html.EditorFor(model => MemberOrder.customerOrderQtyMax) @Html.ValidationMessageFor(model => MemberOrder.customerOrderQtyMax) <input type="submit" value="+" class="btn btn-default" /> }

    谢谢你的帮助,伙计们!

    编辑:

    我已经在<input type="submit" value="+" class="btn btn-default" />方法中更改了代码很多次,但这是我收到的错误:

    1. SaveChanges()中的SNW.Models.CustomerOrderInfo.MemberOrder的引用给我以下错误: {&#34;实体类型MemberOrder不是当前上下文模型的一部分。&#34;} 可能是因为它是我自定义的模型继承自{{1}模型,因为
      • public ActionResult SaveChanges([Bind(Include = "customerOrderQtyMax")] SNW.Models.CustomerOrderInfo.MemberOrder line)可以被EF模型生成器
      • 覆盖
      • 我需要使用额外的自定义属性进行计算
    2. CustomerOrder更改为原始CustomerOrder并收到以下错误: {&#34;存储更新,插入或删除语句影响了意外的行数(0)。自实体加载后,实体可能已被修改或删除。刷新ObjectStateManager条目。&#34;}
      • SNW.Models.CustomerOrderInfo.MemberOrder由EF模型生成器生成,我希望其属性与CustomerOrderLine合并,以便能够在一个窗口中编辑Order的信息,而不是每个单独的编辑视图行(订单行)。这就是我制作自定义CustomerOrderLine模型的原因。
      • 现在CustomerOrderSNW.Models.CustomerOrderInfo.MemberOrder
    3. @Jasen。 HTTP POST标头谢谢。
    4. Request URL:http://localhost:64778/CustomerOrder/SaveChanges/8
      Request Method:POST
      Status Code:500 Internal Server Error
      Request Headersview parsed
      POST /CustomerOrder/SaveChanges/8 HTTP/1.1
      Host: localhost:64778
      Connection: keep-alive
      Content-Length: 68
      Cache-Control: max-age=0
      Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
      Origin: http://localhost:64778
      User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.154 Safari/537.36
      Content-Type: application/x-www-form-urlencoded
      Referer: http://localhost:64778/CustomerOrder/CustomerOrder
      Accept-Encoding: gzip,deflate,sdch
      Accept-Language: en-GB,en;q=0.8,lt;q=0.6
      Cookie: .ASPXFORMSAUTH=F44D36B23D1EA17ABB24DEEC4AFA7B09FD2D7B3EEB8D9C57D95561E9A9B334F4BA90F46AEAC2E2DE23958998B3F888342E507B92484C45D990CD0FD08D38F8D8D994CC8F5C231A0144DE4A7B89A286A1AFFEE765C86C856E71403FF94FDF873E
      Form Dataview parsed
      MemberOrder.customerOrderLineID=8&MemberOrder.customerOrderQtyMax=78
      Response Headersview parsed
      HTTP/1.1 500 Internal Server Error
      Cache-Control: private
      Content-Type: text/html; charset=utf-8
      Server: Microsoft-IIS/8.0
      X-AspNet-Version: 4.0.30319
      X-SourceFiles: =?UTF-8?B?QzpcVXNlcnNcRG9uYXRhc1xTb3VyY2VcUmVwb3NcU291bmRzTmljZVdob2xlZm9vZHNcU05XXFNOV1xDdXN0b21lck9yZGVyXFNhdmVDaGFuZ2VzXDg=?=
      X-Powered-By: ASP.NET
      Date: Wed, 09 Apr 2014 21:03:23 GMT
      Content-Length: 17180
      

      HTML表格:

      SaveChanges()

      1. 尝试了this StackOverflow answer的解决方案并将代码更改为 public ActionResult SaveChanges([Bind(Include = "customerOrderQtyMax")] CustomerOrderLine line)
      2. 现在出现了这个错误: {&#34;无法添加或更新子行:外键约束失败(\&#34; c1snw \&#34;。\&#34; CustomerOrderLines \ &#34;,CONSTRAINT \&#34; FK_ProductCustomerOrderLine \&#34; FOREIGN KEY(\&#34; productID \&#34;)REFERENCES \&#34; Products \&#34;(\&#34; productID \&#34;)ON DELETE NO ACTION ON UPDATE NO ACTION)&#34;} ,这可能意味着......好吧,我不确定是否从DB中选择了正确的行代码以及是否尝试更新或添加新行。会检查一下。

        解:

        在Bind中使用<form action="/CustomerOrder/SaveChanges/8" method="post"> <input data-val="true" data-val-number="The field customerOrderLineID must be a number." data-val-required="The customerOrderLineID field is required." id="MemberOrder_customerOrderLineID" name="MemberOrder.customerOrderLineID" type="hidden" value="8"> <input class="text-box single-line" data-val="true" data-val-number="The field customerOrderQtyMax must be a number." data-val-required="The customerOrderQtyMax field is required." id="MemberOrder_customerOrderQtyMax" name="MemberOrder.customerOrderQtyMax" type="text" value="3"> <span class="field-validation-valid" data-valmsg-for="MemberOrder.customerOrderQtyMax" data-valmsg-replace="true"></span>
        <input type="submit" value="+" class="btn btn-default"> </form>
        的@ Jasen suggestion帮助让代码正常工作!

        但是,我在Bind中删除了 [HttpPost, ActionName("SaveChanges")] public ActionResult SaveChanges([Bind(Include = "customerOrderQtyMax")] CustomerOrderLine line) // whitelist fields { CustomerOrderLine lineTemp = new CustomerOrderLine() { customerOrderQtyMax = line.customerOrderQtyMax }; if(ModelState.IsValid) { db.Entry(lineTemp).State = EntityState.Added; db.SaveChanges(); return RedirectToAction("CustomerOrder"); } return View(lineTemp); } 语句,因为它仅在所有行的属性(最初不为空( null 或0))包含时才有用,由于我需要所有这些内容,因此我在Controller中删除了Prefix="MemberOrder"并在视图中添加了更多Include=个字段。如果我没有这样做,Controller会尝试将初始值更改为 null )或0.

        最终代码:

        我的控制器:

        Include=

        我的观点:

        HiddenFor

        有关类似问题的更多资源:

        1. ASP.NET MVC Model Binding - Part1 (CodeProject)

        2. How to use Bind Prefix? (StackOverflow)

        3. ASP.Net MVC3 Model Binding IEnumerable with Editor Template (StackOverflow)

        4. How to bind multiple prefixes? (ASP.NET)

        5. Multiple submit buttons with ASP.NET MVC: final solution

1 个答案:

答案 0 :(得分:0)

这里的关键问题是for循环会弄乱已发布的变量名称,以便自动绑定失败。因此,您需要将Prefix参数添加到Bind。

[Bind(Prefix="MemberOrder", ...)]

您在视图中的EditorFor帮助程序中指定的前缀:

@Html.EditorFor(model => MemberOrder.customerOrderQtyMax)

此外,将行ID添加到Bind Include。

[HttpPost, ActionName("SaveChanges")]
public ActionResult SaveChanges(
    [Bind(Prefix="MemberOrder", Include = "customerOrderLineID,customerOrderQtyMax")]
        SNW.Models.CustomerOrderInfo.MemberOrder line)
{
    if(ModelState.IsValid)
    {
        db.Entry(line).State = EntityState.Modified;
        db.SaveChanges();
        return RedirectToAction("CustomerOrder");
    }
    return View(line);
}