什么是在MVC模式的组件的责任简单的登录 [英] What are the responsibilities of the components in an MVC pattern for a simple login

查看:189
本文介绍了什么是在MVC模式的组件的责任简单的登录的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想了解MVC模式,我得到的总体思路,该模型是负责维护状态,视图是负责显示模型和控制器是负责修改模型并调用相应的View (多个)。我想尝试并实现使用一个简单的ASP.NET MVC的登录页面的OpenID,以获得怎样一些了解这一切的作品。



我已经下载 DotNetOpenAuth -3.4.6 ,我一直在寻找通过样品,特别是他们的MVC样本。不幸的是,样品实际上并没有一个模型中,只有一个控制器:

 命名空间OpenIdRelyingPartyMvc.Controllers 
$ { b $ b按系统;
使用System.Collections.Generic;
使用System.Linq的;
使用的System.Web;
使用System.Web.Mvc;
使用System.Web.Security;
使用DotNetOpenAuth.Messaging;
使用DotNetOpenAuth.OpenId;
使用DotNetOpenAuth.OpenId.RelyingParty;

公共类UserController的:控制器
{
私有静态OpenIdRelyingParty的OpenID =新OpenIdRelyingParty();

公众的ActionResult指数()
{
如果(!User.Identity.IsAuthenticated)
{
的Response.Redirect(〜/用户/登录?RETURNURL =指数);
}

返回查看(「指数」);
}

公众的ActionResult退出()
{
FormsAuthentication.SignOut();
返回重定向(〜/家庭);
}

公众的ActionResult登录()
{
//第1步:显示登录表单用户
返回视图(登录);
}

[ValidateInput(假)]
公众的ActionResult进行身份验证(字符串RETURNURL)
{
VAR响应= openid.GetResponse();
如果(响应== NULL)
{
//第2阶段:用户提交标识符
标识ID;
如果(Identifier.TryParse(的Request.Form [openid_identifier],掉id))
{

{
返回openid.CreateRequest(的Request.Form [openid_identifier])RedirectingResponse.AsActionResult();
}
赶上(前的ProtocolException)
{
计算机[消息] = ex.Message;
返回视图(登录);
}
}
,否则
{
计算机[消息] =无效的标识符
返回视图(登录);
}
}
,否则
{
//第3阶段:OpenID提供者发出声明响应
开关(response.Status)
$ { b $ b情况下AuthenticationStatus.Authenticated:
会话[FriendlyIdentifier] = response.FriendlyIdentifierForDisplay;
FormsAuthentication.SetAuthCookie(response.ClaimedIdentifier,FALSE); (!string.IsNullOrEmpty(RETURNURL))
如果
{
返回重定向(RETURNURL);
}
,否则
{
返回RedirectToAction(指数,家);
}
情况下AuthenticationStatus.Canceled:
计算机[消息] =在供应商取消;
返回视图(登录);
情况下AuthenticationStatus.Failed:
计算机[消息] = response.Exception.Message;
返回视图(登录);
}
}
返回新EmptyResult();
}
}
}



也许样品过于简单实际上涉及一个模型,因为所有的状态信息被包含Cookie的范围内。随后,我实现它有一个用户表一个简单的数据库:

 用户
+ USER_ID
+ open_id
+ LAST_LOGIN

我相信,我需要一个 LoginModel

 公共类LogInModel 
{
[必填]
〔显示名称(OpenID的)]
公共字符串的OpenID {搞定;组; }
}



A DisplayModel

 公共类DisplayModel 
{
[显示名称(用户ID)]
公共字符串用户名{获得;组; }

[DisplayName的(OpenID的)]
公共字符串的OpenID {搞定;组; }

[DisplayName的(上次登录)]
公众的DateTime LastLogin {搞定;组; }
}

此外,我可能需要一个 ModifyModel ,而 DisplayModel 可重复使用,并可能重命名为的usermodel (正确反映使用该模型)



所以,现在我有几个问题:




  1. 是控制器负责验证用户输入或当输入传递给模型(即调用 Identifier.TryParse openid_identifier )?

  2. 我想允许用户登录,改变自己的信息(即USER_ID),并查看他们的信息(即USER_ID,open_id和LAST_LOGIN)。多少款,我需要( ModifyModel DisplayModel LogInModel )?

  3. 什么是模式的生命周期?是否静态模型存在的地方,或者它只是由控制器创建并传递给视图?

  4. 它会更好,添加的数据库作为模型而不是使上述模型

