Связывание модуля MVC Asp.net с проверкой для сложных типов - PullRequest
2 голосов
/ 15 января 2009

Я создаю приложение для анкетирования в asp.net mvc, и у меня возникают проблемы со связывателем модулей для списка сложных типов.

Во-первых: я не могу получить графа объектов Questionnaire.IList .IList для работы со связывателем. Поэтому в приведенном ниже примере кода я использую только один уровень 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 ]

2 голосов
/ 20 января 2009

Я написал, как это сделать с помощью MvcContrib.FluentHtml:

Одна проблема, которую я вижу, состоит в том, что вы устанавливаете значение своего индексатора элемента списка Вопросов на Идентификатор Вопросника, который на два уровня выше. Значение должно быть идентификатором вопроса, если он существует, или каким-либо прокси-значением (например, отрицательным числом), которое сообщает, что это новый экземпляр.

1 голос
/ 15 января 2009

Вы всегда можете написать свой собственный ModelBinder, который потребует от вас написать о двух методах. См. Метод UpdateCollection здесь . Затем вы можете передать свой репозиторий в свой собственный ModelBinder.

...