ページに複数のハンドラーがあり、関連する命名規則(つまり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呼び出しから呼び出されません。
Razor Pagesは、Antiforgeryトークンを自動的に生成して検証し、 [〜#〜] csrf [〜#〜] 攻撃を防止します。 AJAXコールバック内でトークンを送信していないため、リクエストは失敗します。
この問題を解決するには、次のことを行う必要があります。
<form>
を追加するか、@Html.AntiForgeryToken
HtmlHelperを直接使用して、偽造防止トークンをページに追加しますStartup.cs
にAntiforgery-Serviceを登録しますpublic void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddAntiforgery(o => o.HeaderName = "XSRF-TOKEN");
}
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);
})
これは、<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" />
ドキュメントのこの関連セクションを参照してください 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にマップします
上記の回答を確認した後、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);
}
}
}
ブラウザ
承認されたソリューションはローカルの開発マシンで機能しましたが、失敗して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
以下は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 });
}
すべてうまくいきますが、いくつかの変更を行う必要があります。
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',
答えは私には有効です。次のようにページでメソッドをカスタマイズした場合にのみ追加します。
public IActionResult OnPostFilter1()
{
return new JsonResult("Hello Response Back");
}
次に、ハンドラ名をURLで指定する必要があります。
url: 'OnPost?handler=filter1',