405 response when POSTing data back to controller from JQuery in custom app

In my custom app, i can’t post back to the controller from my view at all. If I use a form to post data to a controller I get a 405, indicating that CSRF fails. I tried including a requesttoken hidden input in the form, switching to using core js, using jquery and finally, adding the @NoCSRFRequired comment to the method out of desperation. The documentation for this is not very explanatory and I’m tired now so not really making much sense from poking around.

Please, can someone explain why this is being weird?

More info:

Each time I tried with with jquery, or raw javascript I have confirmed that the requesttoken header is set and correct. This is how I tried to do it with jquery:

document.getElementById('theform').onsubmit = function(e){
    e.preventDefault();
    var fd = $(this).serializeArray();
    var ajo = {
        method: "POST",
        url: "/apps/myapp/jsonendpoint",        
        data: fd,
        contentType: 'application/json',
        success: function(data) {
            console.debug(data);
        }
    };
    console.debug(ajo);

    $.ajax(ajo);
    debugger
    return false;
}

more info here is my route code for the route in question:

[
	'name' => 'page#jsonendpoint', 
	'url' => '/jsonendpoint', 
	'verb' => 'POST'
],

this is the minimal code from the endpoint in the page controller:

	/**
	 * @NoAdminRequired
	 * @NoCSRFRequired
	 */
	public function jsonendpoint(): JSONResponse {
		return new JSONResponse( [
			'message' => "Saved",
			'request_data' => $_REQUEST
		], Http::STATUS_OK );
     }
}

after finding nickvergessen’s response on What to add in route.php for POST in Self PHP I went back to the documentation at Tutorial — Nextcloud latest Developer Manual latest documentation

based on that documentation, i modified my js to this, and it solved the issue for me:

document.getElementById('theform').onsubmit = function(e){
    e.preventDefault();
    var url: "/apps/myapp/jsonendpoint",   
    url = OC.generateUrl( url );
    var fd = $(this).serializeArray();

    var ajo = {
        method: "POST",
        url: url,        
        data: JSON.stringify( fd ),
        contentType: 'application/json',
        done: function(data) {
            debugger
            console.debug(data);
        },
        fail: function(response, code){
            console.error('failed to save reply');
            console.error(code);
            console.error(response);

        }
    };
    $.ajax(ajo);
    return false;
}

this allowed me to remove the @NoCSRFRequired and get to working on the endpoint’s PHP with the assurance that csrf prevention is as good as it’s going to get.

the main difference is using

OC.generateUrl( url );

JSON.stringify

and getting the object’s callbacks correct (done and fail)

1 Like