Каковы обязанности компонентов в шаблоне MVC для простого входа - PullRequest
3 голосов
/ 16 февраля 2011

Я пытаюсь понять шаблон MVC и получаю общее представление о том, что Модель отвечает за поддержание состояния, представление отвечает за отображение модели, а контроллер отвечает за изменение модели и вызов соответствующего представления.(ы).Я хотел попробовать и реализовать простую страницу входа ASP.NET MVC, которая использует OpenID , чтобы получить некоторое представление о том, как все это работает.

Я скачал DotNetOpenAuth-3.4.6 и я просматривал образцы, в частности их образец MVC.К сожалению, на самом деле образец не имеет модели, только контроллер:

namespace OpenIdRelyingPartyMvc.Controllers
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    using System.Web.Security;
    using DotNetOpenAuth.Messaging;
    using DotNetOpenAuth.OpenId;
    using DotNetOpenAuth.OpenId.RelyingParty;

    public class UserController : Controller
    {
        private static OpenIdRelyingParty openid = new OpenIdRelyingParty();

        public ActionResult Index()
        {
            if (!User.Identity.IsAuthenticated)
            {
                Response.Redirect("~/User/Login?ReturnUrl=Index");
            }

            return View("Index");
        }

        public ActionResult Logout()
        {
            FormsAuthentication.SignOut();
            return Redirect("~/Home");
        }

        public ActionResult Login()
        {
            // Stage 1: display login form to user
            return View("Login");
        }

        [ValidateInput(false)]
        public ActionResult Authenticate(string returnUrl)
        {
            var response = openid.GetResponse();
            if (response == null)
            {
                // Stage 2: user submitting Identifier
                Identifier id;
                if (Identifier.TryParse(Request.Form["openid_identifier"], out id))
                {
                    try
                    {
                        return openid.CreateRequest(Request.Form["openid_identifier"]).RedirectingResponse.AsActionResult();
                    }
                    catch (ProtocolException ex)
                    {
                        ViewData["Message"] = ex.Message;
                        return View("Login");
                    }
                }
                else
                {
                    ViewData["Message"] = "Invalid identifier";
                    return View("Login");
                }
            }
            else
            {
                // Stage 3: OpenID Provider sending assertion response
                switch (response.Status)
                {
                    case AuthenticationStatus.Authenticated:
                        Session["FriendlyIdentifier"] = response.FriendlyIdentifierForDisplay;
                        FormsAuthentication.SetAuthCookie(response.ClaimedIdentifier, false);
                        if (!string.IsNullOrEmpty(returnUrl))
                        {
                            return Redirect(returnUrl);
                        }
                        else
                        {
                            return RedirectToAction("Index", "Home");
                        }
                    case AuthenticationStatus.Canceled:
                        ViewData["Message"] = "Canceled at provider";
                        return View("Login");
                    case AuthenticationStatus.Failed:
                        ViewData["Message"] = response.Exception.Message;
                        return View("Login");
                }
            }
            return new EmptyResult();
        }
    }
}

Возможно, образец слишком прост, чтобы задействовать модель, так как вся информация о состоянии содержится в Cookie.Впоследствии я реализовал простую базу данных с единственной таблицей Users:

Users
+ user_id
+ open_id
+ last_login

Я предполагаю, что мне понадобится LoginModel:

public class LogInModel
{
    [Required]
    [DisplayName("OpenID")]
    public string OpenID { get; set; }
}

A DisplayModel:

public class DisplayModel
{
    [DisplayName("User ID")]
    public string UserID{ get; set; }

    [DisplayName("OpenID")]
    public string OpenID { get; set; }

    [DisplayName("Last Login")]
    public DateTime LastLogin{ get; set; }
}

Кроме того, мне может понадобиться ModifyModel, но DisplayModel можно использовать повторно и, возможно, переименовать в UserModel (чтобы правильно отразить использование модели).

Итак, теперь у меня есть несколько вопросов:

  1. Отвечает ли контроллер за проверку ввода пользователя или это делается, когда ввод передается в модель (т. Е. Вызывается Identifier.TryParse на openid_identifier)?
  2. Я хочу разрешить пользователю вход в систему, изменять его информацию (например, user_id) и просматривать их информацию (например, user_id, open_id и last_login).Сколько моделей мне нужно (ModifyModel, DisplayModel и LogInModel)?
  3. Каков срок службы модели?Модель существует где-то статически или она просто создана контроллером и передана в представление?
  4. Было бы лучше добавить базу данных в качестве модели вместо создания вышеуказанных моделей?

