2013-05-15 3 views
7

Мне сложно четко заявить о проблеме, которую я испытываю. Я пытаюсь понять, как сохранить значения в полях формы, созданных в цикле после завершения проверки. У меня более сложная форма реального мира, в которой есть куча элементов, созданных в цикле и проверки. Я привел его к простому примеру, приведенному ниже.

Когда проверка не удалась, я хотел бы, чтобы текстовые поля с именем «Комментарий», которые были созданы в цикле, сохраняли значения, которые показаны на изображении Pre-Submit ниже.

Когда я отлаживаю отправку формы, значения из каждого из полей успешно связаны с переменной IList с именем Comment, найденной в модели. Это то, что я хочу, чтобы я мог выполнить цикл и найти их на основе индекса.

После представления каждое текстовое поле, созданное циклом, отображает запятую, представляющую переменную IList Comment в модели. Похоже, что поле в представлении и в модели соединяется, потому что у них есть имя. Они правильно подключаются по пути, но не на выходе. Я хотел бы, чтобы представление отображало только значение, связанное с комментарием [i], а не весь список, чтобы значения оставались постоянными между представлениями формы.

Скриншоты и примеры кода Ниже
Первая нагрузка:
First load of form without changes

Pre-Submit Форма изменения:
Form with changes to the first input before submitting

форма, как видно после первого представить:
Form as seen after the first submission

форма, как видно после того, как второй представляет:
enter image description here

Код модели
HTML.Textarea Значения в MVC Razor View

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 
    } 
} 


View Code

@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" /> 
} 


Controller Код

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 ищет HTML-имена в запросе, которые соответствуют свойствам TempListModel, для сборки модели на сервере. Но переопределение комментария Id каждого элемент HTML:

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

Если вам необходимо поместить этот пользовательский идентификатор, необходимо создать новый ModelBinder. Вы можете держать вещи легко, как это:

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

надеется, что ее поможет вам!

+1

Hello Fals. Спасибо, что посмотрели на это. Ясен избил вас, но я благодарен за добавленное объяснение, чтобы помочь моему пониманию. – RacerNerd