$ b? $ b
解决方案

1),这可能是肯定的,但更好的方法是使用数据注释的视图模型。



2)一个模型就行了。模型应代表一个整体对象,在这种情况下,用户。如果每个视图所需要的信息相差很大,那么它们分开出到视图模型。



3)不知道你的意思。 MVC(和ASP.NET一般)是基于HTTP协议,并且因此<青霉>无国籍的。所以,当你打一个网址,一个控制器分配,那么对象newed起来的代码需要它 - 这包括数据库连接。然后,当请求完成后,一切都过去了(管理资源反正)。尽量不要混淆字模式。这不是一个物理实体,而您的编程模型的区域。



4)一般来说,你的模式是你的存储库/ DAL / ORM,它包装基础数据库,并代表你的域模型的。您查看的不应该是关注的领域。那是你的控制器/型号的工作。您认为应该用它需要什么,并没有更多的工作。这就是为什么作为一个经验法则,从不直接绑定到一个ORM模型,使用一个ViewModel。






编辑 - 回应评论中的问题:




对不起...... 1,数据注释的建议是对模型进行了验证,但OpenId.Identifier还提供了一些功能,可以验证输入(例如的TryParse),所以它会比较一致的做所有的验证型号或者说是地方验证通常不那么严格?




把数据注释的视图模型这是交涉模型创建,使生活更轻松的查看。数据注释不应该在您的实际模型实体(实体框架,L2SQL等)付诸表决。数据注释应使用的输入验证的(密码相比较,文字,电话号码,电子邮件地址长度等)。的业务验证的,应在域中完成。我会说,OpenID是域的服务,而不是一部分。如果他们有一些验证功能,你可以在包装定制数据注解这些电话,并把它们放在你的视图模型。这将是一个干净的和一致的方法。




有关3,我同意HTTP协议是无状态的,但如果我理解正确饼干单程保持状态和模型提供的另一种方法。




您的权利,饼干是:维护国家的一种方式。一个常见的用途是在窗体身份验证票。另一个是会话。 的TempData 的使用会话(在一个聪明的方式 - 自动弹出)。该模型是不是替代方法 - 它不维护状态。要多讨论低于




在应用程序的状态(即一个对象)通常是整个应用程序的生命周期持久的,所以如果我是创建一个控制台应用程序模型,将存在,只要有它的参考。因此,当你说的对象是newed,这是否意味着(在一个控制台应用程序等)Model对象已经被实例化,我只是更新,或是否意味着我建立一个新的模式?




在一个控制台应用程序 - 你的权利。只要控制台应用程序运行时,对象是活的。但是,在一个ASP.NET MVC的Web应用程序,父是一个ASP.NET工作者线程,当一个请求到达指定所有所需的对象(控制器,数据库连接,存储库,域对象)的是孩子这个线程,如果是有道理的。一旦该线程已经一去不复返了,所以是所有相关的对象。



有没有神奇的实例化的模式,再一次 - 在型号是您的域,它通常包括一个总体视图/表示的域模型(实体,业务逻辑)和存储库。



一个例外是模型绑定。当你提交一个表单到正在强类型为样板的 [HttpPost] 动作(应该是一个视图模型)。 ASP.NET MVC(通过反射)将构建基于HTTP POST领域的这种模式。



当你做这样的事情的UpdateModel,所有这些都是做的是更新您提供通过模型结合了后来进入行动方法的对象。没有实际的数据库正在更新。



不知道我能说什么。您似乎有关于模特的困惑。愿我建议你抢史蒂芬·桑德森的 临ASP.NET MVC 2 Framework的拷贝 的书。这太棒了,解释一切从地上爬起来 - 简单地说,然后斜了脚步让你在书的结尾专家


I'm trying to understand the MVC pattern and I get the general idea that the Model is responsible for maintaining the state, the View is responsible for displaying the Model and the Controller is responsible for modifying the Model and calling the appropriate View(s). I wanted to try and implement a simple ASP.NET MVC login page that uses OpenID in order to get some understanding of how it all works.

I've downloaded DotNetOpenAuth-3.4.6 and I was looking through the samples, specifically their MVC sample. Unfortunately, the sample doesn't actually have a model, only a controller:

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();
        }
    }
}