1 Ответ

2 голосов
/ 16 февраля 2011

1) Это может быть да, но лучшим подходом было бы использование Аннотации данных на ViewModel.

2) Подойдет одна модель.Модель должна представлять общий объект, в данном случае «Пользователь».Если информация, необходимая для каждого вида, сильно отличается, разделите их на модели вида.

3) Не совсем понятно, что вы имеете в виду.MVC (и ASP.NET в целом) основан на протоколе HTTP и, таким образом, не имеет состояния .Поэтому, когда вы нажимаете URL, назначается контроллер, а затем объекты обновляются, как того требует код - это включает соединение с базой данных.Затем, когда запрос завершен, все пропало (все равно управляемые ресурсы).Постарайтесь не запутаться со словом «модель».Это не физическая сущность, а область вашей модели программирования.

4) Как правило, вашей «моделью» является ваш репозиторий / DAL / ORM, который охватывает вашу базовую базу данных и представляет вашу модель домена .Ваше мнение не должно касаться домена.Это работа вашего контроллера / модели.Ваш вид должен работать с тем, что ему нужно, и не более.Вот почему, как правило, никогда не привязывается напрямую к модели ORM, используйте ViewModel.

Редактировать - в ответ на вопросы в комментариях:

Извините ... за 1, Аннотации данных предполагают, что проверка выполняется на модели, но также OpenId.Identifierпредоставляет некоторые функции, которые могут проверять ввод (например, TryParse), поэтому было бы более последовательным выполнять всю проверку на модели, или «место» проверки обычно не столь строгое?

Putаннотации данных в ViewModel , которые являются представлениями модели, созданной для облегчения представления.Аннотации данных не должны быть наложены на ваши сущности модели (Entity Framework, L2SQL и т. Д.).Аннотации данных должны использоваться для проверки ввода (сравнение паролей, длины символов, телефонных номеров, адресов электронной почты и т. Д.). Проверка бизнеса должна проводиться в домене.Я бы сказал, что OpenId - это сервис, а не часть домена.Если у них есть некоторые функции проверки, вы можете обернуть эти вызовы в пользовательские аннотации данных и поместить их в свою модель представления.Это был бы чистый и последовательный подход.

Для 3 я согласен с тем, что протокол HTTP не имеет состояния, но если я правильно понимаю, куки являются одним из способов поддержания состояния, а модель предоставляет альтернативный способ.,

Ваше право, куки - это один из способов сохранить состояние.Обычное использование для этого - билет проверки подлинности с помощью форм.Еще одна сессия. TempData использует сессию (умным способом - автоматический выброс).Модель не является «альтернативным способом» - она ​​не поддерживает состояние.Подробнее об этом поговорим ниже.

В прикладном программировании состояние (т. Е. Объект) обычно является постоянным на протяжении всего жизненного цикла приложения, поэтому, если бы мне пришлось создавать модель в консольном приложении, этосуществовать до тех пор, пока есть ссылка на него.Поэтому, когда вы говорите, что «объекты обновлены», это означает, что объект Model уже создан (как в консольном приложении), и я просто «обновляю» его, или это означает, что я создаю новую модель?

В консольном приложении - ваше право.Пока консольное приложение работает, объекты живы.Но в веб-приложении ASP.NET MVC «родителем» является рабочий поток ASP.NET, назначаемый при поступлении запроса. Все необходимые объекты (контроллер, соединение с базой данных, хранилище, объекты домена) являются «потомками»этот поток, если это имеет смысл.Как только этот поток исчезнет, ​​исчезнут все связанные объекты.

Опять не существует "волшебного воплощения" модели - модель представляет собой общее представление / представление вашего домена, которое обычно состоит из модели домена (сущности, бизнес-логика)и хранилище.

Единственное исключение - "привязка к модели". Когда вы отправляете форму для действия [HttpPost], которое строго типизировано для «модели» (должен быть ViewModel). ASP.NET MVC (через отражение) построит эту «модель» на основе полей в HTTP POST.

Когда вы делаете что-то вроде «UpdateModel», все, что вы делаете, это обновляет объект, который вы предоставляете, тем, что поступило в метод действия через привязку модели. Фактическая база данных не обновляется.

Не знаю, что еще я могу сказать. Похоже, у вас возникает путаница по поводу «модели». Могу я предложить вам взять книгу Стивена Сандерсона Pro ASP.NET MVC 2 Framework . Это фантастика, объясняет все с нуля - простыми словами, затем наращивает темп, чтобы стать экспертом к концу книги.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...