我正在尝试理解MVC模式,我得到了模型负责维护状态的一般概念,View负责显示模型,Controller负责修改模型并调用相应的View (S)。我想尝试实现一个使用OpenID的简单ASP.NET MVC登录页面,以便了解它是如何工作的。
我已经下载了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
(以正确反映模型的使用情况)。
所以现在我有几个问题:
Identifier.TryParse
上调用openid_identifier
)?ModifyModel
,DisplayModel
和LogInModel
)?答案 0 :(得分:2)
1)可能是肯定的,但更好的方法是在ViewModel上使用数据注释。
2)一个模型会做。模型应表示整体对象,在本例中为“用户”。如果每个视图所需的信息差异很大,则将它们分离到View Models中。
3)不确定你的意思。 MVC(和ASP.NET一般)基于HTTP协议,因此无状态。因此,当您点击URL时,会分配一个Controller,然后在代码需要时添加对象 - 这包括数据库连接。然后,当请求完成后,一切都消失了(无论如何都是托管资源)。尽量不要与“模特”这个词混淆。它不是物理实体,而是编程模型的一个区域。
4)通常,您的“模型”是您的Repository / DAL / ORM,它包装您的基础数据库,并代表您的域模型。您的视图不应该关注域。这是您的控制器/模型的工作。您的View应该可以满足它的需求,而不再需要。这就是为什么根据经验,永远不会直接绑定到ORM模型,使用ViewModel。
对不起......对于1,数据注释表明验证是在模型上执行的,但是OpenId.Identifier还提供了一些可以验证输入的函数(例如TryParse),因此它可以更加一致地完成所有操作对模型进行验证还是验证的“地点”通常不是那么严格?
将数据注释放在 ViewModel 上,这些是创建的模型的表示,以使View更加轻松。数据注释不应放在您的实际模型实体(实体框架,L2SQL等)上。数据注释应该用于输入验证(密码比较,字符长度,电话号码,电子邮件地址等)。 业务验证应在域中完成。我会说OpenId是一种服务而不是域的一部分。如果他们有一些验证功能,您可以将这些调用包装在自定义数据注释中,并将它们放在ViewModel上。这将是一个干净和一致的方法。
对于3,我同意HTTP协议是无状态的,但如果我理解正确,cookie是维持状态的一种方式,而模型提供了另一种方式。
你的权利,cookie是维持状态的一种方式。常见的用途是Forms身份验证票证。另一个是会议。 TempData 使用Session(以智能方式 - 自动弹出)。该模型不是“替代方式” - 它不维持状态。将在下面详细讨论。
在应用程序编程中,状态(即对象)通常在应用程序的整个生命周期中都是持久的,因此如果我要在控制台应用程序中创建模型,只要存在对它的引用,它就会存在。所以当你说“对象是新的”时,这是否意味着Model对象已经被实例化(比如在控制台应用程序中)而我只是“更新”它或者这是否意味着我构建了一个新模型?
在控制台应用中 - 您的权利。只要控制台应用程序正在运行,对象就会处于活动状态。但是在ASP.NET MVC Web应用程序中,“父”是一个ASP.NET工作线程,在请求进入时分配。所有必需的对象(控制器,数据库连接,存储库,域对象)都是“子”。这个线程,如果这是有道理的。一旦该线程消失,所有相关对象也都消失了。
模型没有“神奇的实例化” - 模型是您域的整体视图/表示,通常由域模型(实体,业务逻辑)和库。
唯一的例外是“模型绑定”。当您将表单提交到强类型为“模型”的[HttpPost]
操作时(应该是ViewModel)。 ASP.NET MVC(通过反射)将基于HTTP POST中的字段构建此“模型”。
当您执行“UpdateModel”之类的操作时,所做的就是通过模型绑定更新您提供的操作方法中提供的对象。没有实际的数据库正在更新。
不知道我还能说些什么。你似乎对“模特”感到困惑。我建议你抓一本Steven Sanderson的 Pro ASP.NET MVC 2 Framework 一书。它太棒了,从头开始解释所有内容 - 简单来说,然后加快速度,这样你的专家就会在本书的最后。