2013-05-15 185 views
7

我很難清楚地說明我遇到的問題。我想了解如何在驗證失敗後在循環中創建的表單字段中保留值。我有一個更復雜的真實世界形式,它有一些在循環和驗證中創建的元素。我已經將它簡化爲下面包含的一個簡單示例。

驗證失敗時,我希望在循環中創建的名爲「Comment」的textareas保留下面的預發送圖像中顯示的值。

當我調試表單提交時,每個字段的值都成功連接到模型中名爲Comment的IList變量。這是我想要的,所以我可以循環並根據索引找到它們。

提交後,循環生成的每個textarea都會顯示模型中IList變量Comment的逗號分隔表示。看起來,視圖中和模型中的字段是連接的,因爲它們共享一個名稱。他們在途中正確連接,但不在出路。我希望視圖僅顯示與Comment [i]相關的值而不是整個列表,以便表單提交之間的值保持不變。

截圖和示例代碼下面
第一負載:
First load of form without changes

預提交表單的變化:
Form with changes to the first input before submitting

形式看到後先提交:
Form as seen after the first submission 012纔可以看到
表第二提交:
enter image description here

型號代碼
MVC剃刀視圖中的HTML.Textarea值

using System.Collections.Generic; 
namespace UI.Models.Forms 
{ 
    public class TempListModel : ContentModel 
    { 
     public TempListModel() 
     { 
      Comment = new List<string>(); 
     } 
     public IList<string> Comment { get; set; } //Comments for each URL in the list 
    } 
} 


查看代碼

@model UI.Models.Forms.TempListModel 
@using (Html.BeginForm("temptest", "Test", new { id = 1 }, FormMethod.Post, new { id = "listForm", name = "listForm" })) 
{ 
    <ul> 
     @for (int i = 0; i < Model.Comment.Count(); i++) 
     { 
      <li> 
       <div class="llformlabel"> 
        Notes: 
        <div>@Model.Comment[i]</div> 
        @Html.TextArea("Comment", Model.Comment[i], 4, 63, new { @id = "Comment_" + i, @title = "Comment" })</div> 
      </li> 
     } 
    </ul> 
    <input type="submit" value="Save Changes" /> 
} 


控制器代碼

using System.Collections.Generic; 
using System.Web.Mvc; 
using UI.Models.Forms; 
namespace UI.Controllers 
{ 
    public class TestController : Controller 
    { 
     [AcceptVerbs(HttpVerbs.Post)] 
     public ActionResult TempTest(TempListModel model) 
     { 
      //This function executes after the user submits the form. 
      //If server side validation fails then the user should be shown the form as it was when they submitted. 
      //model.Comment = GetComments(); //In my real world example this comes from a database. 
      if (true) //!ModelState.IsValid) //In my real world code this is a validation step that may fail 
      { 
       return View(model); 
      } 
     } 
     [AcceptVerbs(HttpVerbs.Get)] 
     public ActionResult TempTest(int? id) 
     { 
      //In the real world example there is a lot going on in this function. 
      //It is used to load data from databases and set up the model to be displayed. 
      var model = new TempListModel(); 
      model.Comment = GetComments(); 
      return View("TempTest", "TempLayout", model); 
     } 
     private static IList<string> GetComments() 
     { 
      //Simple sample function used for demo purposes. 
      IList<string> comments = new List<string>(); 
      comments.Add("Comment 1"); 
      comments.Add("Comment 2"); 
      comments.Add("Comment 3"); 
      return comments; 
     } 
    } 
} 

回答

8

如果驗證失敗只返回模型。

[AcceptVerbs(HttpVerbs.Post)] 
    public ActionResult TempTest(TempListModel model) 
    { 
     if (ModelState.IsValid) 
     { 
      return RedirectToAction("TempTest"); 
     } 
     return View(model); 
    } 

編輯試試這個在您的視圖,而不是

@for (int i = 0; i < Model.Comment.Count(); i++) 
{ 
    <li> 
     @Html.TextAreaFor(m => m.Comment[i], 4, 63, new { @title = "Comment" }) 
    </li> 
} 

並讓助手名給你的元素。您最終得到name屬性,如Comment[i]

+0

我剛剛修改我的代碼示例以使用視圖而不是RedirectToAction,因此更清楚的是GetComments函數不會覆蓋這些值。我相信我現在的代碼示例正在按照您的建議顯示,並且仍然存在相同的問題。 – RacerNerd

+0

@RacerNerd見編輯。 – Jasen

+0

謝謝。這個伎倆。每當我希望html字段連接到模型中的變量時,是否更適合在其中使用帶有「For」的html生成器?我正在使用它的代碼出現連接變量主要是通過名稱匹配來完成,因爲我在這裏看到的並不是在所有情況下都能解決。 – RacerNerd

2

ASP。NET MVC默認ModelBinder在請求中查找與TempListModel屬性相匹配的HTML名稱,以便在服務器中構建模型。但要覆蓋每個HTML元素的註釋ID:

@Html.TextArea("Comment", Model.Comment[i], 4, 63, new { @id = "Comment_" + i, @title = "Comment" }) 

如果您需要將這個自定義ID,你必須創建一個新ModelBinder。 可以讓事情變得容易這樣的:

@Html.TextAreaFor(m => m.Comment[i], 4, 63, new { @title = "Comment" }) 

希望其幫助你!

+1

你好Fals。感謝您查看這個。 Jasen擊敗了你,但我很欣賞這個補充解釋,以幫助我進一步理解。 – RacerNerd