My Model:
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; }
[..]
}
}
My Controller:
[..]
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);
}
}
}
My View (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>
Rendered View:

The Problem:
Whenever I change Max value of Order Line and click "+" to update it in database, it doesn't work.
The line values in SaveChanges() method comes as either 0 or null, including customerOrderQtyMax value which is 0.0, but DB update doesn't happen either - former values are being shown again.
So my question is, how do I pass only customerOrderQtyMax input value to DB from this IEnumerable View? I want' to be able to amend order (or shopping cart if you wish) values right in CustomerOrder.cshtml page.
What have I tried so far:
Updating Related Data with the Entity Framework in an ASP.NET MVC Application
Comparing
SaveChanges()method toEdit()method generated from DB Model by EF6 forCustomerOrderLinesentity. The later is not using IEnumerables<> and it has it's own View (Edit.cshtml).Added an extra
HiddenFor()field in my View as my Order Lines' primary keys are composed ofcustomerOrderLineIDandcustomerOrderIDattributes.
@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" />
}
Thank you for your help, guys!
EDIT:
I've changed the code in SaveChanges() method quite a few times, but here is what errors I received:
- Reference to
SNW.Models.CustomerOrderInfo.MemberOrderinpublic ActionResult SaveChanges([Bind(Include = "customerOrderQtyMax")] SNW.Models.CustomerOrderInfo.MemberOrder line)awards me with following error: {"The entity type MemberOrder is not part of the model for the current context."} probably because it's my custom made Model which inherits fromCustomerOrderModel, becauseCustomerOrdercan be overwritten by EF Model generator- I need to use extra custom made properties for calculations
- Changed
SNW.Models.CustomerOrderInfo.MemberOrderto originalCustomerOrderLineand received following error: {"Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. Refresh ObjectStateManager entries."}.CustomerOrderLineis generated by EF Model generator and I want its properties to merge withCustomerOrderto be able to edit Order's information in one window rather then going to Edit View for every single row (order line). That's why I made customSNW.Models.CustomerOrderInfo.MemberOrderModel.- Now
SaveChanges()ispublic ActionResult SaveChanges([Bind(Include = "customerOrderQtyMax")] CustomerOrderLine line)
- @Jasen. HTTP POST Header Thank you.
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 Form:
<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>
- Tried a solution from this StackOverflow answer and changed the code to
[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); }
And now got this error: {"Cannot add or update a child row: a foreign key constraint fails (\"c1snw\".\"CustomerOrderLines\", CONSTRAINT \"FK_ProductCustomerOrderLine\" FOREIGN KEY (\"productID\") REFERENCES \"Products\" (\"productID\") ON DELETE NO ACTION ON UPDATE NO ACTION)"}, which probably means... well, I'm not sure if correct line is selected from DB using this code and whether it is trying to Update or Add a new line. Will check that.
SOLUTION:
@Jasen's suggestion of using Prefix="MemberOrder" in Bind helped to get code working!
However, I got rid of Include= statement in Bind, because it only worked when all line's attributes, that are not initially empty (null or 0) are included, and since I need all of them, I removed Include= in Controller and added more HiddenFor fields in the View. If I haven't had done this, Controller would attempt to change initial values to null) or 0.
Final code:
My Controller:
[HttpPost, ActionName("SaveChanges")]
public ActionResult SaveChanges([Bind(Prefix="MemberOrder")] CustomerOrderLine line) // whitelist fields
{
if(ModelState.IsValid)
{
db.Entry(line).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("CustomerOrder");
}
return View(line);
}
My View:
@using (Html.BeginForm("SaveChanges", "CustomerOrder", new { id = MemberOrder.customerOrderLineID }))
{
@Html.ValidationSummary(true)
@Html.HiddenFor(model => MemberOrder.customerOrderLineID)
@Html.HiddenFor(model => MemberOrder.customerOrderID)
@Html.HiddenFor(model => MemberOrder.productID)
@Html.HiddenFor(model => MemberOrder.customerOrderQtyMin)
@Html.EditorFor(model => MemberOrder.customerOrderQtyMax)
@Html.HiddenFor(model => MemberOrder.customerOrderQtyActual)
@Html.ValidationMessageFor(model => MemberOrder.customerOrderQtyMax)
<input type="submit" value="+" class="btn btn-default" />
}