Как передать строго типизированные результаты обратно в ActionResult? - PullRequest
1 голос
/ 11 июня 2010

У меня есть строгое представление:

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<MPKwithMVC.Models.SmartFormViewModel>" %> 

Отлично работает для генерации представления, но когда я публикую сообщение, у меня определен ActionResult:

[AcceptVerbs(HttpVerbs.Post)]  
public ActionResult Next(MPKwithMVC.Models.SmartFormViewModel model)   
{ .. }  

Который, как я представляю, получит удар при нажатии следующей кнопки (это работает, если я изменю аргумент на FormsCollection). Вместо этого я получаю сообщение: «Для этого объекта не определен конструктор без параметров».

Что я делаю не так?

Моя SmartFormsViewModel:

    [Serializable]
public class SmartFormViewModel
{
    public List<Question> Questions { get;  set; }
    public List<Answer> Answers { get;  set; }

    public SmartFormViewModel(List<Question> questions, List<Answer> answers)
    {
        this.Questions = questions;
        this.Answers = answers;
    }

    public SmartFormViewModel()
    {
    }
}

А вот и вид:

    <%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<MPKwithMVC.Models.SmartFormViewModel>" %>
<%@ Import Namespace="MPKwithMVC.Models" %>

<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
    SmartForms
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

    <h2>
        Questionaire</h2>
    <% using (Html.BeginForm("Next", "SmartForms"))
       { %>
    <div style="float: left; margin-right: 2em;">
        <% Html.RenderPartial("NavigationPanel", Model); %>
    </div>
    <div>
        <table>
            <%
                foreach (Question question in (Model.Questions))
                { %>
            <tr>
                <td>
                    <div style="text-align: right; width: 20em;">
                        <%= Html.Encode(question.QuestionText)%>
                    </div>
                </td>
                <td>
                    <div style="float: left;">
                        <% if (question.QuestionType == 1)
                           { %>
                        <%= Html.TextBoxFor(model => model.Answers[(int)question.QuestionID - 1].AnswerValue) %>
                        <% } %>
                        <% if (question.QuestionType == 2)
                           { %>
                        <%= Html.RadioButton("yn" + question.QuestionID, "Yes", false)%>Yes
                        <%= Html.RadioButton("yn" + question.QuestionID, "No", true)%>No
                        <% } %>
                    </div>
                    <% if (question.Required == true)
                       { %>
                    <div style="color: Red; float: right; margin-left: 3px;">
                        *</div>
                    <% } %>
                </td>
            </tr>
            <%
                } %>
            <tr>
                <td>
                    <%
           if (ViewData["errorMsg"] != null)
                       {%>
                       <div style="color:Red;">
                        <%= Html.Encode(ViewData["errorMsg"].ToString()) %>
                       </div>
                    <% } %>
                </td>
                <td>
                    <div style="margin-top: 1em;">

                        <button name="button" value="next">Next</button>

                    </div>
                </td>
            </tr>
        </table>
    </div>
    <% } %>

</asp:Content>

Ответы [ 3 ]

1 голос
/ 21 июня 2010

Убедитесь, что ваш <form> action указывает на ваш Next метод.

1 голос
/ 22 июня 2010

Посмотрите на входные имена, которые генерируются в вашем HTML.Я думаю, что у вас есть проблема с именованием ваших элементов управления, поэтому привязка модели по умолчанию не работает, поскольку вы упомянули, что использование FormCollection работает правильно.Я делаю это предположение, так как я не знаю, как выглядят ваши классы вопросов и ответов

<%= Html.TextBoxFor(model => 
        model.Answers[(int)question.QuestionID - 1].AnswerValue) %>

Не приведёт ли это к чему-то похожему на следующее;который, если я не ошибаюсь, не будет привязываться к вашей модели.То же самое относится к RadioButtons.

<input type="text" name="Answers[0].AnswerValue" id="Answers_0__AnswerValue" value="somevalues"/>

Помощник RadioButton должен иметь значение

<%= Html.RadioButton("Questions[" + question.QuestionID + "].ID", "Yes", false)%> // you now get a list of questions

<input type="radio" name="Questions[1].ID" id="Questions_1__ID" value="No" checked="checked"/>

Есть несколько способов решить эту проблему:

  1. Правильно назовите ваши элементы управления вводом, чтобы они соответствовали вашей ViewModel.(Это включает в себя разноску всех обязательных полей для вашей модели - я думаю, что эти значения по умолчанию используются, когда привязка модели происходит, если она не разнесена)
  2. Создание привязки пользовательской модели
  3. Вы можетенужно сказать Binder, каков префикс полей ввода.([Bind] атрибут ), чтобы специально включить или исключить поля формы.
  4. Создать новую модель, содержащую значения, которые вы ожидаете отправить обратно

Я думаю, чтоВ целом, что ваш подход должен немного измениться.Из предоставленной информации ваши вопросы и ответы тесно связаны.В зависимости от типа вопроса ваш «ответ» может быть либо логическим, либо свободным текстом.В данный момент вы не отправляете List<Questions> обратно на сервер.Ответы, да, но они не являются, я не думаю, что это признается как List<Answers>.

Haacked имеет пост, который, я думаю, связан с вашей проблемой, и этот вопрос SO дополнительно указывает, что он все еще может применяться к ASP-MVC-2.

1 голос
/ 15 июня 2010

Как следует из сообщения об ошибке, ваш класс SmartFormViewModel должен содержать конструктор без параметров.

Этот является отличным примером того, что вы хотели бы сделать

Я бы также предложил вам использовать строго типизированные помощники из расширений HTML для генерации полей формы.

например.

Html.HiddenFor(x => x.SomeField) 
Html.TextBoxFor(x => x.SomeEditableField)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...