Perhaps the sample is too simple to actually involve a model, since all of the state information is contained within the Cookie. Subsequently, I've implemented a simple database which has a single Users table:

Users
+ user_id
+ open_id
+ last_login

I presume that I would need a 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; }
}

Additionally, I may need a ModifyModel, but the DisplayModel can be reused and possibly renamed to UserModel (to properly reflect the use of the model).

So now I have several questions:

  1. Is the controller responsible for verifying user input or is that done when the input is passed to the model (i.e. calling Identifier.TryParse on the openid_identifier)?
  2. I want to allow the user login, change their information (i.e. the user_id) and view their information (i.e. user_id, open_id and last_login). How many models do I need (ModifyModel, DisplayModel and LogInModel)?
  3. What is the lifetime of a model? Does the model exist somewhere statically or is it just created by the controller and passed to the view?
  4. Would it be better to add the database as a model instead of making the above models?

解决方案

1) It could be yes, but a better approach would be to use Data Annotations on the ViewModel.

2) One model will do. A model should represent an overall object, in this case a "User". If the information required for each View differs greatly, then seperate them out into View Models.

3) Not sure what you mean. MVC (and ASP.NET in general) is based on the HTTP protocol, and is thus stateless. So when you hit a URL, a Controller is assigned, then objects are newed up as the code requires it - this includes a database connection. Then when the request is finished, everything is gone (managed resources anyway). Try not to get confused with the word "model". It's not a physical entity, rather an area of your programming model.

4) Generally, your "model" is your Repository/DAL/ORM, which wraps your underlying database, and represents your domain model. Your View's shouldn't be concerned with the domain. That is the job of your Controller/Model. Your View should work with what it needs, and no more. This is why as a rule of thumb, never bind directly to an ORM model, use a ViewModel.


Edit - in response to questions in comments:

I'm sorry... for 1, Data Annotations suggest the validation is performed on the model, but OpenId.Identifier also provides some functions that can validate input (e.g. TryParse), so would it be more consistent to do all of the validation on the model or is the "place" of validation usually not that strict?

Put the Data Annotations on the ViewModel which are representations of the Model created to make life easier for the View. Data Annotations should not be put on your actual model entities (Entity Framework, L2SQL, etc). Data Annotations should be used for input validation (password comparing, length of characters, phone numbers, email addresses, etc). Business Validation should be done in the domain. I would say that OpenId is a service and not part of the domain. If they have some validation functions, you could wrap those calls in custom data annotations and place them on your ViewModel. That would be a clean and consistent approach.

For 3, I agree that the HTTP protocol is stateless, but if I understand correctly cookies are one way to maintain a state and the model provides an alternate way.

Your right, cookies are one way to maintain state. A common use for this is the Forms Authentication ticket. Another one is session. TempData uses Session (in a smart way - automatic ejection). The model is not an "alternate way" - it does not maintain state. Will talk more about that below.

In application programming a state (i.e. an object) is usually persistent throughout the lifetime of the application, so if I were to create a Model in a console app it would exist for as long as there is a reference to it. So when you say that the "objects are newed," does that mean that the Model object is already instantiated (like in a console app) and I just "update" it or does that mean that I construct a new Model?

In a console app - your right. As long as the console application is running, the objects are alive. But in a ASP.NET MVC Web Application, the "parent" is a ASP.NET Worker Thread, assigned when a request comes in. All of the required objects (controller, database connection, repository, domain objects) are "children" of this thread, if that makes sense. Once that thread is gone, so is all the related objects.

There is no "magic instantiation" of the model, again - the Model is an overall view/representation of your domain, which usually consists of the domain model (entities, business logic) and the repository.

The one exception is "model-binding". When you submit a Form to an [HttpPost] action that is strongly-typed to a "model" (should be a ViewModel). ASP.NET MVC (via reflection) will construct this "model" based on the fields in the HTTP POST.

When you do things like "UpdateModel", all that is doing is updating an object you supply with what came into the action method via the model binding. No actual database is being updated.

Don't know what else i can say. You seem to be having confusion about the "model". May i suggest you grab a copy of Steven Sanderson's Pro ASP.NET MVC 2 Framework book. It's fantastic, explains everything from the ground up - in simple terms, then ramps up the pace so your an expert by the end of the book.

这篇关于什么是在MVC模式的组件的责任简单的登录的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