Asp.net Core 2.0 Razor Pages Ajax Post

2019-04-10 20:00发布

I am trying to just jquery ajax call to retrieve a list of users from a Razor page.

Users.cshtml.cs page:

public ActionResult OnPostList(string FirstName, string LastName,string IsActive)
{
        var data=(from s in _db.SecurityUser
                 where s.FirstName.Contains(FirstName) && s.LastName.Contains(LastName) && (IsActive=="" || (IsActive =="Y" && s.IsActive==true) || (IsActive == "N" && s.IsActive == false))
                 select s).OrderBy(s=>s.FirstName);
        return new JsonResult(data);
}

JS Call:

$.ajax({
    type: "POST",
    url: "/Security/Users?handler=List",
    data: JSON.stringify({
        FirstName: $("#txtFirstName").val(),
        LastName: $("#txtLastName").val(),
        IsActive: $("#ddActive").val()
    }),
    contentType: "application/json",
    dataType: "json",
    success: function (response) {
        var d = response.d;
        var tblBody = $("#tblUsers > tbody");
        tblBody.empty();
        $.each(d, function (i, item) {
            var modifiedDate = new Date(parseInt(item.ModifiedDate.substr(6)));
            var $tr = $('<tr>').append(
                $('<td>').html("<a href='javascript:void(0)' onclick='fnDialogShow(" + item.UserID + ")'>Edit</a>"),
                $('<td>').text(item.FirstName),
                $('<td>').text(item.LastName),
                $('<td>').text(item.IsActive ? "Yes" : "No")
            ).appendTo(tblBody);

        });
    },
    failure: function (response) {
        alert(response.d);
    }

});

When it calls I get a 400 error back. Trying to figure out what I am doing wrong.

5条回答
男人必须洒脱
2楼-- · 2019-04-10 20:10

Your URL formation for Ajax request is correct. One thing to note down is, Razor Pages are designed to be protected from (CSRF/XSRF) attacks. Hence, Antiforgery token generation and validation are automatically included in Razor Pages. I believe that is the problem here. Your page may have antiforgery token present on the page if you have form tag in your HTML. But you need to pass the same in your Ajax request.

First, add antiforgery token using @Html.AntiForgeryToken(), if not present.

Then, modify your Ajax request to send the same in request header.

Like,

beforeSend: function (xhr) {
       xhr.setRequestHeader("XSRF-TOKEN",
          $('input:hidden[name="__RequestVerificationToken"]').val());
},

Read this post Handle Ajax Requests in ASP.NET Core Razor Pages to know more about making ajax request with ASP.NET Core razor pages.

查看更多
可以哭但决不认输i
3楼-- · 2019-04-10 20:22

add [HttpPost] in Action

  [HttpPost]
    public ActionResult OnPostList(string FirstName, string LastName,string IsActive)
    {
            var data=(from s in _db.SecurityUser
                     where s.FirstName.Contains(FirstName) && s.LastName.Contains(LastName) && (IsActive=="" || (IsActive =="Y" && s.IsActive==true) || (IsActive == "N" && s.IsActive == false))
                     select s).OrderBy(s=>s.FirstName);
            return new JsonResult(data);
    }

Used this Script in Users.cshtml.cs

<script>
  var url='@(Url.Action("OnPostList","ControllerName"))';
  var firstName= $("#txtFirstName").val();
  var lastName= $("#txtLastName").val();
  var isActive= $("#ddActive").val();
  $.post(Url,{FirstName:firstName,LastName=lastName,IsActive=isActive},function(data){
      var d = data.d;
      var tblBody = $("#tblUsers > tbody");
      tblBody.empty();
      $.each(d, function (i, item) {
         var modifiedDate = new Date(parseInt(item.ModifiedDate.substr(6)));
         var $tr = $('<tr>').append(
         $('<td>').html("<a href='javascript:void(0)' onclick='fnDialogShow(" + item.UserID + ")'>Edit</a>"),
         $('<td>').text(item.FirstName),
         $('<td>').text(item.LastName),
         $('<td>').text(item.IsActive ? "Yes" : "No")
         ).appendTo(tblBody);
       });
    });
</script>
查看更多
男人必须洒脱
4楼-- · 2019-04-10 20:24

By default, Razor Pages are designed to be protected CSRF attacks.

You must properly inject the antiforgery token into your ajax request.

See the Documentation.

In ASP.NET Core 2.0 it looks like this...

First place this code into the top of your razor view:

// At the top of your page
@inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Xsrf
@functions{
    public string GetAntiXsrfRequestToken()
    {
        return Xsrf.GetAndStoreTokens(Context).RequestToken;
    }
}

Then in your ajax request, set the token header.

$.ajax({
    type: "post",
    headers: {
        "RequestVerificationToken": '@GetAntiXsrfRequestToken()'
    },
    url: '@Url.Action("Antiforgery", "Home")',
    success: function (result) {
        alert(result);
    },
    error: function (err, scnd) {
        alert(err.statusText);
    }
});
查看更多
爷的心禁止访问
5楼-- · 2019-04-10 20:27

Mark your OnPostList with HttpPost attribute and change your URL in ajax call to /Security/OnPostList

查看更多
混吃等死
6楼-- · 2019-04-10 20:29

I had bad experiences with $.ajax, I used $.post instead. I used validateAntiforgeryToken but its not necessary

    $("#emailSubmit").click(function () {

        $.post("/Projects/SendInvite",
            {
                Email: $("#email").val(),
                Message: $("#message").val(),
                __RequestVerificationToken: $('input[name="__RequestVerificationToken"]').val()
            }

        )
        return false;

    });

And this is net core action:

    [HttpPost]
    [ValidateAntiForgeryToken]
    public IActionResult SendInvite(string Email, string Message)
{

        //MailTest();
        var json = new List<string>
        {
        Email,
        Message
        };
        return new JsonResult(json);
   }
查看更多
登录 后发表回答