AJAX 回调到 ASP.NET Core Razor 页面的示例
Example AJAX call back to an ASP.NET Core Razor Page
我找到了在一个页面上有多个处理程序以及关联的命名约定(即 OnPostXXX)和 'asp-post-hanlder' 标签助手的示例。但是如何从 AJAX 调用中调用这些方法之一。
我有一个带有典型 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("");
}
}
Ajax 调用未调用 OnPost。
请参阅文档的相关部分
https://docs.microsoft.com/en-us/aspnet/core/mvc/razor-pages/?tabs=visual-studio
The associations of URL paths to pages are determined by the page's location in the file system. The following table shows a Razor Page path and the matching URL
/Pages/Index.cshtml 映射到 / 或 /Index
/Pages/Contact.cshtml 映射到 /Contact
Razor Pages 自动生成并验证防伪令牌以防止 CSRF 攻击。由于您没有在 AJAX 回调中发送任何令牌,因此请求失败。
要解决此问题,您必须:
- 注册Antiforgery-Service
- 将令牌添加到您的请求中
- 通过添加
<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 回调中,我们添加了额外的代码以通过我们的请求 header.
发送 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 Pages 都会在页面加载后自动添加包含防伪标记的隐藏输入字段:
<input name="__RequestVerificationToken" type="hidden" value="THE_TOKEN_VALUE" />
一切正常,但必须进行一些更改:
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',
看了上面的答案后,我 JSON ajax 使用 Visual Studio 2017 预览版 2 来处理 .NET Core 2.1 Razor 页面:
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 剃刀页面; jQuery3.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 });
}
我为后代添加这个。
争论同样的问题,我发现以下代码可以添加到 Startup.cs:
services.AddRazorPages().AddRazorPagesOptions(options =>
{
options.Conventions.ConfigureFilter(new IgnoreAntiforgeryTokenAttribute());
});
不再需要防伪令牌。
我找到了在一个页面上有多个处理程序以及关联的命名约定(即 OnPostXXX)和 'asp-post-hanlder' 标签助手的示例。但是如何从 AJAX 调用中调用这些方法之一。
我有一个带有典型 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("");
}
}
Ajax 调用未调用 OnPost。
请参阅文档的相关部分 https://docs.microsoft.com/en-us/aspnet/core/mvc/razor-pages/?tabs=visual-studio
The associations of URL paths to pages are determined by the page's location in the file system. The following table shows a Razor Page path and the matching URL
/Pages/Index.cshtml 映射到 / 或 /Index
/Pages/Contact.cshtml 映射到 /Contact
Razor Pages 自动生成并验证防伪令牌以防止 CSRF 攻击。由于您没有在 AJAX 回调中发送任何令牌,因此请求失败。
要解决此问题,您必须:
- 注册Antiforgery-Service
- 将令牌添加到您的请求中
- 通过添加
<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 回调中,我们添加了额外的代码以通过我们的请求 header.
发送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 Pages 都会在页面加载后自动添加包含防伪标记的隐藏输入字段:
<input name="__RequestVerificationToken" type="hidden" value="THE_TOKEN_VALUE" />
一切正常,但必须进行一些更改:
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',
看了上面的答案后,我 JSON ajax 使用 Visual Studio 2017 预览版 2 来处理 .NET Core 2.1 Razor 页面:
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 剃刀页面; jQuery3.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 });
}
我为后代添加这个。 争论同样的问题,我发现以下代码可以添加到 Startup.cs:
services.AddRazorPages().AddRazorPagesOptions(options =>
{
options.Conventions.ConfigureFilter(new IgnoreAntiforgeryTokenAttribute());
});
不再需要防伪令牌。