4

マスターページにログインフォームを表示するエレガントな方法を見つけようとしています。つまり、ユーザーがログインしない限り、すべてのページにログイン フォームが表示されます。(これは最近非常に一般的です)

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 から継承されるため、部分ビューは常に満足されますが、このソリューションは非常に洗練されていません。これを達成する他の方法はありますか?

4

1 に答える 1

2

部分ビューをそのまま使用しますが、ログイン状態によってビューが異なります。ログインフォーム/ランクを持つ匿名ユーザーの1つのビューを登録ページに戻し、ログインしたユーザーの2番目のビューを返します。

部分ビューは、マスタービューモデルから継承する必要のない独自のモデルを持つことができます。

モデルを継承すると、後で問題が発生する可能性があります(共通のマスタービューフィールドもレンダリングされるため、使用する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>!

<%:( notに注意してください<%=)。この形式のタグは、コンテンツがHTMLでエンコードされている必要があることを示します。さらに良いのは、が発生した場合stringにそれをエンコードすることです。に遭遇した場合HTMLString、それは発生しません。すべての.NetMVC関数は、必要に応じて文字列またはHTML文字列を返すため、次のことができます。

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

EditFor()最初のものは、を返すようにhtmlエンコードされませんHTMLString。2番目はエンコードされます(somefield標準文字列の場合)

これにより、コードがよりすっきりと堅牢になります。また、これを使用して、必要に応じてHTMLを動的に生成し、エンコードする/適切でないようにすることもできます。たとえば、CSS/JSを含むいくつかのヘルパー関数を処理できます。HTMLStringsを返します...

<%: Helper.IncludeCSS("SomeCSS.css") %>
于 2010-11-15T21:35:06.717 に答える