ASP.NET MVC2 Форма входа на главной странице - PullRequest
4 голосов
/ 15 ноября 2010

Я пытаюсь найти элегантный способ иметь форму входа на главной странице.Это означает, что если пользователь не вошел в систему, форма входа должна появиться на каждой странице.(Это очень распространено в наши дни)

Используя пример, который поставляется с приложением MVC2 в Visual Studio, я создал это:

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 частичное представление всегда выполняется, но я нахожу это решение очень не элегантным.Есть ли другой способ добиться этого?

1 Ответ

2 голосов
/ 16 ноября 2010

Используйте частичное представление, как есть, но разные представления в зависимости от статуса входа в систему. Вернуть одно представление для анонимных пользователей с формой входа / ланком на страницу регистрации и второе представление для зарегистрированных пользователей.

Частичные представления могут иметь свои собственные модели, которые не должны наследоваться от модели основного вида.

Наследование моделей может вызвать проблемы позже (это делает использование 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. Еще лучше то, что если он встречает string, он его кодирует. Если он встречает HTMLString, он не будет. Все функции .Net MVC возвращают строку или строку HTML в зависимости от ситуации, поэтому вы можете сделать это:

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

Первый НЕ будет кодироваться в формате html, так как EditFor() возвращает HTMLString. Второй будет закодирован (если somefield является стандартной строкой)

Это сделает ваш код более аккуратным и надежным. Вы также можете использовать это для динамической генерации HTML, если вам нужно, и закодировать его / не так, как нужно. Например, у нас есть несколько вспомогательных функций для обработки, включая CSS / JS. Они возвращают HTMLStrings ...

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