I am trying to obtain the JSON data that is sent to the server via an AJAX POST when a button is clicked on my homescreen
page on my Catalyst application:
The AJAX POST that sends the JSON data to the server:
$("#saveCanvasStates").click(function () {
// button to save canvas states to a database
// Serialize the states array
var JsonStringForTransport = JSON.stringify({stateForUserNumber7: states});
// POST the JSON to the server
var thePost = $.ajax({
url: 'homescreen',
type: 'POST',
dataType: 'json',
data: JsonStringForTransport,
contentType: 'application/json; charset=utf-8'
});
I also have the following Catalyst Controller for the homescreen
page which the button that sends the AJAX POST is located on:
Catalyst Controller:
package MyProject::Controller::Homescreen;
use strict;
use warnings;
use parent 'Catalyst::Controller';
use Data::Dumper;
__PACKAGE__->config->{namespace} = '';
sub homescreen :Path('/homescreen') :Args(0) {
my ( $self, $c ) = @_;
$c->stash({title => 'Home Screen',
pagetype => 'html',
template => 'homescreen.html'
});
#here is where I think I need to obtain the JSON data from the AJAX POST request
#and save it to my database
}
1;
Once I have this JSON data in a form I can work with I will then be saving it to a Postgres database.
From looking at the CPAN docs for Catalyst::Request, as it's my understanding this is what to refer to when dealing with request stuff, it's possible to use the following to do stuff with AJAX POST data?:
But I am unsure about the best way to get the data into a form I can then insert into my database and which one of the methods should be used in preference?
I can find very little documentation that has helped me.
I definitely have body_data
to display because when I do:
print Dumper($c->req->body_data);
I get the following printed in my development server log:
$VAR1 = {
'stateForUserNumber7' => [
{
'width' => 102,
'offsetY' => 56,
'x' => 11,
'height' => 102,
'image' => {},
'y' => 14,
'contextIndex' => 2,
'dragging' => bless( do{\(my $o = 0)}, 'Cpanel::JSON::XS::Boolean' ),
'offsetX' => 73
},
{
'width' => 102,
'offsetY' => 34,
'x' => 103,
'height' => 102,
'image' => {},
'y' => 17,
'contextIndex' => 3,
'dragging' => $VAR1->{'stateForUserNumber7'}[0]{'dragging'},
'offsetX' => 46
}
]
};
[info] *** Request 15 (1.250/s) [17427] [Fri Dec 6 00:02:22 2013] ***
[debug] Path is "homescreen"
[debug] "POST" request for "homescreen" from "192.168.1.100"
[debug] Rendering template "homescreen.html"
[debug] Response Code: 200; Content-Type: text/html; charset=utf-8; Content-Length: 7010
[info] Request took 0.025343s (39.459/s)
.------------------------------------------------------------+-----------.
| Action | Time |
+------------------------------------------------------------+-----------+
| /homescreen | 0.014044s |
| /end | 0.001992s |
| -> Organiser::View::TT->process | 0.001058s |
'------------------------------------------------------------+-----------'
This is the error it gives in the development server output when using -d
:
Caught exception in Organiser::Controller::Homescreen->homescreen "Can't use an undefined value as a HASH reference at /home/fred/Organiser/script/../lib/Organiser/Controller/Homescreen.pm line 21."
This is the error I get from Stack Trace when running the development server:
Stack Trace
Package Line File
Organiser::Controller::Homescreen 21 /home/fred/Organiser/lib/Organiser/Controller/Homescreen.pm
18:
19: print STDERR Dumper $c->req->body_data;
20:
21: foreach my $data (@{$c->req->body_data->{stateForUserNumber7}}) { <-- it highlights in bold this line
22: print "DOLLAR DATA $data\n";
23: }
24:
Organiser::Controller::Root 17 /home/fred/Organiser/lib/Organiser/Controller/Root.pm
14: sub index :Path :Args(0) {
15: my ( $self, $c ) = @_;
16:
17: $c->forward('homescreen'); <-- it highlights in bold this line
18:
19: }
20:
Using Firebug this is the POST request that is occurring (after I comment out the foreach that is making it error)
Source
{"stateForUserNumber7":[{"dragging":false,"contextIndex":4,"image":{},"x":108,"y":4,"width":102,"height":102,"offsetX":45,"offsetY":65}]}
It is always stateForUserNumber7
(I should have named it master_user or something really)
Although the built in logging stuff is great when you are making logs to persist and to do analysts on, I find it not terribly using for basic debugging. I've lately been using Devel::Dwarn which is an easy install. This is like a warn dumper + rolled up very neatly.
If you start your app like so
perl -MDevel::Dwarn ...
You can stick Dwarn $ref
and get a nice stderr output:
Dwarn $c->req->body_data
Should give you a neat review. Plus if you drop the -MDevel::Dwarn
you'll get errors in all the places you accidentally left Dwarn
out (something I should have done with the borked release of Runner 002 last month).
If that is confusing to you just try:
(after cpanm Devel::Dwarn
)
use Devel::Dwarn;
Dwarn $c->req->body_data
You should get a deep structure output to your console. Best of luck!
My other answer is (hopefully) useful information for anyone debugging Catalyst/JSON issues. But subsequent updates to the question have shown the problem here is actually something entirely different.
There are not enough actions to support the required functionality here. If the index
action forwards to the homescreen
action which renders the homescreen.html
template, then the $.json()
call has to be to some other action which is responsible for handling the data save request and nothing else.
package MyProject::Controller::Homescreen;
use strict;
use warnings;
use parent 'Catalyst::Controller';
use JSON;
sub homescreen :Path('/homescreen') :Args(0) {
my ( $self, $c ) = @_;
$c->stash({title => 'Home Screen',
pagetype => 'html',
template => 'homescreen.html'
});
}
sub savecanvasstates :Local {
my ($self, $c, @args) = @_;
my $p = $c->req->param->{stateForUserNumber7} || die "wrong parameters!";
my $result = {};
foreach my $r (@{$p}) {
# ... do something with $r->{x} etc
$result->{output} = # construct whatever object the ajax caller expects
}
$c->res->body(to_json($result))
}
1;
And in some nearby JavaScript:
$("#saveCanvasStates").click(function () {
// button to save canvas states to a database
// Serialize the states array
var JsonStringForTransport = JSON.stringify({stateForUserNumber7: states});
// POST the JSON to the server
var thePost = $.ajax({
url: 'savecanvasstates',
type: 'POST',
dataType: 'json',
data: JsonStringForTransport,
contentType: 'application/json; charset=utf-8',
success: function(data, textStatus){ ... }
error: function(XMLHttpRequest, textStatus, errorThrown){ ... }
});
});
I hope all that makes what you have to do clearer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With