使用 AJAX 删除 Razor 页面
Razor Pages delete using AJAX
我正在尝试将 AJAX 与 Razor Pages 结合使用。
我一直在网上搜索,但我发现的每个示例都有所不同,而且大多数不完整或不适用于 Razor Pages。
到目前为止,我一直在关注类似这样的变体:
$.post('/?handler=Delete', 5, function (x) {
alert(x);
});
然后我的页面模型如下所示:
public void OnPostDelete(int id)
{
}
我已经尝试过对此的变体,但到目前为止,我的 C# 代码没有被调用。
问题:
- 有人可以告诉我我缺少什么吗?
- 有人可以为此提供一些好的参考吗? (我还需要执行其他 AJAX 任务。)
- 我发现的一些示例具有与防伪令牌相关的特殊处理。我是否也需要为此编写代码?
更新:
所以我一直在研究这个,这就是我现在所拥有的:
$.ajax({
url: '?handler=Delete',
data: {
id: $(this).data('id')
}
})
.fail(function (e) {
// Error
alert(e.responseText); // Way too much info
})
.done(function () {
// Success
})
.always(function () {
// Always
});
我的经纪人:
public void OnGetDelete(int id)
{
}
这实际上是在调用我的处理程序,我终于让它传递了 id
参数。
由于我有赏金,以下是我希望在答案中看到的内容:
- 如果我将 AJAX 调用设置为使用 POST 并将我的处理程序重命名为
OnPostDelete()
,则不会调用该处理程序。我该怎么做 post?
- 对上述代码还有其他建议或批评吗?我知道有很多方法可以做到这一点。我只是在寻找最简单的方法并尝试改进它。
两条建议:
1-在url前面加上页面路径。 (我不确定你的话里有没有提到)。
$.post('/{page_path}/?handler=Delete', 5, function (x) {
alert(x);
});
2- 遵循路由映射规则。例如,您的函数中有 'id' 。该页面可能配置为@page "{id:int}"。所以 url 应该是
$.post('/{page_path}/{id}/?handler=Delete', 5, function (x) {
alert(x);
});
您可以通过 F12 在“网络”选项卡中检查请求,您可能会看到 400 bad request 错误。
Razor 页面旨在自动保护免受 cross-site 请求伪造 (CSRF/XSRF) 攻击。您不必编写任何额外的代码。防伪令牌生成和验证自动包含在 Razor Pages 中。这里请求失败,页面上没有 AntiForgeryToken。
对于问题,您可以使用 @Html.AntiForgeryToken()
明确添加
要添加 AntiForgeryToken,我们可以使用任何一种方法。这两种方法都添加了一个隐藏的输入类型,名称为 __RequestVerificationToken。 Ajax 请求应将请求 header 中的 anti-forgery 令牌发送到服务器。所以,修改后的 Ajax 请求看起来像
@Html.AntiForgeryToken()
@section Scripts
{
<script>
$.ajax({
type: "POST",
url: "/?handler=Delete&id="+5,
beforeSend: function (xhr) {
xhr.setRequestHeader("XSRF-TOKEN",
$('input:hidden[name="__RequestVerificationToken"]').val());
},
success: function (x) {
alert(x);
},
failure: function (response) {
alert(response);
}
});
</script>
}
由于脚本在名为 X-CSRF-TOKEN 的 header 中发送令牌,因此配置防伪服务以查找 X-CSRF-TOKEN header:
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddAntiforgery(o => o.HeaderName = "XSRF-TOKEN");
}
参考:https://www.talkingdotnet.com/handle-ajax-requests-in-asp-net-core-razor-pages/
这就是我喜欢的方式:
配置您的 Javascript
//If you're returning a object, configure it
var yourObject = {
field1: "value1",
field2: "value2"
};
//setup ajax
$.ajax({
data: yourObject,
type: "POST",
url: "urltoyourhandler/delete" //you can add other paramters here as well by doing ?parm=value
success: function(data){
//do success stuff here
//based off my handler code below:
if(data.success){
console.log("Success!");
}
else{
console.log("Failed for some reason!");
}
}
error: function(){
//do error stuff here
//gets called if there is a issue contacting the URL or if there is a server error like 500
}
});
正在配置您的处理程序。对于我的 CRUD 操作,我喜欢制作一个 CRUD 控制器来处理所有事情
[BindProperty]
public YourClass Name { get; set; }
//set handler to only accept POST and set a URL for it. URL should be to the same folder you're in
//the 'delete' in route doesn't have to match the function name but it's less confusing if it does
[HttpPost, Route("RouteToThisHandler/delete)]
public async Task<IActionResult> Delete()
{
//verify data and the do something with it
//I like returning a JsonResult. Add whatever data you want. I like returning success
//with true or false and some other data if needed
return new JsonResult(new { success: true, importantInfo: "This is important" });
}
Ajax 有更多配置选项,可为您提供有关发生的任何服务器错误的更多信息
对于防伪令牌,微软表示:
Antiforgery middleware is added to the Dependency injection container
when one of the following APIs is called in Startup.ConfigureServices:
- AddMvc
- MapRazorPages
- MapControllerRoute
- MapBlazorHub
这里是微软link关于防伪令牌的:https://docs.microsoft.com/en-us/aspnet/core/security/anti-request-forgery?view=aspnetcore-3.1
我调查了一些事情,当你从 AJAX 传递一个字符串而不是一个整数时会发生什么,以及不同的路由如何影响调用(如果你有时间,请参阅下面有趣的注释)但主要是,我所发现的只是 Razor Pages 相当宽容,一切似乎都能正常工作。就像我提到的,即使传递一个字符串,其中整数类型 id
仍然命中处理程序方法(它只是给了我一个 default(int)
)
我创建这个 repo 只是为了探索:https://github.com/EntityAdam/RazorPageHandlers
正如@Yan 指出的那样,主要的障碍是防伪令牌。这确实是导致处理程序未命中断点的唯一原因。正如建议的那样,检查您的网络选项卡是否有失败的请求或控制台是否有错误 JavaScript 代码。
从您的代码片段中,要将其更改为 OnPostDelete
,您需要在 AJAX 调用中使用 POST
类型并包含防伪标记。
$.ajax({
type: 'POST',
headers: { "RequestVerificationToken": $('input[name="__RequestVerificationToken"]').val() },
url: '?handler=Delete',
data: {
id: $(this).data('id')
}
})
.fail(function (e) {
// Error
alert(e.responseText); // Way too much info
})
.done(function () {
// Success
})
.always(function () {
// Always
});
另一个我没有看到讨论的话题是这个令牌来自哪里?只要有 <form>
元素,它就会由 Razor 自动生成。如果您没有 <form>
元素,您可以在需要时生成标记,查看此 MSDN Article 中的 @functions {}
块。在某些情况下,CSRF 无用或不需要,如果不需要,您也可以关闭防伪造(这是一个完全不同的讨论)。
我对这种方法的批评是意见,所以要么接受要么放弃。
- 如果可以避免使用 jQuery,前提是 JavaScript 的改进可以说已经过时 jQuery。使用普通的 JS 代码。
- Ajax 也显示了它的年龄。如果您只需要支持现代浏览器,请考虑 Fetch API
- 完全不写任何JS! Blazor 是新的,闪亮的。仍然有一些成长的烦恼,但我宁愿我的痛苦在 C# 中而不是在 JavaScript =)
我遇到的一件有趣的事..
对于这个演示,我使用了以下 @page
指令
@page "{id?}"
在 HTML 部分的表格如:
<form method="post" asp-page-handler="Delete">
<input type="hidden" name="id" value="1" />
<button class="btn btn-danger">Delete</button>
</form>
我正在使用 asp-page-handler
标签助手来帮助生成正确的 URL。对于 Create 处理程序,使用 @page
指令,标签助手提出了 /?handler=Create
的表单目标
如果您用 @page "{handler?}/{id:int?}"
替换掉 @page 指令,标签助手会计算出现在的路由 /Delete
。但猜猜怎么了? AJAX 调用与任一 @page
指令一起工作,即使 AJAX 中的 URL 被硬编码为 ?handler=Delete'
我正在尝试将 AJAX 与 Razor Pages 结合使用。
我一直在网上搜索,但我发现的每个示例都有所不同,而且大多数不完整或不适用于 Razor Pages。
到目前为止,我一直在关注类似这样的变体:
$.post('/?handler=Delete', 5, function (x) {
alert(x);
});
然后我的页面模型如下所示:
public void OnPostDelete(int id)
{
}
我已经尝试过对此的变体,但到目前为止,我的 C# 代码没有被调用。
问题:
- 有人可以告诉我我缺少什么吗?
- 有人可以为此提供一些好的参考吗? (我还需要执行其他 AJAX 任务。)
- 我发现的一些示例具有与防伪令牌相关的特殊处理。我是否也需要为此编写代码?
更新:
所以我一直在研究这个,这就是我现在所拥有的:
$.ajax({
url: '?handler=Delete',
data: {
id: $(this).data('id')
}
})
.fail(function (e) {
// Error
alert(e.responseText); // Way too much info
})
.done(function () {
// Success
})
.always(function () {
// Always
});
我的经纪人:
public void OnGetDelete(int id)
{
}
这实际上是在调用我的处理程序,我终于让它传递了 id
参数。
由于我有赏金,以下是我希望在答案中看到的内容:
- 如果我将 AJAX 调用设置为使用 POST 并将我的处理程序重命名为
OnPostDelete()
,则不会调用该处理程序。我该怎么做 post? - 对上述代码还有其他建议或批评吗?我知道有很多方法可以做到这一点。我只是在寻找最简单的方法并尝试改进它。
两条建议:
1-在url前面加上页面路径。 (我不确定你的话里有没有提到)。
$.post('/{page_path}/?handler=Delete', 5, function (x) {
alert(x);
});
2- 遵循路由映射规则。例如,您的函数中有 'id' 。该页面可能配置为@page "{id:int}"。所以 url 应该是
$.post('/{page_path}/{id}/?handler=Delete', 5, function (x) {
alert(x);
});
您可以通过 F12 在“网络”选项卡中检查请求,您可能会看到 400 bad request 错误。
Razor 页面旨在自动保护免受 cross-site 请求伪造 (CSRF/XSRF) 攻击。您不必编写任何额外的代码。防伪令牌生成和验证自动包含在 Razor Pages 中。这里请求失败,页面上没有 AntiForgeryToken。
对于问题,您可以使用 @Html.AntiForgeryToken()
明确添加
要添加 AntiForgeryToken,我们可以使用任何一种方法。这两种方法都添加了一个隐藏的输入类型,名称为 __RequestVerificationToken。 Ajax 请求应将请求 header 中的 anti-forgery 令牌发送到服务器。所以,修改后的 Ajax 请求看起来像
@Html.AntiForgeryToken()
@section Scripts
{
<script>
$.ajax({
type: "POST",
url: "/?handler=Delete&id="+5,
beforeSend: function (xhr) {
xhr.setRequestHeader("XSRF-TOKEN",
$('input:hidden[name="__RequestVerificationToken"]').val());
},
success: function (x) {
alert(x);
},
failure: function (response) {
alert(response);
}
});
</script>
}
由于脚本在名为 X-CSRF-TOKEN 的 header 中发送令牌,因此配置防伪服务以查找 X-CSRF-TOKEN header:
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddAntiforgery(o => o.HeaderName = "XSRF-TOKEN");
}
参考:https://www.talkingdotnet.com/handle-ajax-requests-in-asp-net-core-razor-pages/
这就是我喜欢的方式:
配置您的 Javascript
//If you're returning a object, configure it
var yourObject = {
field1: "value1",
field2: "value2"
};
//setup ajax
$.ajax({
data: yourObject,
type: "POST",
url: "urltoyourhandler/delete" //you can add other paramters here as well by doing ?parm=value
success: function(data){
//do success stuff here
//based off my handler code below:
if(data.success){
console.log("Success!");
}
else{
console.log("Failed for some reason!");
}
}
error: function(){
//do error stuff here
//gets called if there is a issue contacting the URL or if there is a server error like 500
}
});
正在配置您的处理程序。对于我的 CRUD 操作,我喜欢制作一个 CRUD 控制器来处理所有事情
[BindProperty]
public YourClass Name { get; set; }
//set handler to only accept POST and set a URL for it. URL should be to the same folder you're in
//the 'delete' in route doesn't have to match the function name but it's less confusing if it does
[HttpPost, Route("RouteToThisHandler/delete)]
public async Task<IActionResult> Delete()
{
//verify data and the do something with it
//I like returning a JsonResult. Add whatever data you want. I like returning success
//with true or false and some other data if needed
return new JsonResult(new { success: true, importantInfo: "This is important" });
}
Ajax 有更多配置选项,可为您提供有关发生的任何服务器错误的更多信息
对于防伪令牌,微软表示:
Antiforgery middleware is added to the Dependency injection container when one of the following APIs is called in Startup.ConfigureServices:
- AddMvc
- MapRazorPages
- MapControllerRoute
- MapBlazorHub
这里是微软link关于防伪令牌的:https://docs.microsoft.com/en-us/aspnet/core/security/anti-request-forgery?view=aspnetcore-3.1
我调查了一些事情,当你从 AJAX 传递一个字符串而不是一个整数时会发生什么,以及不同的路由如何影响调用(如果你有时间,请参阅下面有趣的注释)但主要是,我所发现的只是 Razor Pages 相当宽容,一切似乎都能正常工作。就像我提到的,即使传递一个字符串,其中整数类型 id
仍然命中处理程序方法(它只是给了我一个 default(int)
)
我创建这个 repo 只是为了探索:https://github.com/EntityAdam/RazorPageHandlers
正如@Yan 指出的那样,主要的障碍是防伪令牌。这确实是导致处理程序未命中断点的唯一原因。正如建议的那样,检查您的网络选项卡是否有失败的请求或控制台是否有错误 JavaScript 代码。
从您的代码片段中,要将其更改为 OnPostDelete
,您需要在 AJAX 调用中使用 POST
类型并包含防伪标记。
$.ajax({
type: 'POST',
headers: { "RequestVerificationToken": $('input[name="__RequestVerificationToken"]').val() },
url: '?handler=Delete',
data: {
id: $(this).data('id')
}
})
.fail(function (e) {
// Error
alert(e.responseText); // Way too much info
})
.done(function () {
// Success
})
.always(function () {
// Always
});
另一个我没有看到讨论的话题是这个令牌来自哪里?只要有 <form>
元素,它就会由 Razor 自动生成。如果您没有 <form>
元素,您可以在需要时生成标记,查看此 MSDN Article 中的 @functions {}
块。在某些情况下,CSRF 无用或不需要,如果不需要,您也可以关闭防伪造(这是一个完全不同的讨论)。
我对这种方法的批评是意见,所以要么接受要么放弃。
- 如果可以避免使用 jQuery,前提是 JavaScript 的改进可以说已经过时 jQuery。使用普通的 JS 代码。
- Ajax 也显示了它的年龄。如果您只需要支持现代浏览器,请考虑 Fetch API
- 完全不写任何JS! Blazor 是新的,闪亮的。仍然有一些成长的烦恼,但我宁愿我的痛苦在 C# 中而不是在 JavaScript =)
我遇到的一件有趣的事..
对于这个演示,我使用了以下 @page
指令
@page "{id?}"
在 HTML 部分的表格如:
<form method="post" asp-page-handler="Delete">
<input type="hidden" name="id" value="1" />
<button class="btn btn-danger">Delete</button>
</form>
我正在使用 asp-page-handler
标签助手来帮助生成正确的 URL。对于 Create 处理程序,使用 @page
指令,标签助手提出了 /?handler=Create
如果您用 @page "{handler?}/{id:int?}"
替换掉 @page 指令,标签助手会计算出现在的路由 /Delete
。但猜猜怎么了? AJAX 调用与任一 @page
指令一起工作,即使 AJAX 中的 URL 被硬编码为 ?handler=Delete'