我正在尝试在主页面中找到一种优雅的登录表单方式。这意味着除非用户登录,否则登录表单应出现在每个页面上。 (这些日子很常见)
以Visual Studio中的MVC2应用程序为例,我创建了这个:
public class MasterViewModel
{
public string User { get; set; } // omitted validation attributes
public string Pass{ get; set; }
public bool RememberMe { get; set; }
}
每个视图模型都继承自MasterViewModel
public class RegisterViewModel : MasterViewModel
{
public string UserName { get; set; }
public string Email { get; set; }
public string Password { get; set; }
public string ConfirmPassword { get; set; }
}
我的母版页呈现部分视图
<%@ Master Language="C#" Inherits="System.Web.Mvc.ViewMasterPage<MyLogon.ViewModels.MasterViewModel>" %>
.....
<div id="logindisplay">
<% Html.RenderPartial("LogOn"); %>
</div>
......
强类型局部视图:
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<MyLogon.ViewModels.MasterViewModel>" %>
<%
if (Request.IsAuthenticated) {
%>
Welcome <b><%= Html.Encode(Page.User.Identity.Name) %></b>!
<div>[ <%= Html.ActionLink("Change Password", "ChangePassword", "Account") %> ]</div>
<div>[ <%= Html.ActionLink("Log Off", "LogOff", "Account") %> ]</div>
<%
}
else {
%>
<%= Html.ValidationSummary(true, "Login was unsuccessful. Please correct the errors and try again.") %>
<% using (Html.BeginForm("LogOn", "Account",FormMethod.Post)) { %>
<div>
<fieldset>
<legend>Account Information</legend>
<div class="editor-label">
<%= Html.LabelFor(m => m.User) %>
</div>
<div class="editor-field">
<%= Html.TextBoxFor(m => m.User) %>
<%= Html.ValidationMessageFor(m => m.User) %>
</div>
<div class="editor-label">
<%= Html.LabelFor(m => m.Pass) %>
</div>
<div class="editor-field">
<%= Html.PasswordFor(m => m.Pass) %>
<%= Html.ValidationMessageFor(m => m.Pass) %>
</div>
<div class="editor-label">
<%= Html.CheckBoxFor(m => m.RememberMe) %>
<%= Html.LabelFor(m => m.RememberMe) %>
</div>
<p>
<input type="submit" value="Log On" />
</p>
</fieldset>
</div>
<% } %>
<%
}
%>
注册页面:
<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<MyLogon.Models.RegisterViewModel>" %>
...
<h2>Create a New Account</h2>
<p>
Use the form below to create a new account.
</p>
<p>
Passwords are required to be a minimum of <%= Html.Encode(ViewData["PasswordLength"]) %> characters in length.
</p>
<% using (Html.BeginForm("Register", "Account" ,FormMethod.Post))
{ %>
<%= Html.ValidationSummary(true, "Account creation was unsuccessful. Please correct the errors and try again.") %>
<div>
<fieldset>
<legend>Account Information</legend>
<div class="editor-label">
<%= Html.LabelFor(m => m.UserName) %>
</div>
<div class="editor-field">
<%= Html.TextBoxFor(m => m.UserName) %>
<%= Html.ValidationMessageFor(m => m.UserName) %>
</div>
<div class="editor-label">
<%= Html.LabelFor(m => m.Email) %>
</div>
<div class="editor-field">
<%= Html.TextBoxFor(m => m.Email) %>
<%= Html.ValidationMessageFor(m => m.Email) %>
</div>
<div class="editor-label">
<%= Html.LabelFor(m => m.Password) %>
</div>
<div class="editor-field">
<%= Html.PasswordFor(m => m.Password) %>
<%= Html.ValidationMessageFor(m => m.Password) %>
</div>
<div class="editor-label">
<%= Html.LabelFor(m => m.ConfirmPassword) %>
</div>
<div class="editor-field">
<%= Html.PasswordFor(m => m.ConfirmPassword) %>
<%= Html.ValidationMessageFor(m => m.ConfirmPassword) %>
</div>
<p>
<input type="submit" value="Register" />
</p>
</fieldset>
</div>
<% } %>
</asp:Content>
由于所有视图模型都继承自MasterViewModel LogOn局部视图总是得到满足,但我发现这个解决方案非常不优雅。还有其他方法可以达到这个目的吗?
答案 0 :(得分:2)
按原样使用局部视图,但根据登录状态具有不同的视图。将具有登录表单/ lunk的匿名用户的一个视图返回到注册页面,并为登录用户返回第二个视图。
部分视图可以有自己的模型,不需要从主视图模型继承。
继承模型可能会导致以后出现问题(这会使html.EditForModel()
或.DisplayForModel()
变得棘手,因为它们也会渲染公共主视图字段。)
哦,一般来说,视图依赖于模型之外的任何东西都是不好的做法 - 你对Request.IsAuthenticated
的测试现在可能没问题,但如果你想要绝对正确,你应该有一个{{ 1}}由action设置的属性。也就是说,切换视图将完全消除这个问题。
编辑:最后一项改进。在这样的行上:
model.IsAuthenticated
取而代之的是:
Welcome <b><%= Html.Encode(Page.User.Identity.Name) %></b>!
实际上更好的方法是只打出模型:
Welcome <b><%: Page.User.Identity.Name %></b>!
(请注意Welcome <b><%: model.Username %></b>!
而非<%:
)。这种形式的标记表示内容应该是HTML编码的。更好的是,如果它遇到<%=
,它将对其进行编码。如果遇到string
,则不会。所有.Net MVC函数都会根据需要返回字符串或HTML字符串,以便您可以执行此操作:
HTMLString
第一个不会被html编码,因为<%: html.EditFor(x => x.fieldname) %>
<%: model.somefield %>
会返回EditFor()
。第二个将被编码(如果HTMLString
是标准字符串)
这将使您的代码更整洁,更健壮。您也可以使用它来动态生成HTML,并且必须对其进行编码/不适当。例如,我们有一些辅助函数来处理包括CSS / JS。他们返回HTMLStrings ......
somefield