MVC 模式中简单登录的组件职责是什么

2024-01-10

我试图理解 MVC 模式,我得到的一般想法是模型负责维护状态,视图负责显示模型,控制器负责修改模型并调用适当的视图。我想尝试实现一个简单的 ASP.NET MVC 登录页面,该页面使用OpenID http://www.openid.net以便了解这一切是如何运作的。

我已经下载了DotNetOpenAuth-3.4.6 http://www.dotnetopenauth.net/tag/contributor/我正在查看示例,特别是他们的 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
+ 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 on the openid_identifier)?
  2. 我想允许用户登录、更改其信息(即 user_id)并查看其信息(即 user_id、open_id 和 last_login)。我需要多少型号(ModifyModel, DisplayModel and LogInModel)?
  3. 模型的生命周期是多长?模型是否静态存在于某处,或者只是由控制器创建并传递给视图?
  4. 最好添加一下而不是制作上述模型?

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

2) 一种模型就可以了。模型应该代表一个整体对象,在本例中是“用户”。如果每个视图所需的信息差异很大,则将它们分成视图模型。

3)不知道你的意思。 MVC(以及一般的 ASP.NET)基于 HTTP 协议,因此无国籍的。因此,当您点击 URL 时,就会分配一个控制器,然后根据代码的需要更新对象 - 这包括数据库连接。然后,当请求完成时,一切都消失了(无论如何托管资源)。尽量不要与“模型”这个词混淆。它不是一个物理实体,而是编程模型的一个区域。

4)一般来说,你的“模型”是你的Repository/DAL/ORM,它包装了你的底层数据库,代表了你的领域模型。您的视图不应该与域有关。这是你的控制器/模型的工作。您的视图应该满足其需要,仅此而已。这就是为什么根据经验,永远不要直接绑定到 ORM 模型,而是使用 ViewModel。

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

抱歉...对于1,数据注释建议在模型上执行验证,但是 OpenId.Identifier 还提供了一些可以验证输入的函数(例如 TryParse),因此执行所有验证会更加一致在模型上或者验证的“地点”通常不那么严格吗?

将数据注释放在视图模型它们是为使视图的生活更轻松而创建的模型的表示。数据注释不应放在实际模型实体(实体框架、L2SQL 等)上。数据注释应该用于输入验证(密码比较、字符长度、电话号码、电子邮件地址等)。业务验证应该在域中完成。我想说 OpenId 是一项服务,而不是域的一部分。如果它们有一些验证函数,您可以将这些调用包装在自定义数据注释中并将它们放置在您的 ViewModel 上。这将是一种干净且一致的方法。

对于 3,我同意 HTTP 协议是无状态的,但如果我理解正确的话,cookie 是维护状态的一种方法,并且该模型提供了另一种方法。

你说得对,cookie 是维护状态的一种方式。其常见用途是表单身份验证票证。另一种是会话。TempData使用Session(以一种聪明的方式——自动弹出)。该模型不是一种“替代方式”——它不维护状态。下面将详细讨论这一点。

在应用程序编程中,状态(即对象)通常在应用程序的整个生命周期中是持久的,因此,如果我要在控制台应用程序中创建模型,那么只要存在对它的引用,它就会存在。因此,当您说“对象是新的”时,这是否意味着模型对象已经实例化(就像在控制台应用程序中一样)并且我只是“更新”它,或者这是否意味着我构造了一个新模型?

在控制台应用程序中 - 你的权利。只要控制台应用程序正在运行,对象就处于活动状态。但在 ASP.NET MVC Web 应用程序中,“父级”是 ASP.NET 工作线程,在收到请求时分配。所有必需的对象(控制器、数据库连接、存储库、域对象)都是 ASP.NET 工作线程的“子级”这个线程,如果有道理的话。一旦该线程消失,所有相关对象也消失。

再次强调,模型没有“神奇的实例化”Model是域的整体视图/表示,通常由域模型(实体、业务逻辑)和存储库组成。

一个例外是“模型绑定”。当您将表格提交给[HttpPost]强类型化为“模型”的操作(应该是 ViewModel)。 ASP.NET MVC(通过反射)将根据 HTTP POST 中的字段构建此“模型”。

当您执行“UpdateModel”之类的操作时,所做的就是更新您通过模型绑定进入操作方法所提供的对象。没有实际的数据库正在更新。

不知道我还能说什么。您似乎对“模型”感到困惑。我可以建议你拿一本史蒂文·桑德森的书吗专业 ASP.NET MVC 2 框架 http://apress.com/book/view/1430228865书。这太棒了,从头到尾解释了一切——用简单的术语,然后加快步伐,这样你在本书结束时就成为了专家。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

MVC 模式中简单登录的组件职责是什么 的相关文章

