3
votes

In my .net core razor page project, i would like to call server side methods from a cshtml input without reloading the page. I'm still a newbie with razor pages.

.cshtml : 

input type="submit" id="AddCart" asp-page-handler="AddToCart" hidden

Some JS to .click() the input.

.cs :
public async void OnPostAddToCart()
{
//code
}

So far i did not find a way to prevent the page reload and still access my server-side methods.

Thanks

EDIT : Looking at the link provided by brad, i managed to make it work.

I added @Page "{handler?}" to write the url without the handler (not sure if it matters for ajax), I set my ajax url to "thePage/theMethod", I decorated my razor controller class with [ValidateAntiForgeryToken] And mentioned the anti forgery token in ajax :

$.ajax({
                url: "/mainPage/AddToCart",
                type: "POST",
                contentType: "application/json; charset=utf-8",
                beforeSend: function (xhr) {
                    xhr.setRequestHeader("XSRF-TOKEN",
                        $('input:hidden[name="__RequestVerificationToken"]').val());
                },
                success: function () {
                    alert("success");
                },
                complete: function () {
                    alert("complete")
                },
                failure: function () {
                    alert("failure");
                }
            });
2
At the moment this is not possible with razor pages alone, you will have to use AJAX.Anton Toshik
Or you can try Blazor, if you are brave enough to use the bleeding-edge experimental frameworks ;)Tseng
See stackoverflow.com/questions/46410716/… for more info on calling back to a razor pageBrad Patton

2 Answers

2
votes

First ,change the naming of your Handler method like below :

 public async void OnPostAddToCartAsync()
    {
        //code
    }

Refer to Handler Methods in Razor Pages for more details on the nameing convention .

Second ,If you want to use ajax in Razor Pages , the URL pattern should be like "/mainPage?handler=AddToCart" .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.

  • Add antiforgery token using @Html.AntiForgeryToken(), if not present.

  • Modify your Ajax request to send the same in request header like below:

    <input type="button" id="AddCart"  onclick="clickbtn()" value="Submit"/>
    function clickbtn() {
        $.ajax({
            url: "/Test?handler=AddToCart",
            type: 'POST',
            beforeSend: function (xhr) {
                xhr.setRequestHeader("X-XSRF-TOKEN",
                    $('input:hidden[name="__RequestVerificationToken"]').val());
            },
            success: function ()
            {
                alert("success");
            },
            complete: function ()
            {
                alert("complete")
            },
            failure: function ()
            {
                alert("failure");
            }
        });
    }
    
  • Since the script sends the token in a header called X-XSRF-TOKEN, configure the antiforgery service to look for the X-XSRF-TOKEN header:

    services.AddAntiforgery(option => option.HeaderName = "X-XSRF-TOKEN");
    

    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.

1
votes

If you do not want to reload the page you must use ajax or XMLHttpRequest , (the former being based on the latter).

<script>
window.onload=function()
{
  window.click=function()
  {
        $.ajax({  
            url: '[baseUrl/OnPostAddToCart]',  
            data: JSON.stringify(postData), //your data 
            type: 'POST',  
            contentType: 'application/json',  
            dataType: 'json',  

            success: function (result) {  
                alert(result);  //do something if successful
            },  
            complete: function(){  
                 //do something on complete
            },  
            failure: function (err) {                  
                alert(err); // Display error message  
            }  
        });
   }
}
</script>
<input  onclick="click()" type="button"/>

Using XMLHttpRequest:

window.click=function()
{
var xhr = new XMLHttpRequest();
xhr.open("POST", "[Your URL]");
xhr.onload=function()
{
  if(xhr.status==200)
    resolve(xhr.response);
  else
    reject("error:"+xhr.status);
}
var data=JSON.stringify({some_data});
xhr.send(data);
}

Controller method

 public class MyController:Controller
 {
    [HttPost]
    [Route("/OnPostAddToCart")]
    public async Task AddToCart(object data)
    {

    }
 }

P.S For more information on ajax