R
R
Roman Gamretsky2014-06-07 12:49:26
ASP.NET
Roman Gamretsky, 2014-06-07 12:49:26

How to pass a specific parameter to an element in a list?

The situation is the following. There is a Model1 which contains a list of another object (Model2) which has a Text property. Tell me how to transfer the form to the Model1 controller, as well as the Model2 list element that should be automatically filled, and the Text property to take the value from the form element.
Model1

public class PollModel
    {

        public string Id { get; set; }
        public string Question { get; set; }
        public IEnumerable<Answer> Answer { get; set; }
        public int Answered { get; set; }
        public string UserIdCreated { get; set; }
    }

Model2
public class Answer
    {
        [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public string Id { get; set; }
        public string QuestionId { get; set; }
        public string Text { get; set; }
        public int Chosen { get; set; }

    }

Controller
public ActionResult Create([Bind(Include = "Id,Question,Answer,Answered,UserIdCreated")] PollModel poll)
        {
            return View(poll);
        }

As well as a part of the view from which the Text property should be filled
<div class="form-group">
            @Html.LabelFor(model => model.Answer, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Answer.Single().Text, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Answer.Single().Text, "", new { @class = "text-danger" })
            </div>
        </div>

Tell me how to fill in the IEnumerable Answer correctly and pass it to the controller.

Answer the question

In order to leave comments, you need to log in

1 answer(s)
V
Valery Abakumov, 2014-06-30
@rgamretsky

Добрый день!
1. Я, возможно, что-то немного не понял, но использовать тип string для поля Id - плохая практика. Используйте int вместо string.
2. Называйте переменные правильно: если у Вас список ответов, то лучше вместо "Answer" назовите Answers" или "AnswerList" - старайтесь писать такой код, чтобы с ним после Вас мог легко работать другой программист.
3. (на всякий случай) Для сообщений валидации можно использовать атрибуты (Required, MaxLength, ...) - я заметил, что в ValidationMessageFor Вы используете "" для текста сообщения валидации.
4. В классе Answer у Вас есть свойство Chosen - если я правильно понимаю, это "Выбран", т.е. это логическая переменная, которая может быть либо "Да", либо "Нет". Зачем используете тип int, ведь есть тип bool?
4. Не знаю, как у Вас, но не заполнив коллекцию Answer(s) в модели PollModel на сервере, Вы не сможете обращаться к ней через Single(), потому что в методе действия Create, который Вы привели, модель не заполняется, соответственно, коллекция Answer(s) равна null, в результате - ошибка, т.к. у null-объекта нельзя обращаться к свойствам. Поэтому Вам нужно как минимум сформировать модель на сервере, например, так:

[HttpGet]
public ActionResult Create()
{
     List<Answer> answers = new List<Answer>();
     answers.Add(new Answer() { Id = 1, QuestionId = 1, Text = "Вопрос №1", Chosen = false });
     PollModel viewModel = new PollModel()
     {
          Id = "1", 
          UserIdCreated = "user1",
          Answers = answers
     };
     return View(viewModel);
}

5. Т.к. у Вас коллекция Answer(s), то для правильной привязки нужно правильно сформировать View, потому что привязка к коллекциям в ASP.NET MVC осуществляется особым образом - если посмотрите на html-код, то увидите, что тег input, в который нужно ввести текст, имеет атрибут name="Answers[0].Text и атрибут id="Answers_0__Text". Так работает связыватель модели (Model Binder) в ASP.NET MVC по-умолчанию .
Рабочий пример - основан на шаблоне ASP.NET MVC 4 Internet Application в VS 2012:
HomeController.cs:
[HttpGet]
        public ActionResult Create()
        {
            List<Answer> answers = new List<Answer>();
            answers.Add(new Answer() { Id = 1, QuestionId = 1, Text = "Вопрос №1", Chosen = false });
            PollModel viewModel = new PollModel()
            {
                Id = "1", 
                UserIdCreated = "user1",
                Answers = answers
            };
            return View(viewModel);
        }

        [HttpPost]
        public ActionResult Create(PollModel viewModel)
        {
            TempData["Message"] = String.Format("Текст Вашего вопроса - {0}", viewModel.Answers.First().Text);
            return View(viewModel);
        }

Create.cshmtl:
@using TosterQuestion101113_MVC.Models;
@model PollModel

@{
    ViewBag.Title = "Create";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2>Create</h2>
<div class="form-group">
    @using (Html.BeginForm("Create", "Home", FormMethod.Post, null))
    {
        if (TempData["Message"] != null)
        {
            <div class="message">
                @TempData["Message"]
            </div>
        }
        
        @Html.LabelFor(e => e.Answers, new { @class = "control-label col-md-2" })
        for (int i = 0; i < Model.Answers.Count(); i++)
        {
            <div class="col-md-10">
            @Html.EditorFor(e => e.Answers[i].Text, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(e => e.Answers.Single().Text, "", new { @class = "text-danger" })
        </div>
        }
        
        <div>
            <input type="submit" value="ОК!" />
        </div>
    }
</div>

Notes:
1. Property IEnumerable<Answer> Answerchanged to IList<Answer> Answers- because Ilist provides access to the Count() method to implement the enumeration in a loop
2. Answer.Single().Textchanged to Answers[i].Text
3. In general - I got the impression that you have recently started learning ASP.NET MVC and that you have been programming for a long time. Therefore, I have to insist: read from cover to cover the book "ASP.NET MVC3 (or 4) Framework with C # examples for professionals" - everything is simply perfectly explained by ASP.NET MVC.
I hope I helped you a little.
Good luck!

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question