Главная > ASP.NET > ASP.NET MVC для начинающих. Часть 2. Работа с формами.

ASP.NET MVC для начинающих. Часть 2. Работа с формами.

Поработаем немного с формами. В проекте будет три формы: стартовая, форма регистрации, результат регистрации.

В экшене Index() контроллера HomeController напишем такой код:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using MvcApplication1.Models;

namespace MvcApplication1.Controllers
{
    public class HomeController : Controller
    {
        public ViewResult Index()
        {
            int hour = DateTime.Now.Hour;
            ViewData["greeting"] = (hour < 12 ? "Доброе утро" : "Добрый вечер");
            return View();
        }
    }
}

Ничего сложного, в зависимости от времени суток выводится определенное приветствие. Код вьюхи Index выглядит так:

<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Index</title>
</head>
<body>
    <h1>Сейшен !</h1>

    <%= ViewData["greeting"] %>! Для участия в вечеринке, ты должен сообщить о себе.

    <%= Html.ActionLink("Перейти к регистрации", "RegForm") %>
</body>
</html>

Запускаем, проверяем ссылку. Вьюхи RegForm пока нет, сейчас мы ее создадим. Нам понадобятся три ТекстБокса (имя, мыло, телефон), один ДропДаунЛист и кнопка отправки данных.

<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Форма регистрации</title>
</head>
<body>
    <h1>Регистрация</h1>
    <% using(Html.BeginForm()) { %>
        Твое имя: <%= Html.TextBox("Name") %>
        Твое мыло: <%= Html.TextBox("Email")%>
        Твой телефон: <%= Html.TextBox("Phone")%>

            Будет весело. Ты решился ?
            <%= Html.DropDownList("WillAttend", new[] {
            new SelectListItem { Text = "Да, я готов",
            Value = bool.TrueString },
            new SelectListItem { Text = "Наверное нет",
            Value = bool.FalseString }
            }, "Выбирай") %>

    <input type="submit" value="Зарегиться" />
    <% } %>
</body>
</html>

С введенными данными нужно что-то делать, независимо от того, что именно, работать с данными должна модель. Правильнее было бы наверное сначала спроектировать модель, а затем вьюху, но мы сделали так. У нас имеется четыре контрола, которые предоставят нам свои данные, соответственно для каждого из них создадим по свойству – все предельно просто:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace MvcApplication1.Models
{
    public class GuestResponseModel
    {
        public string Name { get; set; }
        public string Email { get; set; }
        public string Phone { get; set; }
        public bool? WillAttend { get; set; }
    }
}

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

Небольшое подведение итогов: у нас есть модель в кол-ве 1шт, есть вьюхи в кол-ве 2шт, есть экшен контроллера в кол-ве 1шт. Видите нестыковку ? Не хватает экшена RegForm(). Сделаем его как делали раньше, т.е. метод нам просто возвратит View():

        public ViewResult RegForm()
        {
            return View();
        }

