我一直在使用 Entity Framework 6 作為我的 Business Programming II 課程的作業來開發 ASP.NET MVC 5 Web 應用程式。盡管我對編程知之甚少,但我一直在進步,但我遇到了麻煩。我應該為基于 Northwind Traders 資料庫的在線店面撰寫 CRUD 操作。我已經有了從資料庫中讀取以及在資料庫中添加和更新專案的作業代碼。我正在努力的地方是洗掉專案。分配描述中列出了以下要求:
通過停止產品來洗掉產品,以便資訊顯示在資料庫中。不要實際從資料庫中洗掉產品。
我已經嘗試了幾件事來嘗試完成這項作業,但由于各種原因都失敗了。
這是我當前Delete視圖的代碼(忽略任何奇怪的 HTML 格式決定,現在我專注于獲得這個功能):
@model NWTradersWeb.Models.Product
@{
ViewBag.Title = "Delete";
}
<h2>Delete</h2>
<h3>Are you sure you want to delete this?</h3>
<div>
<h4>Product: @Html.DisplayFor(model => model.ProductName)</h4>
<hr />
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-actions">
<input type="submit" value="Yes" class="btn btn-dark" /> |
@Html.ActionLink("Back to List", "Index")
</div>
}
</div>
我已嘗試編輯我ProductsController.cs以手動將Discontinued屬性設定為 true,如下所示:
public ActionResult Delete(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Product product = db.Products.Find(id);
if (product == null)
{
return HttpNotFound();
}
return View(product);
}
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public ActionResult DeleteConfirmed(int id)
{
Product product = db.Products.Find(id);
product.Discontinued = true;
db.SaveChanges();
return RedirectToAction("Index");
}
這可行,但如果我在同一產品上運行該操作Edit,我將無法撤消更改。我可以取消選中已停產復選框,但在我提交更改后它不會保存,并且索引頁面仍將產品顯示為已停產。
這是我的Edit視圖代碼和相應的ProductsController.cs方法,我不確定這些是否與我的問題有關,但無論如何我都會包含它們:
看法:
@model NWTradersWeb.Models.Product
@{
ViewBag.Title = "Edit";
}
<h2>Edit</h2>
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Product: @Html.DisplayFor(model => model.ProductName)</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
@Html.HiddenFor(model => model.ProductID)
<div class="form-group">
@Html.LabelFor(model => model.SupplierID, "SupplierID", htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownList("SupplierID", null, htmlAttributes: new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.SupplierID, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.CategoryID, "CategoryID", htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownList("CategoryID", null, htmlAttributes: new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.CategoryID, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.QuantityPerUnit, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.QuantityPerUnit, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.QuantityPerUnit, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.UnitPrice, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.UnitPrice, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.UnitPrice, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.UnitsInStock, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.UnitsInStock, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.UnitsInStock, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.UnitsOnOrder, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.UnitsOnOrder, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.UnitsOnOrder, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.ReorderLevel, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.ReorderLevel, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.ReorderLevel, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Discontinued, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
<div class="checkbox">
@Html.EditorFor(model => model.Discontinued)
@Html.ValidationMessageFor(model => model.Discontinued, "", new { @class = "text-danger" })
</div>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}
控制器方法:
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Product product = db.Products.Find(id);
if (product == null)
{
return HttpNotFound();
}
ViewBag.CategoryID = new SelectList(db.Categories, "CategoryID", "CategoryName", product.CategoryID);
ViewBag.SupplierID = new SelectList(db.Suppliers, "SupplierID", "CompanyName", product.SupplierID);
return View(product);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "ProductID,ProductName,SupplierID,CategoryID,QuantityPerUnit,UnitPrice,UnitsInStock,UnitsOnOrder,ReorderLevel,Discontinued")] Product product)
{
if (ModelState.IsValid)
{
db.Entry(product).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.CategoryID = new SelectList(db.Categories, "CategoryID", "CategoryName", product.CategoryID);
ViewBag.SupplierID = new SelectList(db.Suppliers, "SupplierID", "CompanyName", product.SupplierID);
return View(product);
}
My professor also alluded to making the Delete operation redirect to a simpler Edit page where we could toggle the Discontinued attribute. I think he may be alluding to a partial view but we have not covered that to my knowledge.
Please note: I consider myself a novice when it comes to programming. I've taken other classes but the instructors focused more on syntax than concepts and as such my foundation is incredibly weak. I might be clueless about certain things that other people take for granted. I want to go back and study the fundamentals after I graduate and self-study, but this is a required class for a degree that is almost completely unrelated to programming. Any tips, hints, even a nudge in the right direction would be greatly appreciated.
uj5u.com熱心網友回復:
您的洗掉邏輯似乎很好。我要更詳細地看的是您的編輯。
總的來說,我不喜歡在服務器和視圖之間傳遞物體,尤其是從視圖中接受物體。這通常是一種不好的做法,因為您信任來自視圖的資料,這些資料很容易被篡改。將資料從視圖傳遞到服務器時也是如此,這可能導致僅通過使用一些“草率”的 JavaScript 或將模型轉換為 JSON 模型以檢查客戶端而意外暴露有關您的域的更多資訊(和性能問題)。最近一名記者因在密蘇里州政府網站的瀏覽器除錯器中發現額外資訊而被指控“黑客行為”的案例概述了當服務器端代碼有可能向其發送太多細節時可能出現的廢話。瀏覽器。
無論如何,在您的 Edit 方法中,當您在停用 Discontinued 標志后接受系結的 Product 時,該物體模型中有哪些值?例如,如果您使用 Delete 將 Discontinued 設定為“True”,然后轉到該產品的“編輯”視圖并取消選中該輸入控制元件并提交表單,在“編輯”頁面中的“產品”中,狀態是什么的產品。停產?
如果該值仍為“True”,則您的頁面系結存在潛在問題,即 EditorFor 未正確鏈接到該標志或該值未反序列化到 Product 物體中。(一個private或缺少二傳手?)
如果它回傳正確的值,那么我會考慮更改更新物體的方式。像這樣的代碼:
db.Entry(product).State = EntityState.Modified;
db.SaveChanges();
...本質上是危險的,因為“產品”不是物體,它是用于填充物體類的反序列化值集。理想情況下,在更新資料時,您將提供一個不會與物體類混淆的 ViewModel,并且只包含允許更新的欄位。使用您當前的代碼,但將物體類用作該視圖模型,我建議更像:
var dataProduct = db.Products.Single(x => x.Id == product.Id);
dataProduct.ProductName = product.ProductName;
dataProduct.Discontinued = product.Discontinued;
// ...
db.SaveChanges();
當涉及到可能允許用戶更改類別之類的 FK 時,您應該立即加載這些關系,比較 FK ID,然后在從資料狀態加載的物體中加載并重新關聯這些“新”關系。(不要只替換 FK 值。)
這樣做而不是附加并將狀態設定為已修改的原因:
- 我們在加載物體時執行驗證。如果我們回傳一個不存在的 Id,我們可以處理該例外。我們還可以過濾資料以確保當前用戶實際上有權查看請求的 ID,并且如果看起來有人在篡改資料,則可以結束會話。
- 我們只更新我們允許更改的值,而不是物體中的所有內容。在進行更改之前,我們還可以驗證以確保提供的值適合用途。
- When copying values across, EF will only generate
UPDATEstatements for values that actually change if any actually change. Attaching and setting the entity state toModifiedor usingUpdatewill always generate anUPDATEstatement replacing all values whether anything changed or not. (can have negative impacts on triggers or hooks in the DbContext for things like Auditing)
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/456797.html
