ASP.NET 核心 2,在没有 MVC 的情况下使用 Razor 页面单击按钮

ASP.NET Core 2, button click with Razor pages without MVC

正如有人在评论中指出的那样,Razor 页面不需要控制器,就像您在 MVC 中习惯做的那样。我现在 Razor 也没有对按钮单击事件的本机处理。要在用户单击按钮时执行某些操作(在 "code-behind" 中),我们至少有两个选项:

我找到了很多 MVC 示例,它们展示了如何定义控制器函数。但是如前所述,我没有。

因此我试图理解这两种方式。这是我的测试 cshtml:

<form method="post">
    <input type="submit" class="btn btn-primary" value="way1">Way 1/>
</form>

<button id="btn" type="button" class="btn btn-primary" value="way2">Way 2</button>

<script>
$(document).ready(function() {
    $("#btn").click(function (e) {
        e.preventDefault();
        $.ajax({
            url: "@Url.Action("Way2")",
            type: "POST",
            data: "foo",
            datatype: "text",
            success: function (data) {
                alert(data);
            }
        });
        return false;
    });
});
</script>

这里是 cshtml.cs:

public class 测试模型:页面模型 { 私有只读 MyContext _context;

public TestModel(MyContext context)
{
    _context = context;
}

public IActionResult OnPost()
{
    // here I can put something to execute 
    // when the submit button is clicked
}

public ActionResult Way2(string data)
{
    // this is never triggered
}

问题

  1. 使用 "Way1"(提交)我能够捕捉到按钮的点击,但有一些缺点。默认情况下,由于 post,页面会重新加载。有时我不需要更改任何内容,只需调用一个 C# 函数即可。但我不明白如何处理多个按钮。 IE。如果我有 5 个按钮,如何为每个按钮做不同的事情?

  2. 使用 "Way2" 我做错了什么,因为 cs 代码中的函数从未达到,我收到错误请求错误 (400)。我错过了什么?

普通表单提交

在进行普通表单提交时,按照惯例,处理程序方法名称需要遵循 On{{HttpVerb}}{{YourHanderName}} 格式

public ActionResult OnPostWay2(string data)
{
    // to do : return something
}

现在确保您的提交按钮位于 form 标签内并且您提到了 asp-page-handler。该属性的值应该是您在页面模型中的处理程序名称 class (Way2)

<form method="POST">       
    <button type="submit" asp-route-data="foo" asp-page-handler="Way2">Way 2</button>
</form>

以上代码将为 formaction attribute 设置为 url yourBaseUrl/YourPageName?data=foo&handler=Way2 的按钮生成标记。 当用户单击提交按钮时,它将 post 表单 url 因为 formaction 属性值将覆盖表单的默认操作 url。收到请求后,razor pages 框架将使用此参数 (handler) 并将请求定向到相应的处理程序方法。

Ajax 来电

您收到 400(错误请求)响应,因为框架需要 RequestVerificationToken 作为 posted 请求数据的一部分。如果您检查页面的视图源,您可以在表单中看到一个名为 __RequestVerificationToken 的隐藏输入元素。该框架使用它来防止可能的 CSRF 攻击。如果您的请求没有此信息,框架将 return 400 错误请求。

要使您的 ajax 代码有效,您所要做的就是明确发送此代码。这是一个工作示例

$("#btn").click(function(e) {
    e.preventDefault();

    var t = $("input[name='__RequestVerificationToken']").val();
    $.ajax({
        url: $(this).attr("formaction"),
        headers:
        {
            "RequestVerificationToken": t
        },
        type: "POST",
        data: { data: 'foo2' },
    }).done(function(data) {
        console.log(data);
    }).fail(function(a, v, e) {
        alert(e);
    });
});

现在,由于您正在进行 ajax 调用,因此 return 一个 json 响应

是有意义的
public ActionResult OnPostWay2(string data)
{
    return new JsonResult("Received "+ data + " at "+DateTime.Now);        
}

在上面的示例中,我们使用一些 jQuery 代码来获取名称为 __RequestVerificationToken 的输入元素并读取它的值。一种更健壮的方法是将 IAntiforgery 实现注入视图并使用 GetAndStoreTokens 方法。

@inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Xsrf
@functions{
    public string GetAntiXsrfRequestToken()
    {
        return Xsrf.GetAndStoreTokens(Model.HttpContext).RequestToken;
    }
}
<script>
     $(function () {

         $("#btn").click(function(e) {
             e.preventDefault();
             var t = '@GetAntiXsrfRequestToken()';
             $.ajax({
                      url: $(this).attr("formaction"),
                      headers:
                      {
                          "RequestVerificationToken": t
                      },
                      type: "POST",
                      data: { data: 'foo2' },
             }).done(function(data) {
                     console.log(data);
             }).fail(function(a, v, e) {
                     alert(e);
             });
         });
    })
</script>

除了显示的处理点击的 jQuery 代码之外,您还必须在 asp-page-handler 中包含函数名称,以便路由到正确的函数.如果您没有 asp-page-handler,请求将在默认的 OnPost() 函数中结束。您希望它转到 OnPostWay2 函数。

代码:

<button id="btn" type="button" class="btn btn-primary" value="way2" asp-page-handler="Way2">Way 2</button>

如果您想执行任何处理程序并只想导航到另一个页面,这是另一种简单的排序方式:

<button type="button" class="btn" onclick="window.location.href = '/YourPage'">Button Title</button>