示例 AJAX 回调到 ASP.NET Core Razor 页面
Posted
技术标签:
【中文标题】示例 AJAX 回调到 ASP.NET Core Razor 页面【英文标题】:Example AJAX call back to an ASP.NET Core Razor Page 【发布时间】:2018-03-06 17:57:39 【问题描述】:我发现一个页面上有多个处理程序以及相关的命名约定(即 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("");
OnPost 不是从 Ajax 调用中调用的。
【问题讨论】:
你想做什么?你能展示你的观点吗? 没有“视图”,只有 Razor 页面。我已经扩展了这个例子。 docs.microsoft.com/en-us/aspnet/core/mvc/razor-pages/… @page 使文件成为 MVC 操作 - 这意味着它直接处理请求,而不通过控制器。 ... URL 路径与页面的关联取决于页面在文件系统中的位置。下表显示了 Razor 页面路径和匹配 URL:文件名和路径匹配 URL /Pages/Index.cshtml / 或 /Index /Pages/Contact.cshtml /Contact /Pages/Store/Contact.cshtml /Store/Contact / Pages/Store/Index.cshtml /Store 或 /Store/Index 【参考方案1】:Razor Pages 自动生成并验证 Antiforgery 令牌以防止 CSRF 攻击。由于您没有在 AJAX 回调中发送任何令牌,因此请求失败。
要解决这个问题,您必须:
-
注册防伪服务
将令牌添加到您的请求中
通过添加
<form>
或直接使用@Html.AntiForgeryToken
HtmlHelper 将防伪令牌添加到您的页面
1。在您的Startup.cs
中注册防伪服务
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 Pages 都会自动添加一个隐藏的输入字段,其中包含防伪令牌:
<input name="__RequestVerificationToken" type="hidden" value="THE_TOKEN_VALUE" />
【讨论】:
我遇到了同样的问题。如果您查看控制台输出,它会告诉您缺少 XSRF-TOKEN。 即使进行了这些更改,我仍然收到错误请求。该文档docs.microsoft.com/en-us/aspnet/core/security/… 谈到了进行类似的更改,但这似乎也不起作用:( 你重建了吗?我完全按照我写的方式进行了测试,并开始收到回复。还要确保 program.cs 使用 Microsoft.Extensions.DependencyInjection; 刚刚创建了一个新的网络应用程序并根据我的 OP 修改了“关于”页面(还添加了一个错误处理程序,见上文)和您建议的更改。控制台显示以下内容:状态:错误错误请求。这似乎是正确的道路,但我只是错过了一些东西。 无需添加 [ValidateAntiForgeryToken] 属性,因为 Razor 页面旨在自动验证 Antiforgery 令牌。【参考方案2】:请参阅文档的相关部分 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
【讨论】:
我了解页面的路径,但 AJAX 调用未触发 OnPost 方法。你有一个有效的 ajax 调用的例子吗? 您是否收到错误请求或未找到? @Greg regaring Url,最好使用@Url.Page让asp.net构造正确的url并传递参数。【参考方案3】:一切正常,但必须进行一些更改:
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',
【讨论】:
刚刚测试了这个与接受的答案相比,它似乎不起作用。您是否使用新的 Razor Pages 而不是 MVC 进行了测试? url应该指向页面, 我通过VS2017创建了一个新项目“Asp.net Core 2.0”并修改了View About。我还没有创建新的 Controller,url 指向包含 Home 视图的文件夹。启动应用程序后,通过浏览器的调试(F12 键),网络 -> 您可以在“onPost”中看到正确答案。 您正在创建一个 MVC Web 应用程序。不是 Razor Page 网络应用程序。 About 应该在 Pages 文件夹下而不是 View 下。我确定您所做的对 MVC 来说很好,但它不适用于 Razor Pages。 见:docs.microsoft.com/en-us/aspnet/core/tutorials/razor-pages/… 你是对的。事实上,我正在“Asp.net Core 2”类型的 Web 应用程序 MVC 中创建一个应用程序,它可以工作。【参考方案4】:查看上面的答案后,我使用 Visual Studio 2017 Preview 2 获得了 JSON ajax 来处理 .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);
浏览器
http://localhost:44322/postJson
【讨论】:
【参考方案5】:接受的解决方案在本地开发机器上工作,但失败然后部署在 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
【讨论】:
【参考方案6】:以下内容适用于使用 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 );
【讨论】:
【参考方案7】:我为后代添加这个。 解决同样的问题,我发现下面的代码可以添加到 Startup.cs 中:
services.AddRazorPages().AddRazorPagesOptions(options =>
options.Conventions.ConfigureFilter(new IgnoreAntiforgeryTokenAttribute());
);
不再需要防伪令牌。
【讨论】:
【参考方案8】:答案对我有用。如果我们在页面上有自定义方法,我只会添加:
public IActionResult OnPostFilter1()
return new JsonResult("Hello Response Back");
那么我们应该在 url 中指定处理程序名称:
url: 'OnPost?handler=filter1',
【讨论】:
以上是关于示例 AJAX 回调到 ASP.NET Core Razor 页面的主要内容,如果未能解决你的问题,请参考以下文章
ASP.NET Core 模型未通过 AJAX 绑定到控制器
CORS 不适用于从 Ajax 到 ASP.NET Core Web API 的调用
ASP.NET Core MVC - 使用 Ajax 将数据发送到另一个模型中的模型