Привязка модуля MVC Asp.net с проверкой для сложных типов
Я создаю приложение для анкетирования в asp.net mvc, и у меня возникают проблемы с модулем связывания для списка сложных типов.
Во-первых: я не могу получить граф объектов Questionnaire.IList
Второе: я хотел бы передать в свой репозиторий / фабрику вместо класса связывателю, чтобы я мог отказаться от отображения между вопросами формы и вопросами БД, просто работая над одним набором объектов. Или, по крайней мере, что-то более красивое, чем этот код;).
Кто-нибудь получил указатель в правильном направлении для меня?
Контроллер:
public class QuestionnaireController : Controller
{
#region Constructors
public QuestionnaireController(IRepositoryWithTypedId<QuestionGroup, string> questionnaireRepository)
{
repository = questionnaireRepository;
}
#endregion
public ActionResult Create(string Id)
{
if (!string.IsNullOrEmpty(Id))
{
QuestionGroup questionnaire = repository.Get(Id);
return View(questionnaire);
}
else return RedirectToAction("Index");
}
[Transaction]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(string Id, QuestionGroup questionGroup)
{
QuestionGroup dbQuestionGroup = repository.Get(Id);
//Map Questions in form to Questions from db
foreach (var question in dbQuestionGroup.Questions)
{
Question persQuestion =
(from item in questionGroup.Questions where item.QuestionID.Equals(question.ID) select item)
.SingleOrDefault();
if (persQuestion != null)
{
question.Answer = persQuestion.Answer;
}
}
//Validate Questions(db)
bool valid = true;
foreach (var question in dbQuestionGroup.Questions)
{
if (!question.IsValid())
{
foreach (var item in question.ValidationMessages)
{
ViewData.ModelState.AddModelError("questionGroup.Questions[" + question.ID + "]." +
item.PropertyName,
item.Message);
}
valid = false;
}
}
//Return the same form with validation info appended
if (!valid)
{
return View(dbQuestionGroup);
}
//Persist to db and redirect to Complete
else
{
repository.SaveOrUpdate(dbQuestionGroup);
return RedirectToAction("Complete");
}
}
private IRepositoryWithTypedId<QuestionGroup, string> repository;
}
Частичное представление (основное представление просто выполняет foreach для вопросов в QuestionGroup и отображает это представление для каждого вопроса)
<div class="Question">
<div class="QuestionTitle">
<%=ViewData.Model.Description %>
</div>
<input name="questionGroup.Questions.Index" value='<%=ViewData.Model.ID %>' type="hidden" />
<input name='<%="questionGroup.Questions[" + ViewData.Model.ID + "].QuestionID" %>' value='<%=ViewData.Model.ID %>' type="hidden" />
<div class="QuestionText">
<%switch (ViewData.Model.Type.ToLower())
{
case QuestionType.Text:%>
<%=Html.TextBox("questionGroup.Questions[" + ViewData.Model.ID + "].Answer")%>
<% break;
case QuestionType.Number:%>
<%=Html.TextBox("questionGroup.Questions[" + ViewData.Model.ID + "].Answer")%>
<%= Html.ValidationMessage("questionGroup.Questions[" + ViewData.Model.ID + "].Answer")%>
<% break;
case QuestionType.PhoneNumber:%>
<%=Html.TextBox("questionGroup.Questions[" + ViewData.Model.ID + "].Answer")%>
<% break;
case QuestionType.Email:%>
<%=Html.TextBox("questionGroup.Questions[" + ViewData.Model.ID + "].Answer")%>
<%= Html.ValidationMessage("response.Questions[" + ViewData.Model.ID + "].Answer")%>
<% break;
case QuestionType.Date:%>
<%=Html.TextBox("questionGroup.Questions[" + ViewData.Model.ID + "].Answer")%>
<% break;
case QuestionType.YesNo:%>
<%=Html.RadioButton("questionGroup.Questions[" + ViewData.Model.ID + "].Answer", "0", true)%>Ikke valgt<br />
<%=Html.RadioButton("questionGroup.Questions[" + ViewData.Model.ID + "].Answer", "true", false)%>Ja<br />
<%=Html.RadioButton("questionGroup.Questions[" + ViewData.Model.ID + "].Answer", "false", false)%>Nei<br />
<% break;
case QuestionType.Alternative:%>
<%=Html.DropDownList("questionGroup.Questions[" + ViewData.Model.ID + "].Answer", new SelectList(ViewData.Model.Alternatives, "ID", "Description"))%>
<% break;
}%>
</div>
</div>
2 ответа
Я написал, как это сделать с помощью MvcContrib.FluentHtml:
- Редактирование списка элементов переменной длины с помощью MvcContrib.FluentHtml
- Редактирование списка элементов переменной длины с помощью MvcContrib.FluentHtml - Take 2
Одна проблема, которую я вижу, состоит в том, что вы устанавливаете значение своего индексатора элемента списка Вопросов на Идентификатор Вопросника, который на два уровня выше. Значение должно быть идентификатором вопроса, если он существует, или каким-либо прокси-значением (например, отрицательным числом), которое говорит вам, что это новый экземпляр.
Вы всегда можете написать свой собственный ModelBinder, который потребует от вас написать о двух методах. Смотрите метод UpdateCollection здесь. Затем вы можете передать свой репозиторий в свой собственный ModelBinder.