How to process Ajax requests in asp.net core razor

Time:2020-2-23

When asp.net core razor (hereinafter referred to as razor) first came out, I looked at the official documents, but I haven’t used them very much.

Today, I had nothing to do. I was ready to use rozor to do a project skillfully. As a result, I got stuck writing the first page.. It’s been a long time. Let’s share the solution. First, let’s briefly introduce that razor razor pages is a new function of asp.net core, which can make the programming scheme of page making simpler and more efficient. The razor page uses handler methods to process incoming HTTP requests (get / post / put / delete). These are similar to the action methods of asp.net MVC or web API. Razor pages follow a specific naming convention, as do handler methods. They also follow specific naming conventions, and have asynchronous versions of ongetasync(), onpostasync() and other processing methods like the “on” prefix: the same as HTTP verbs. After the introduction of razor, directly above

The function is very simple. It’s just a login. Users click the “Login button” and use jQuery to get the value of the text box, which is submitted to the server asynchronously. It’s a very simple function. I believe you’ve written it many times. The code came out with a few clicks.

##Foreground code
<form method="post">
      <div>
        <i></i>
        <input asp-for="Login.UserName" />
        <div> </div>
      </div>
      <div>
        <i></i>
        <input asp-for="Login.PassWord" />
        <div> </div>
      </div>
      <div>
        <ul>
          <li>
            <input type="checkbox" value="">
            < label for = "brand1" > remember me < / label >
          </li>
        </ul>
        <a href="#" rel="external nofollow" >
          Forget the password?
        </a>
      </div>
      <div>
        < input type = "button" value = "login" >
      </div>
      <div>
        < input type = "button" value = "register" >
      </div>
</form>
##Script code
$("#btnLogin").click(function () {
      $.post('/user/Login?hanler=LoginIn', { UserName:$("#UserName").val(),              PassWord:$("#PassWord").val() }, function (data) {
        console.log(data);
      });
    });
##Background code
public class LoginModel : PageModel
{

  private UserServiciCasee _userService;

  public LoginModel(UserServiciCasee userService)
  {
    _userService = userService;
  }

  public void OnGet()
  {
  }
  [BindProperty]
  public UserLoginDto Login { get; set; }
  public async Task<ActionResult> OnPostLoginInAsync()
  {
    //if (ModelState.IsValid)
    //{
    //  var user = await _userService.LoginAsync(Login);
    //  if (user != null)
    //  {
    //Return new jsonresult (apiresult. Tosuccess ("login succeeded!");
    //  }
    //Return new jsonresult (apiresult. Tofail ("account password error!"));
    //}
    Return new jsonresult (apiresult.tofail ("parameter filling error, please check!");
  }
}

First of all, explain the meaning of / user / login? Hanner = loginin. User is a directory under my page, login is a page, and loginin is a corresponding method within the page. The purpose of this URL is to submit the request to the onpostlogininasync() method for processing. As for why loginin is not onpostloginasync, it is also mentioned at the beginning of the article that this is the syntax limit of rozar. If you don’t know clearly, you can go to see the official documents of Microsoft and write better than me.. At first glance, this code has a clear idea. The project runs and takes a walk.

 

Yes, you are right. The response code is 400. All kinds of postures have been tried for half a day, which is 400. Now you must want to know what’s wrong with the code above. Well, there’s nothing wrong with the code above. The reason is that razor is designed to automatically prevent cross Site Request Forgery (CSRF / xsrf) attacks. You don’t have to write any other code. The razor page automatically contains anti-counterfeiting token generation and validation. The request here failed because the post did not submit the anti forgery token. There are two ways to add an anti forgery token.

In asp.net core MVC 2.0, formtaghelper injects anti forgery tokens into HTML form elements. For example, the following tags in the razor file will automatically generate anti-counterfeiting Tags:


<form method="post">
<!-- form markup -->
</form>

 

Explicitly add the use of @ HTML. Antiforgerytoken()

To add an anti forgery token, we can use any method. Both methods add a hidden name input type, requestverificationtoken. Ajax requests should send the anti-counterfeiting token in the request header to the server. So the modified Ajax request looks like this:


$("#btnLogin").click(function () {
      $.ajax({
        type: "POST",
        url: "/user/Login?handler=LoginIn",
        beforeSend: function (xhr) {
          xhr.setRequestHeader("XSRF-TOKEN",
            $('input:hidden[name="__RequestVerificationToken"]').val());
        },
        data: { UserName: $("#UserName").val(), PassWord: $("#PassWord").val() },
        success: function (response) {
          console.log(response);
        },
        failure: function (response) {
          alert(response);
        }
      });
    });

The improved code adds “xsrf-token” in the request header before sending the request, and the value is the anti-counterfeiting tag automatically generated by the form. Because “xsrf-token” is added by ourselves, the framework itself will not recognize it, so we need to add this tag to the framework:


public void ConfigureServices(IServiceCollection services)
{
  services.AddMvc();
  services.AddAntiforgery(o => o.HeaderName = "XSRF-TOKEN");
}

Now the server can receive the post request normally. After a long time of tossing and turning, we finally solved…. After solving this problem, I found that I had drilled a bull’s horn before, in fact, there is a simpler way.. It’s too late. Let’s test it tomorrow. If possible, make up.