ASP.NET Core 2,使用没有 MVC 的 Razor 页面单击按钮

Posted

技术标签:

【中文标题】ASP.NET Core 2,使用没有 MVC 的 Razor 页面单击按钮【英文标题】:ASP.NET Core 2, button click with Razor pages without MVC 【发布时间】:2018-05-07 16:09:12 【问题描述】:

正如有人在评论中指出的那样,Razor 页面不需要控制器,就像您在 MVC 中习惯的那样。我现在 Razor 也没有对按钮单击事件的本机处理。当用户点击一个按钮时,我们至少有两个选项:

使用提交按钮 使用 ajax 调用

我找到了很多 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:

公共类 TestModel : PageModel 私有只读 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

问题

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

    使用“Way2”时我做错了,因为 cs 代码中的函数永远无法到达,并且我收到错误请求错误 (400)。我错过了什么?

【问题讨论】:

【参考方案1】:

普通表单提交

在进行普通表单提交时,按照约定,处理程序方法名称必须遵循OnHttpVerbYourHanderName格式

public ActionResult OnPostWay2(string data)

    // to do : return something

现在确保您的提交按钮位于 form 标记内,并且您提到了 asp-page-handler。该属性的值应该是您在页面模型类中的处理程序名称 (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&amp;handler=Way2。 当用户点击提交按钮时,它会发布表单这个url,因为formaction属性值会覆盖表单的默认action url。当接收到请求时,razor pages 框架将使用这个参数(handler)并将请求定向到相应的处理方法。

Ajax 调用

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

要使您的 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 调用,返回一个 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>

【讨论】:

很好的解释!现在我对正在发生的事情有了更好的理解。第一种方法就像一个魅力。我想问你关于 ajax url 的最后一个澄清:这里的正确语法是什么?我最初的猜测 ("@Url.Action("Way2)") 现在导致错误 500 没有。您需要使用按钮的formaction 属性值。这就是您需要发布到的位置(它与我上面提到的网址相同)。只需检查视图源。 哦,对不起。我以为这只是一个例子!无论如何,它仍然回答错误 500。也许我的代码中还有其他问题。 500 表示,您的代码正在崩溃。在OnPostWay2 中设置断点,看看发生了什么。 找到。我没有意识到即使在进行 ajax 调用时也必须添加 asp-page-handler 属性。非常感谢。【参考方案2】:

除了显示的处理点击的 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>

【讨论】:

【参考方案3】:

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

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

【讨论】:

以上是关于ASP.NET Core 2,使用没有 MVC 的 Razor 页面单击按钮的主要内容,如果未能解决你的问题,请参考以下文章

带有标识 2 和 EntityFramework 6(Oracle)的 ASP.NET Core MVC

这是如何使用 Entity Framework Core 和 ASP.NET Core MVC 2.2+ 和 3.0 创建数据传输对象 (DTO)

ASP.NET Core MVC 2.x 全面教程_ASP.NET Core MVC 25. 过滤器

asp.net core mvc 2中抽象类的模型绑定器

ASP.NET Core MVC 2.x 全面教程_ASP.NET Core MVC 14. ASP.NET Core Identity 入门

[MVC&Core]ASP.NET Core MVC 视图传值入门