web-dev-qa-db-ja.com

例AJAX ASP.NET Core Razorページへのコールバック

ページに複数のハンドラーがあり、関連する命名規則(つまりOnPostXXX)と 'asp-post-hanlder'タグヘルパーがある例を見つけました。しかし、AJAX呼び出しからこれらのメソッドの1つを呼び出す方法を教えてください。

典型的なMVCビューとコントローラーを持つ古い例がありますが、これはRazorページでどのように機能しますか?

たとえば、ベースアプリケーションを取得して、About.cshtmlページを次のように変更したとします。

@page
@model AboutModel
@{
    ViewData["Title"] = "About";
}
<h2>@ViewData["Title"]</h2>
<h3>@Model.Message</h3>

    <input type="button" value="Ajax test" class="btn btn-default" onclick="ajaxTest();"  />

@section Scripts {
<script type="text/javascript">
    function ajaxTest() {
        console.log("Entered method");
        $.ajax({
            type: "POST",
            url: '/About', // <-- Where should this point?
            contentType: "application/json; charset=utf-8",
            dataType: "json",
        error: function (xhr, status, errorThrown) {
            var err = "Status: " + status + " " + errorThrown;
            console.log(err);
        }
        }).done(function (data) {
            console.log(data.result);
        })
    }
</script>
}

そしてモデルページAbout.cshtml.cs

public class AboutModel : PageModel
{
    public string Message { get; set; }

    public void OnGet()
    {
        Message = "Your application description page.";
    }

    public IActionResult OnPost() {
        //throw new Exception("stop");
        return new JsonResult("");
    }
}

OnPostはAjax呼び出しから呼び出されません。

5
Brad Patton

Razor Pagesは、Antiforgeryトークンを自動的に生成して検証し、 [〜#〜] csrf [〜#〜] 攻撃を防止します。 AJAXコールバック内でトークンを送信していないため、リクエストは失敗します。

この問題を解決するには、次のことを行う必要があります。

  1. 偽造防止サービスを登録する
  2. リクエストにトークンを追加する
  3. <form>を追加するか、@Html.AntiForgeryToken HtmlHelperを直接使用して、偽造防止トークンをページに追加します

1. Startup.csにAntiforgery-Serviceを登録します

public void ConfigureServices(IServiceCollection services)
{
  services.AddRazorPages();
  services.AddAntiforgery(o => o.HeaderName = "XSRF-TOKEN");
}

2. AJAXコールバックを変更します

AJAXコールバックに、リクエストヘッダーとともにXSRF-TOKENを送信するためのコードを追加します。

$.ajax({
    type: "POST",
    url: '/?handler=YOUR_CUSTOM_HANDLER', // Replace YOUR_CUSTOM_HANDLER with your handler.
    contentType: "application/json; charset=utf-8",

    beforeSend: function (xhr) {
      xhr.setRequestHeader("XSRF-TOKEN",
        $('input:hidden[name="__RequestVerificationToken"]').val());
    },

    dataType: "json"
}).done(function (data) {
  console.log(data.result);
})

3.偽造防止トークンをページに追加します

これは、<form>を追加することで実現できます。

<form method="post">
    <input type="button" value="Ajax test" class="btn btn-default" onclick="ajaxTest();" />
</form>

または@Html.AntiForgeryTokenを使用して:

@Html.AntiForgeryToken()
<input type="button" value="Ajax test" class="btn btn-default" onclick="ajaxTest();" />

どちらの場合も、Razorページは、ページが読み込まれると、偽造防止トークンを含む非表示の入力フィールドを自動的に追加します。

<input name="__RequestVerificationToken" type="hidden" value="THE_TOKEN_VALUE" />
13
causita

ドキュメントのこの関連セクションを参照してください https://docs.Microsoft.com/en-us/aspnet/core/mvc/razor-pages/?tabs=visual-studio

ページへのURLパスの関連付けは、ファイルシステム内のページの場所によって決まります。次の表は、Razorページのパスと一致するURLを示しています

/Pages/Index.cshtmlは/または/ Indexにマップします

/Pages/Contact.cshtmlは/ Contactにマップします

1
Greg

上記の回答を確認した後、Visual Studio 2017プレビュー2を使用して.NET Core 2.1 RazorページでJSON ajaxを使用できるようにしました。

Startup.cs

services.AddAntiforgery(o => o.HeaderName = "XSRF-TOKEN");

PostJson.cshtml

@page
@model myProj.Pages.PostJsonModel
@{
    ViewData["Title"] = "PostJson";
}

<input type="button" value="Post Json" class="btn btn-default" onclick="postJson();" />

<script>
    function ajaxRazorPostJson(o) {
        return $.ajax({
            type: "POST",
            data: JSON.stringify(o),
            url: 'postJson',
            contentType: "application/json; charset=utf-8",
            beforeSend: function (xhr) { xhr.setRequestHeader("XSRF-TOKEN", $('input:hidden[name="__RequestVerificationToken"]').val()); },
            dataType: "json"
        });
    }

    function postJson() {
        ajaxRazorPostJson({ reqKey: "reqVal" }).done(data => alert(data));
    }
</script>

PostJson.cshtml.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Newtonsoft.Json.Linq;    

namespace myProj.Pages
{
    public class PostJsonModel : PageModel
    {
        public IActionResult OnPost([FromBody] JObject jobject)
        {
            // request buffer in jobject
            return new ContentResult { Content = "{ \"resKey\": \"resVal\" }", ContentType = "application/json" };
            // or ie return new JsonResult(obj);
        }
    }
}

ブラウザ

http:// localhost:44322/postJson

1
kofifus

承認されたソリューションはローカルの開発マシンで機能しましたが、失敗してNginxリバースプロキシの背後にあるDebianサーバーにデプロイされました(404エラーが見つかりません)。

これは、ペイロードデータの実際の例です。

<script type="text/javascript">
    $('#btnPost').on('click', function () {

        var payloadData; /*asign payload data here */

        $.post({              /* method name in code behind, and full path to my view*/
            url: '@Url.Action("OnPostAsync", "/Turtas/Inventorius/InventoriausValdymas")', 
            beforeSend: function (xhr) {
                xhr.setRequestHeader("XSRF-TOKEN",
                    $('input:hidden[name="__RequestVerificationToken"]').val());
            },
            data: JSON.stringify({ payloadData }),
            contentType: "application/json; charset=utf-8",
            dataType: "json"
        })
    })
</script>

VS 2017; .Net Core 2.2 Razorページ; jQuery 3.3.1

0
Exc1t4r

以下はheaders設定を使用してASP.NET Core MVC 3.1で動作します:

$.ajax({
    type: "POST",
    url: '/Controller/Action', 
    data: {
        id: 'value'
    },
    headers: {
        RequestVerificationToken:
            $('input:hidden[name="__RequestVerificationToken"]').val()
    },
    error: function (xhr, status, errorThrown) {
        var err = "Error: " + status + " " + errorThrown;
        console.log(err);
    }
}).done(function (data) {
    console.log(data.result);
});

コントローラーメソッドにValidateAntiForgeryToken属性を含める:

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<JsonResult> Action(string id)
    {
        var result = $"You sent '{id}'";
        return Json(new { id, result });
    }
0
Doug Dekker

すべてうまくいきますが、いくつかの変更を行う必要があります。

1)Startup.csを開きます。

