[英]ASP.Net MVC Postback and Models
這主要是對本期評論的后續評論,但我沒有足夠的聲譽評論......
假設我有一個簡單的模型:
public class SimpleClass
{
public String Label { get; set; }
public String FirstName { get; set; }
}
標簽是基於用戶/客戶端更改的,因此它不能是DataAttribute。 如果發布回發處理問題時,我們需要重繪整個頁面。 這是前一篇文章的關鍵問題。 接受的解決方案是這樣做:
@Html.DisplayTextFor(model => model.Label)
@Html.HiddenFor(model => model.Label)
@Html.EditorFor(model => model.FirstName)
這是有道理的,因為它有效。 但是我們的模型更加復雜和廣泛。 這種方法會導致大量的隱藏字段,這似乎是一個非常骯臟的解決方案。
這讓我想到JP的評論:
解決方案是重新加載模型。 但它不僅僅是重新加載,它也是一種合並,因為您希望保留任何客戶端數據更改。
default: SimpleClass { Label="TheLabel", FirstName="Rob"}
postedback: SimpleClass { Label="", FirstName="Steve" }
we want: SimpleClass { Label="TheLabel", "FirstName="Steve" }
我的問題是MVC有一個很好的方法來知道哪些字段被回發,所以它正確合並? 我們只需要合並回傳字段而不是空白屬性。
或者只是更好地整理回發而不是表單提交? 這樣可以避免提交時出現所有模型重新加載問題。
為了給予Pablo信用,我接受了他的解決方案。 要查看我的解決方案的簡單示例,請在下面的答案中查看Robert Harvey的評論:
這里的主要問題是嘗試將WebForms的PostBack概念融入MVC。 沒有狀態回發之類的東西只會自動保留其狀態。
您只有綁定到視圖的ViewModel,以及由視圖發布到Controller的ViewModel。 它們甚至不一定需要是同一類型。 這意味着,控制器應該只接收用戶確實可以更改的數據,而不是具有許多屬性的大對象,這些屬性是初始ViewModel的一部分,但是只讀。
標簽通常表示只讀文本,它們不是可編輯的表單元素。 這就是為什么你必須使用隱藏字段的原因。
是的,有時這意味着您必須重新加載控制器中的原始數據,並與您發布的新數據同步,這不一定是壞事。 如果將只讀數據綁定到用戶無法手動編輯的視圖,則您不應該真正信任之后在帖子中返回的數據。 僅僅因為你的html可能試圖讓它成為只讀並不意味着我不能操縱帖子並最終在你不知道的情況下改變你的“只讀”數據。
我剛看了你提到的第二個問題,從它的外觀來看,他的主要問題是他試圖再次重復使用相同的ViewModel,因此所有數據都丟失了,模型無效。 解決方案確實很簡單,只發布你需要的東西,作為一個新的ViewModel類型,並讓控制器處理其余的事情。
[移至OP]
我認為這就是巴勃羅對那些想知道的人的建議。 這似乎是解決這個問題的好方法。
楷模:
public class SimpleClass : SimpleClassPostBack
{
public String Label { get; set; }
public SimpleClass()
{
// simulate default loading
Label = "My Label";
FirstName = "Rob";
}
}
// contains only editable by the user fields
public class SimpleClassPostBack
{
public String FirstName { get; set; }
}
控制器動作:
[HttpGet]
public ActionResult SimpleClassExample3()
{
SimpleClass simpleClass = new SimpleClass();
return View(simpleClass);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult SimpleClassExample3(SimpleClassPostBack postBackSimpleClass)
{
Boolean errorOccurred = true;
if (!errorOccurred)
{
// do whatever success action is necessary
}
// redraw the page, an error occurred
// reload the original model
SimpleClass simpleClass = new SimpleClass();
// move the posted back data into the model
// can use fancy reflection to automate this
simpleClass.FirstName = postBackSimpleClass.FirstName;
// bind the view
return View(simpleClass);
}
視圖:
@model SimpleClass
@{
ViewBag.Title = "Simple Class Example3";
}
<h2>Simple Class Example3</h2>
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<label for="FirstName">@Html.DisplayFor(m => m.Label)</label>
@Html.EditorFor(m => m.FirstName)
<br/>
<button>Submit</button>
}
您應該只將數據從客戶端發送到服務器無法自行“弄清楚”的服務器。 如果服務器在用戶首次導航到該視圖時知道標簽是什么,那么如果用戶無法修改它們,則服務器將能夠在重新加載視圖時知道標簽是什么。
使用隱藏字段標識數據庫對象。 所以你的SimpleClass
應該有一些你將在隱藏輸入中使用的Id
。 使用EditorFor
for FirstName
。 現在,當發布表單時,使用發送的Id
從數據庫中查找正確的SimpleClass
,並使用發布的值修改其FirstName
屬性。 Label
屬性為null
,因為您不需要保存它。 現在,如果帖子中存在問題,並且您希望像往常一樣發回相同的視圖,則需要以與用戶第一次到達視圖時相同的方式重新填充Label
。 Id
和FirstName
屬性的值將自動發送回具有模型狀態的視圖。
綜上所述:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.