web-dev-qa-db-ja.com

ASP.NET Core 2、MVCなしのRazorページでのボタンクリック

誰かがコメントで指摘したように、MVCで行うのと同じように、Razorページにはコントローラーは必要ありません。また、Razorにはボタンクリックイベントのネイティブ処理がありません。ユーザーがボタンをクリックしたときに(「コードビハインド」で)何かを行うには、少なくとも2つのオプションがあります。

  • 送信ボタンを使用する
  • ajax呼び出しを使用する

コントローラー関数を定義する方法を示すMVCの例がたくさんあります。しかし、言ったように、私は持っていません。

したがって、私は両方の方法を理解しようとしています。ここで私のテストcshtml:

<form method="post">
    <input type="submit" class="btn btn-primary" value="way1">Way 1/>
</form>

<button id="btn" type="button" class="btn btn-primary" value="way2">Way 2</button>

<script>
$(document).ready(function() {
    $("#btn").click(function (e) {
        e.preventDefault();
        $.ajax({
            url: "@Url.Action("Way2")",
            type: "POST",
            data: "foo",
            datatype: "text",
            success: function (data) {
                alert(data);
            }
        });
        return false;
    });
});
</script>

そしてここにcshtml.cs:

パブリッククラスTestModel:PageModel {private readonly MyContext _context;

public TestModel(MyContext context)
{
    _context = context;
}

public IActionResult OnPost()
{
    // here I can put something to execute 
    // when the submit button is clicked
}

public ActionResult Way2(string data)
{
    // this is never triggered
}

ご質問

  1. 「Way1」(送信)を使用すると、ボタンのクリックをキャッチできますが、いくつかの欠点があります。デフォルトでは、投稿のためにページがリロードされます。時々、何も変更する必要はなく、C#関数を呼び出すだけです。しかし、複数のボタンを処理する方法がわかりません。つまり5つのボタンがある場合、それぞれに異なる方法を実行するにはどうすればよいですか?

  2. 「Way2」では、csコードの関数に到達できず、Bad Requestエラー(400)が発生するため、何か間違ったことをしました。私は何を取りこぼしたか?

8
Mark

通常のフォーム送信

通常のフォーム送信を行う場合、慣例に従って、On{{HttpVerb}}{{YourHanderName}}形式に従うハンドラーメソッド名が必要です。

public ActionResult OnPostWay2(string data)
{
    // to do : return something
}

formタグ内に送信ボタンがあり、asp-page-handlerに言及していることを確認してください。その属性の値は、ページモデルクラスのハンドラー名である必要があります(Way2

<form method="POST">       
    <button type="submit" asp-route-data="foo" asp-page-handler="Way2">Way 2</button>
</form>

上記のコードは、url yourBaseUrl/YourPageName?data=foo&handler=Way2に設定されている formaction属性 でボタンのマークアップを生成します。ユーザーが送信ボタンをクリックすると、formaction属性値がフォームのデフォルトアクションURLをオーバーライドするため、このURLをフォームにポストします。リクエストを受信すると、razor pagesフレームワークはこのパラメーター(handler)を使用し、対応するハンドラーメソッドにリクエストを送信します。

Ajax呼び出し

フレームワークは、送信されたリクエストデータの一部としてRequestVerificationTokenを予期しているため、400(Bad Request)応答を取得しています。ページの表示ソースを確認すると、フォーム内に__RequestVerificationTokenという名前の非表示の入力要素が表示されます。フレームワークはこれを使用して、起こり得るCSRF攻撃を防ぎます。リクエストにこの情報がない場合、フレームワークは400の不正なリクエストを返します。

Ajaxコードを機能させるには、これを明示的に送信するだけです。これが実際のサンプルです

$("#btn").click(function(e) {
    e.preventDefault();

    var t = $("input[name='__RequestVerificationToken']").val();
    $.ajax({
        url: $(this).attr("formaction"),
        headers:
        {
            "RequestVerificationToken": t
        },
        type: "POST",
        data: { data: 'foo2' },
    }).done(function(data) {
        console.log(data);
    }).fail(function(a, v, e) {
        alert(e);
    });
});

これでajax呼び出しを行っているので、json応答を返すのが理にかなっています

public ActionResult OnPostWay2(string data)
{
    return new JsonResult("Received "+ data + " at "+DateTime.Now);        
}

上記の例では、jQueryコードを使用して__RequestVerificationTokenという名前の入力要素を取得し、その値を読み取ります。より堅牢なアプローチは、ビューにIAntiforgery実装を挿入し、GetAndStoreTokensメソッドを使用することです。

@inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Xsrf
@functions{
    public string GetAntiXsrfRequestToken()
    {
        return Xsrf.GetAndStoreTokens(Model.HttpContext).RequestToken;
    }
}
<script>
     $(function () {

         $("#btn").click(function(e) {
             e.preventDefault();
             var t = '@GetAntiXsrfRequestToken()';
             $.ajax({
                      url: $(this).attr("formaction"),
                      headers:
                      {
                          "RequestVerificationToken": t
                      },
                      type: "POST",
                      data: { data: 'foo2' },
             }).done(function(data) {
                     console.log(data);
             }).fail(function(a, v, e) {
                     alert(e);
             });
         });
    })
</script>
11
Shyju