public void ConfigureServices(IServiceCollection services)
        {
            services.AddAntiforgery(o => o.HeaderName = "XSRF-TOKEN");
            services.AddMvc();
        }

2)HomeController.csを開きます。

[ValidateAntiForgeryToken]
        public IActionResult OnPost()
        {
            return new JsonResult("Hello Response Back");
        }

3)About.cshtmlを開きます。

@{
    ViewData["Title"] = "About";
}
<h2>@ViewData["Title"]</h2>
<h3>@ViewData["Message"]</h3>

<p>Use this area to provide additional information.</p>
<form method="post">
    <input type="button" value="Ajax test" class="btn btn-default" onclick="ajaxTest();" />
</form>

<script src="~/lib/jquery/dist/jquery.js"></script>

<script type="text/javascript">
    function ajaxTest() {
        $.ajax({
            type: "POST",
            url: 'onPost',
            contentType: "application/json; charset=utf-8",
            beforeSend: function (xhr) {
                xhr.setRequestHeader("XSRF-TOKEN",
                    $('input:hidden[name="__RequestVerificationToken"]').val());
            },
            dataType: "json"
        }).done(function (data) {
            console.log(data.result);
        })
    }
</script>

「onPost」がコントローラ内に追加されたことに注意する必要があるため、AJAX=には正しい「url」を指定する必要があります。次に、

url: 'onPost',
0
piedatt80

答えは私には有効です。次のようにページでメソッドをカスタマイズした場合にのみ追加します。

   public IActionResult OnPostFilter1()
    {
        return new JsonResult("Hello Response Back");
    }

次に、ハンドラ名をURLで指定する必要があります。

url: 'OnPost?handler=filter1',
0
Nije Vazno