母版页中的 ASP.NET MVC2 登录表单

发布于 2024-10-02 05:30:20 字数 5698 浏览 0 评论 0原文

我正在尝试找到一种在母版页中包含登录表单的优雅方式。这意味着除非用户登录,否则登录表单应该出现在每个页面上。 (这在现在很常见)

以 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 部分视图总是令人满意,但我发现这个解决方案非常不优雅。还有其他方法可以实现这一目标吗?

I'm trying to find an elegant way of having login form in the master page. That means unless user logs in, login form should appear on every page. (This is very common these days)

Taking the example that comes with MVC2 Application in Visual Studio I have created this:

public class MasterViewModel
{
    public string User { get; set; } // omitted validation attributes
    public string Pass{ get; set; }
    public bool RememberMe { get; set; }
}

Every view model inherits from 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; }
}

My master page renders partial view

<%@ Master Language="C#" Inherits="System.Web.Mvc.ViewMasterPage<MyLogon.ViewModels.MasterViewModel>" %>
.....
            <div id="logindisplay">
                <% Html.RenderPartial("LogOn"); %>
            </div> 
......

Strongly-typed partial view:

<%@ 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>
        <% } %>
    <%
        }
    %>

Register page:

<%@ 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>

Since all view models inherit from MasterViewModel LogOn partial view is always satisfied but I'm finding this solution very inelegant. Is there any other way to achieve this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

行至春深 2024-10-09 05:30:20

按原样使用部分视图,但根据登录状态有不同的视图。为匿名用户返回一个视图,并带有注册页面的登录表单/链接,为登录用户返回第二个视图。

部分视图可以有自己的模型,不需要从主视图模型继承。

继承模型可能会在以后引起问题(这使得使用 html.EditForModel().DisplayForModel() 变得棘手,因为它们也会渲染公共主视图字段)。

哦,一般来说,视图依赖于模型之外的任何东西都是不好的做法 - 您对 Request.IsAuthenticated 的测试目前可能没问题,但如果您想绝对正确,您应该有一个由操作设置的 model.IsAuthenticated 属性。也就是说,切换视图将完全消除这个问题。

编辑:最后一项改进。在这样的行上:

Welcome <b><%= Html.Encode(Page.User.Identity.Name) %></b>!

相反,这样做:

Welcome <b><%: Page.User.Identity.Name %></b>!

实际上更好的是只命中模型:(

Welcome <b><%: model.Username %></b>!

注意 <%: 而不是 <%=)。这种形式的标签表明内容应该是 HTML 编码的。更好的是,如果它遇到字符串,它就会对其进行编码。如果它遇到 HTMLString,则不会。所有 .Net MVC 函数都会根据需要返回字符串或 HTML 字符串,因此您可以执行以下操作:

<%: html.EditFor(x => x.fieldname) %>
<%: model.somefield %>

第一个不会进行 html 编码,因为 EditFor() 返回 HTMLString。第二个将被编码(如果 somefield 是标准字符串)

这将使您的代码更整洁、更健壮。如果需要的话,您还可以使用它动态生成 HTML,并对其进行编码/不适当编码。例如,我们有一些辅助函数要处理,包括 CSS/JS。他们返回 HTMLStrings...

<%: Helper.IncludeCSS("SomeCSS.css") %>

Use a partial view as you are but have different views based on the logged in status. Return one view for anonymous users with a login form/lunk to the register page and a second view for logged in users.

Partial views can have their own models which do not need to inherit from the master view model.

Inheriting models can cause problems later (It makes using html.EditForModel() or .DisplayForModel() tricky as they will render the common master view fields too).

Oh and in general, it's bad practice for the view to rely on anything outside the model - your test on Request.IsAuthenticated may be fine for now but if you want to be absolutely correct, you should have a model.IsAuthenticated property which is set by the action. That said, switching views will obviate this problem entirely.

Edit: One last improvement. On lines like this one:

Welcome <b><%= Html.Encode(Page.User.Identity.Name) %></b>!

Instead do:

Welcome <b><%: Page.User.Identity.Name %></b>!

Actually even better would be to only hit the model:

Welcome <b><%: model.Username %></b>!

(Note the <%: not <%=). This form of tag indicates that the contents should be HTML-encoded. What's even better is that if it encounters a string, it will encode it. If it encounters an HTMLString, it won't. All the .Net MVC functions return string or HTML string as appropriate so you can do this:

<%: html.EditFor(x => x.fieldname) %>
<%: model.somefield %>

The first will NOT be html encoded as EditFor() returns an HTMLString. The second WILL be encoded (if somefield is a standard string)

This will make your code both neater and more robust. You can also use this to dynamically generate HTML should you have to and have it encoded/not as appropriate. Eg we have some helper functions to handle including CSS/JS. They return HTMLStrings...

<%: Helper.IncludeCSS("SomeCSS.css") %>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文