【问题标题】:Razor Pages delete using AJAX使用 AJAX 删除 Razor 页面
【发布时间】:2020-06-25 01:00:20
【问题描述】:

我正在尝试将 AJAX 与 Razor 页面结合使用。

我一直在网上搜索,但我发现的每个示例都有不同的作用,而且大多数示例都不完整或不适用于 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 参数。

由于我有赏金,这就是我希望在答案中看到的内容:

  1. 如果我将 AJAX 调用设置为使用 POST 并将我的处理程序重命名为 OnPostDelete(),则不会调用处理程序。我将如何发帖?
  2. 对上面的代码还有其他建议或批评吗?我知道有很多方法可以做到这一点。我只是在寻找最简单的方法并尝试改进它。

【问题讨论】:

  • 为什么不写这样的ajax $.ajax({ url: "Controller /Action", type: "POST", dataType: "json", data: JSON.stringify(data) , success: function (response) { // 你的响应逻辑 } });
  • @MdFaridUddinKiron:嗯,这是 Razor Pages,所以没有控制器。除此之外,$.post() 只是调用$.ajax(),所以我不知道这将如何解决我的问题。
  • 我明白了,我想知道后端,是Web from还是mvc?

标签: c# asp.net ajax asp.net-core razor-pages


【解决方案1】:

两个建议:

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);
 });

【讨论】:

    【解决方案2】:

    您可以通过 F12 在 Network 标签中检查请求,您可能会看到 400 bad request 错误。

    Razor 页面旨在自动防止 跨站点请求伪造 (CSRF/XSRF) 攻击。您不必编写任何额外的代码。防伪令牌生成和验证自动包含在 Razor 页面中。这里请求失败,页面上没有 AntiForgeryToken。

    对于这个问题,您可以使用@Html.AntiForgeryToken() 明确添加 要添加 AntiForgeryToken,我们可以使用任何方法。这两种方法都添加了一个名为 __RequestVerificationToken 的隐藏输入类型。 Ajax 请求应将请求标头中的防伪令牌发送到服务器。所以,修改后的 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 的标头中发送令牌,因此配置防伪服务以查找 X-CSRF-TOKEN 标头:

    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/

    【讨论】:

    • 我尝试在启动时添加services.AddAntiforgery(...) 并在页面中添加@Html.AntiForgeryToken(),但我似乎无法执行任何操作来调用我的处理程序。
    • 添加AntiForgeryToken后,在Delete handler下下断点,按f12查看ajax触发时是否有错误。
    • 你把ajax类型改成'POST'了吗?
    【解决方案3】:

    这就是我喜欢的方式:

    配置您的 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 有更多的配置选项,可以为您提供有关发生的任何服务器错误的更多信息

    对于防伪令牌,微软表示:

    防伪中间件被添加到依赖注入容器中 在 Startup.ConfigureServices 中调用以下 API 之一时:

    • AddMvc
    • MapRazorPages
    • MapControllerRoute
    • MapBlazorHub

    这是关于防伪令牌的 Microsoft 链接:https://docs.microsoft.com/en-us/aspnet/core/security/anti-request-forgery?view=aspnetcore-3.1

    【讨论】:

    • 请问您为什么不使用?handler 方法?我会使用您的方法进行创建或更新操作。但它似乎不适合删除。
    • 个人喜好。有很多方法可以做事,这是我喜欢的方式。它适用于我所做的一切,包括删除。我不仅使用这种方法来处理数据,而且还用于获取数据。例如,自动完成框。
    • MVC1002 'HttpPostAttribute' 不能应用于 Razor 页面处理程序方法。这不仅引入了警告,而且还与 Razor Pages 惯例作斗争。如果您不喜欢这些约定,请坚持使用 MVC。
    • 正如我的帖子所说,这些是控制器中的一些。
    【解决方案4】:

    我调查了一些事情,当你从 AJAX 传递一个字符串而不是一个整数时会发生什么,以及不同的路由如何影响调用(如果你有时间,请参阅下面有趣的注释)但大多数情况下,我发现的只是Razor Pages 非常宽容,一切似乎都正常工作。就像我提到的,即使传递一个整数类型 id 的字符串仍然会命中处理程序方法(它只是给了我一个 default(int)

    我创建这个 repo 只是为了探索:https://github.com/EntityAdam/RazorPageHandlers

    正如@Yan 所指出的,主要的障碍是防伪令牌。这确实是导致处理程序没有达到断点的唯一原因。正如建议的那样,检查您的网络选项卡是否有失败的请求或控制台是否有错误的 JavaScript 代码。

    从您的 sn-p 中,要将其更改为 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
    });
    

    另一个我没有看到讨论的话题是这个令牌来自哪里?只要有 &lt;form&gt; 元素,它就会由 Razor 自动生成。如果您没有&lt;form&gt; 元素,您可以在需要时生成令牌,请查看此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 中的 URL 被硬编码为 ?handler=Delete'

    ,AJAX 调用也可以使用 @page 指令

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-06-16
      • 2017-01-23
      • 2019-08-04
      • 2021-12-13
      • 1970-01-01
      • 1970-01-01
      • 2019-08-02
      相关资源
      最近更新 更多