1

質問をする前に、この演習の目的は研究/概念実証であることを明確にさせてください。そのため、設計を改善する方法や、これを達成するためのより簡単な方法についての回答は高く評価されていますが、目的を達成するのに役立たない可能性があります。 .

ASP .Net MVC 4 アプリケーションのテンプレートを変更しているため、ログイン コントロールを含む部分ビューのみを更新し、ページの残りの部分はそのままにしておく ajax 要求でログイン機能が実装されます。

これまでのところ、私が行ったことは次のとおりです。

部分ビューにフォームを追加して、投稿してアクション リンクをボタンに置​​き換えられるようにしました。

@using (Html.BeginForm("Login", "Account", FormMethod.Post, new { ReturnUrl = ViewBag.ReturnUrl }))
{
    @Html.ValidationSummary(true)

    if (Request.IsAuthenticated)
     {
         <p>
             Hello, @Html.ActionLink(User.Identity.Name, "ChangePassword", "Account", routeValues: null, htmlAttributes: new {@class = "username", title = "Change password"})!
             @Html.ActionLink("Log off", "LogOff", "Account")
         </p>
     }
     else
     {
         <ul>
             <li>@Html.LabelFor(m => m.UserName)</li>
             <li>@Html.TextBoxFor(m => m.UserName)</li>
             <li>@Html.LabelFor(m => m.Password)</li>
             <li>@Html.PasswordFor(m => m.Password)</li>
             <li><input class="loginLink loginButton" type="button" value="Log in"/></li>
             <li>@Html.ActionLink("Register", "Register", "Account", routeValues: null, htmlAttributes: new {id = "registerLink"})</li>
         </ul>
     }
}

アクションを次のように変更しました

[AllowAnonymous]
[HttpPost]
public ActionResult Login(LoginModel model, string returnUrl)
{
    ActionResult result = View("_LoginPartial", model);

    if (ModelState.IsValid)
    {
        if (Membership.ValidateUser(model.UserName, model.Password))
        {
            FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
            if (Url.IsLocalUrl(returnUrl))
            {
                result = Redirect(returnUrl);
            }
            else
            {
                result = View("_LoginPartial", model);
            }
        }
        else
        {
            ModelState.AddModelError("", "The user name or password provided is incorrect.");
        }
    }

    return result;
}

そして、私はこの小さなJavascriptファイルを作成しました

var login = {
    callLogin: function () {
        var userName = $("#UserName").val();
        var password = $("#Password").val();

        var data = { UserName: userName, Password: password };
        $("#login").load("/Account/Login", data);
    }
};

$(document).ready(function () {
    $(".loginButton").click(login.callLogin);
});

ログイン自体は機能します。POST アクション メソッドが呼び出され、資格情報が検証されます。問題は、部分ビューが更新されていないことです。ユーザーがログインしているかのように部分ビューを表示できるように、別のページに移動して投稿を強制的に戻す必要があります。

これを達成するために不足している要素は何でしょうか?

ありがとうございました。

4

3 に答える 3

1

2 つの考えられる問題/解決策:

  1. の ID を持つ要素はありませんlogin- フォームにその ID があることを確認するか、div でラップしてください。
  2. .loadへの呼び出しで url パラメータの一部としてセレクターを渡し$("section").load("/Account/Login #login", data)ますdata
  3. Firebug などを使用してネットワーク トラフィックを検査し、POST が行われており、部分的なレンダリングが返されていることを確認します。
  4. より手動のアプローチにフォールバックします。
    $.ajax("/Account/Login", { data: data, type: 'POST', dataType: 'html' }).done(function(result) { $("#login").empty().append(result); });

編集:

ただし、ログイン試行が成功した後に部分ビューのみを返す場合、これが機能しない理由を知りたいです。

交換されている HTTP ヘッダーを注意深く調べると、そのログイン部分ビューを取得するための最初の呼び出しが、予想される 401 (属性なしで許可されていない) ではなく、ログイン ページとともに 200 (OK) になることが[AllowAnonymous]わかります。したがって、応答 HTML は期待した部分ではなく、完全な HTML ドキュメントです。ただし、スクリプトはそれに気付かず、通常どおり続行します。これを修正するには、認証されていないリクエストに対するアプリの応答方法を変更する必要があります。できることはたくさんありますが、幸運なことに、Phil Haack が少し前にブログでそれらについて説明しています。彼の投稿はここにあります。

于 2012-08-16T21:05:21.497 に答える
0

理想的ではありませんが、本当にクールだと答えてください。

コントローラーを少し変更する必要があることがわかりました。

[AllowAnonymous]
[HttpPost]
public ActionResult Login(LoginModel model, string returnUrl)
{
    ActionResult result = View("_LoginPartial", model);

    if (ModelState.IsValid)
    {
        if (Membership.ValidateUser(model.UserName, model.Password))
        {
            FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
            if (Url.IsLocalUrl(returnUrl))
            {
                result = Redirect(returnUrl);
            }
            else
            {
                //This is the only difference from the original action
                result = RedirectToAction("Index", "Home");
            }
        }
        else
        {
            ModelState.AddModelError("", "The user name or password provided is incorrect.");
        }
    }

    return result;
}

唯一の違いは、認証が成功した場合に RedirectToAction("index", "Home") を呼び出すことができ、パーシャルが正しく更新されることです。

これはクールで理想的ではない部分です。これが機能する理由は、RedirectToAction メソッドが完全な Index ビューを返しているにもかかわらず、私が興味を持っている部分には「フォーム」要素があり、jQuery ロードに「フォーム」セレクターを含めるという Josh の提案のおかげであるためです。メソッドでは、完全な Index ビューのうち、_LoginPartial ビューのみが "login" 要素に読み込まれます。

これは理想的ではないと思います。大量の不要な HTML が返されて破棄され、かなりのオーバーヘッドが発生するからです。また、これはそれほど悪くはありません。返された「Index」ビューがたまたま別の場所に独自のフォームを持っている場合、2 つのフォームが「login」要素に読み込まれます。これは、より具体的なセレクターを配置することで簡単に解決できます。ロード方法。

ただし、ログイン試行が成功した後に部分ビューのみを返す場合、これが機能しない理由を知りたいです。

于 2012-08-16T22:02:05.247 に答える
0

ajax 呼び出しは、表示する必要がある html コンテンツを返す必要があり、負荷を適用する要素は、そのコンテンツが ajax 応答に置き換えられる要素である必要があります。

load をあまり使用していないため ($.post を優先して)、load が何をするかを見逃していたと思いますが、それでも、アクションは View(Model) を返す必要があります。RedirectToAction は、そのアクションのビューをレンダリングする (したがって、html コンテンツを返す) アクションにリダイレクトするため、同じことを行います。

于 2012-08-16T21:26:48.290 に答える