随机推荐

  • PHP。为什么日期对象的月份差异在 12 个月后重置为 0?

    今天是 2015 年 7 月 8 日 当我运行以下命令时它返回0 如果不返回12 日期是12个月前 同样如果 date 2014 06 03 它返回1 难道不是吗13 过去 12 个月内的所有日期均已正确计算 date 2014 07 03
  • wwwroot 之外的 Elmah logPath

    我们正在尝试部署我们的项目 但我们无法让 elmah 在 wwwroot 之外创建 xml 日志 它当前正在记录到 inetpub site wwwroot App Data 因为这是唯一可行的路径 我们希望将其记录到我们的 inetpub
  • Java:使用引用游标作为 OUT 调用存储过程时结果集为空

    我试图从 Java 调用存储过程 但返回的结果始终是false 实际上 它必须返回 100 条记录 连接建立良好 我有一个存储过程 PROCEDURE get records grp1 IN a name TYPE DEFAULT NULL
  • 使用 PHP 将带有换行符的字符串分解为 HTML 段落

    我从 MySQL 数据库获取文本 该文本被分成行 段落 它存储在变量中 post data content 如何使其打印时带有换行符 我当前使用的代码 post data content explode n post data conten
  • 退出 Putty 后如何保持 Spring Boot 应用程序处于活动状态

    我正在通过命令使用 putty 在我的服务器上运行我的 spring boot 应用程序 mvn spring boot run 仅当我打开 ssh 会话时才运行 断开会话后是否可以使应用程序保持活动状态 或者我是否必须制作可执行的 war
  • g++ 编译另一个目录中存在的源文件

    我正在尝试使用 makefile 为我正在开发的 C 插件设置构建过程 我很好奇是否有任何方法可以让 g 编译source在另一个目录中找到的文件 我这样做的动机是避免为每个源文件指定相对路径 正如我在下面解释的那样 我的项目目录结构如下
  • wpf 工具提示 - 设置跨应用程序的持续时间

    我可以在单个控制工具提示上设置属性 例如持续时间 但我需要的是为整个应用程序中的所有工具提示设置更长的持续时间 所有窗口 所有用户控件等 有没有任何干净的方法来实现它 谢谢 您可以覆盖元数据ToolTipService ShowDurati
  • 为什么我不能将 python 的 print 分配给变量?

    我正在学习编程 并使用 Python 开始 在那里 我发现我可以做这样的事情 gt gt gt gt def myFunction return 1 gt gt gt gt test myFunction gt gt gt gt test
  • 通过 Python 在 Excel 中创建切片器对象

    我正在尝试使用 python 中的 XLwings 包在 Excel 工作表中重新创建一些 tableau 功能 具体来说 我编写了一个脚本 用于处理来自 SQl Server 的数据并执行一些聚合 统计函数 其输出是 pandas 数据帧
  • 将字符串转换为自定义日期格式 - C# razor

    我有一个存储事件的 mySQL 数据库 并且这些事件都有日期 我正在提取事件日期 它们以字符串形式在 HTML 中输出 ul IEntity latestEvents ViewBag LatestEvents foreach IEntity
  • Python Selenium 单击可见元素

    使用 Python Selenium 我试图检查一个元素是否可见 然后单击它 如果是 Check to see if element is visible myelement driver find element by xpath a i
  • PowerShell 自定义提供程序RemoveItem

    我正在实施一个自定义电源外壳 http en wikipedia org wiki Windows PowerShell提供者 我现在正在研究remove item cmdlet 实现 RemoveItem 方法具有以下签名 protect
  • Angular Abstract 控件删除错误

    我想要一种从表单控件中删除特定错误而不是清除所有错误的方法 control setError firstError true 并删除该特定错误 例如 control removeError firstError and not contro
  • Javascript 在 dom 内移动时失去与 flash 的通信

    Actionscript 内的代码 var methodName4 String startupload var instance4 Object null var method4 Function startupload var wasS
  • Facebook 图形 API 不会返回用户的所有帖子

    我正在尝试通过 Facebook 图形 API 获取所有用户帖子 但永远无法得到全部 当我通过路径 me posts 参数限制 5000 尝试它时 我得到了用户写的所有帖子 就像我想要的那样 但不是在特定日期之前 意思是 这样我就不会在特定
  • iPhone 上令人困惑的内存分配错误

    你好 我正在开发一个 iPhone 应用程序 它提供图像和文本信息 每个文本中都有一个图像 可以单击和缩放 用 UIImageView 显示 NSString imgName imgPath substringToIndex imgPath
  • javafx FXML Canvas 绘制后为空

    我正在使用 Intellij IDEA 进行 javafx FXML 开发 我使用以下代码简单地绘制了一个矩形 然而 它从未出现过 主程序 java public class Main extends Application Overrid
  • 当结果依赖于前面的单元格时,如何将函数应用于数组的每个元素

    我有一个数组 a np array 2 3 5 8 3 5 计算每个结果元素所在数组的最有效 向量化 方法是什么 伪代码 result 0 a 0 for i gt 0 result i result i 1 a i result i 1
  • Node js http服务器请求正文作为流可读

    我正在使用 node js 编写一个 http 服务器 但无法将请求正文隔离为可读的流 这是我的代码的基本示例 var http require http fs require fs http createServer function r
  • MVC 模式中简单登录的组件职责是什么

    我试图理解 MVC 模式 我得到的一般想法是模型负责维护状态 视图负责显示模型 控制器负责修改模型并调用适当的视图 我想尝试实现一个简单的 ASP NET MVC 登录页面 该页面使用OpenID http www openid net以便