Trying to convert V7 Surface Controller to work on...
# help-with-umbraco
i
Hello i have a problem with one surface controller who doesn't have access to the "CurrentPage". When i try to access this im getting this error "Cannot find the Umbraco route definition in the route values". The controller is invoked by Javascript with the culture "Culture" property. Please if any have experience with these Surface controllers, i should appreciate any help. If more information is needed please ask for a picture of the controller itself.
A little update I'm able to get CurrwntPage property when I call the endpoint with BeginUmbracoForm, but still didn't find a way to call it correctly with AJAX
k
Compare the working
BeginUmbracoForm
request with your AJAX request. Sounds like the path, querystring or POST data is wrong/insufficient. But in 9+ you need to register your Umbraco routes in a way you didn't need to in 7/8. If you look into the documentation on registering surface controller routes it could be there.
s
You might be missing the anti forgery token (or other things!) https://docs.umbraco.com/umbraco-cms/reference/routing/surface-controllers#preventing-cross-site-request-forgery-xsrf-csrf-attacks Have a look at the docs and see where yours differs!
i
Thank you, can u give me an example where to register this route? I saw the documentation but I'm a little bit lost.
k
If it's a normal surface controller, the URL is
/umbraco/surface/{controllername}/{action}/{id}
I think you should use
BeginUmbracoForm
etc if you are posting (from HTML) to the surface controller.
i
Yep I'm calling the controller with this route like you mention, but by Ajax call. The idea is to post a formal and if there is an error to render the error without refresh the whole page
Ani forgery is not the problem, because I am able to hit the action, but in the action I can't access the CurrentPage. I'm able to access this property only when I invoke the controller with BeginUmbracoForm, what in my case is not the desirable behavior.
k
There is no Current Page if you just invoke a surface controller. There is only the surface controller. The concept of a "current page" for a surface controller is magic injected by Umbraco. If I just POST to your controller from nowhere, what would the current page be? There was a page that you invoked the Umbraco form from, and that page is probably being passed to Umbraco and picked up by the surface controller when you
BeginUmbracoForm
. Unless there is a
BeginUmbracoAjaxForm
, you probably have to pass a page ID in the form ("current page ID"), and use
UmbracoContext
in the controller, but not
CurrentPage
. So sort of "brew your own" BeginUmbracoForm but for AJAX. (Didn't know people still said AJAX 🙂 )
h
You should be able to do something like below, change your submit button into a normal button and give it an id. In your javascript post the form like this
Copy code
js
$(document).on("click","#signin-btn", function (e) {  
    e.preventDefault();
    e.stopPropagation();
    var form = $("#submitsigninform");

    $.ajax({
        url: "/umbraco/surface/membershipsurface/submitsigninform",
        type: "POST",
        data: form.serialize(),
        beforeSend: function (xhr) {
            xhr.setRequestHeader("RequestVerificationToken",
                $('#submitsigninform input:hidden[name="__RequestVerificationToken"]').val());
        },
        error: function (xhr,  status, error) {
            console.log(xhr.responseText);
        }
    });
});
In your surface controller your method should look like
Copy code
cs
        [HttpPost]
        [ValidateUmbracoFormRouteString]
        [IgnoreAntiforgeryToken]
        public IActionResult SubmitSigninPage( PortalSigninViewModel model)
        {
            var test = UmbracoContext.PublishedRequest.PublishedContent;

            if (ModelState.IsValid)
            {
                ...

                //something was wrong so add an error
                ModelState.AddModelError("SigninError", result);

                return CurrentUmbracoPage();
            }

            return CurrentUmbracoPage();
        }
i
Thanks a lot i think that is the solution what im looking for.
4 Views