Запускаем проект, вводим регистрационные данные, отправляем их. После нажатия на кнопку отправки, наши контролы возвращаются пустыми. HTTP-протокол не поддерживает состояния между запросами, при каждой новой загрузке страницы, все контролы создаются заново (чистыми), в Webforms эта проблема решается использованием Viewstate и Postback (это один из вариантов), информация Viewstate хранит в себе данные о состоянии объекта до его отправки на сервер, вновь создаваемый объект восстанавливает свое состояние из Viewstate. За эти прелести приходится платить – Viewstate гоняется на сервер и обратно при каждом запросе, следовательно растет объем передаваемых данных, и появляется SEO-кошмар в коде HTML. В ASP.NET MVC отсутствует Viewstate, поэтому будем делать как в старые добрые времена – методами GET и POST. Методом GET мы запрашиваем страницу RegForm, отсылать данные мы будем методом POST, поэтому нам нужны два варианта экшена RegForm() контроллера HomeController:

        [AcceptVerbs(HttpVerbs.Get)]
        public ViewResult RegForm()
        {
            return View();
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ViewResult RegForm(MvcApplication1.Models.GuestResponseModel guestResponse)
        {
            return View(guestResponse);
        }

Теперь все должно работать как надо. То, как входные данные связываются с моделью и контроллером объясняется работой ASP.NET MVC. Познакомимся теперь с Strongly Typed Views. Для этого перепишем код последнего экшена:

        [AcceptVerbs(HttpVerbs.Post)]
        public ViewResult RegForm(MvcApplication1.Models.GuestResponseModel guestResponse)
        {
            return View("Thanks", guestResponse);
        }

ASP.NET MVC теперь должна находить и отрисовывать вьюху Thanks, снабжая ее объектом guestResponse. Создадим Strongly Typed View с именем Thanks, для этого в появившемся модальном окне Add View отметим пункт Create a strongly typed view и из выпадающего списка выберем MvcApplication1.Models.GuestResponseModel, пункт “View content” поставим в Empty. Созданная вьюха будет строго типизирована для работы с GuestResponse, поэтому у нас будет возможность работать с Model класса GuestResponseModel:

<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<mvcApplication1.Models.GuestResponseModel>" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Спасибо</title>
</head>
<body>
    <h1>Привет, <%= Html.Encode(Model.Name) %>!</h1>
    <% if(Model.WillAttend == true) { %>
        Отлично, что ты придешь !
        <% } else { %>
        Очень жаль.
    <% } %>
</body>
</html>

Кроме точного определения типа данных для рендеринга, используя Strongly Typed Views, мы получаем полную поддержку IntelliSense для нашего типа данных.

Добавим валидацию. Не забываем, что мы используем паттерн MVC, а следовательно валидация должна быть частью модели, а не чего-либо еще. Перепишем код модели:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel;

namespace MvcApplication1.Models
{
    public class GuestResponseModel : IDataErrorInfo
    {
        public string Name { get; set; }
        public string Email { get; set; }
        public string Phone { get; set; }
        public bool? WillAttend { get; set; }

        public string Error { get { return null; } }
        public string this[string propName]
        {
            get
            {
                if ((propName == "Name") && string.IsNullOrEmpty(Name))
                    return "Имя не введено";
                else if ((propName == "Email") && string.IsNullOrEmpty(Email))
                    return "Некорректный е-майл";
                else if ((propName == "Phone") && string.IsNullOrEmpty(Phone))
                    return "Телефон не введен";
                else if ((propName == "WillAttend") && !WillAttend.HasValue)
                    return "Никак не определишься ?";
                return null;
            }
        }
    }
}

Теперь нам необходимо немного переписать экшен RegForm:

[AcceptVerbs(HttpVerbs.Post)]
        public ViewResult RegForm(MvcApplication1.Models.GuestResponseModel guestResponse)
        {
            if (ModelState.IsValid)
            {
                return View("Thanks", guestResponse);
            }
            else
                return View();
        }

и добавить сообщение о валидации на страницу RegForm:

<%= Html.ValidationSummary() %>

Как вы заметили, валидация довольно простенькая, без регулярок и т.п., в этом уроке у нас другая цель — познакомиться с формами.

  1. alessandro
    25 сентября 2010 в 12:50 | #1

    где то я уже видел этот пример;))в одной книге
    Даешь копипаст в народ!

  2. Kiril1
    25 сентября 2010 в 14:30 | #2

    Добрый день!
    Будьте добры подскажите почему в данном коде возникает ошибка в месте где else (ошибка — недопустимый элемент «else» в выражении)

    Заранее признателен!

  3. 4 октября 2010 в 20:05 | #3

    @Kiril1
    В каком конкретно месте ? Код, насколько я помню, тестировал сам, когда разбирался с MVC, и подобных ошибок не помню.

    @alessandro
    Тем не менее, многие почему-то ленятся читать книги и задают вопросы на форумах/сайтах, поэтому, чтобы не высасывать из пальца, порой проще скопипастить.

  4. Vector
    15 ноября 2010 в 10:26 | #4

    Не подскажит назвние книги?

  5. Vector
    15 ноября 2010 в 10:39 | #5

    Я уже нашел.

  1. Пока что нет уведомлений.