Insert data into DB with Symfony2 via JavaScript, without a form - javascript

I'm currently working on a Symfony2 project where a user can comment on parts of a webpage via contenteditable spans. I now want to save these comments, that are assembled in an array of JSON objects, into the database, with a reference to the page and the user id. This is where I'm stuck.
What steps are needed to put the data from the JavaScript code into the specific DB table?
I already created a Comment class in the Entity folder. And based on this
answer I added the following code in my saveComment() in JavaScript:
$.post('saveComments.php', {
page_id : getPageId(),
user_id : getUserId(),
comments : getJSONcomments(),
});
What next...?
Ok, let's create a saveComments.php ... but where in the bundle? Or could this be done with a Controller? If so, how and what would I need to replace the url ("saveComments.php") in the $.post(...) call with?

Don't post to a PHP page as this breaks the Symfony 2 model. Instead post to a route, like save/comment or along these lines.
Configure the route to point to an action in a controller.
Implement the controller and the action so that it does not take any parameters. Inside the action unpack the posted data the usual PHP way using (because you won't have a form to bind your data to):
$_POST
Just to get it working, echo a var_dump() to the console and see what you get. This is an example on how to write to the console.
Decode the JSON data with the serializer.
The decoded data will be a simple associative PHP array. Interpret the data you received and act accordingly (don't forget to handle security and all that stuff, too -- you don't want to open up security holes through AJAX).
Best is, you check that the route you chose falls into the security tier you need and probably already have configured in the Symfony 2 application. This way you don't need to handle security manually in the action.
Once this is done return an HTTP response with code 200 OK.
return new Response('', Response::HTTP_OK); // no response text at all
If there's any error reply with a 500 class HTTP server error:
return new Response('', Response::HTTP_INTERNAL_SERVER_ERROR); // 500
Also, don't forget to handle client-side errors with the .error() method.

Related

Cache API with MVC Views

I have a basic MVC form and I've been trying to use the Javascript Cache API to cache all my css, js, html files so that when users (people in the field) do not have reliable access, they can still use my web form. Obviously I'm using IndexedDB and service workers as well to check for a connection and save locally when a connection is not available, syncing when it is available.
I've gone through some tutorials and everything seems straightforward when dealing with caching actual, physical files (css, html, js). MVC is weird though since you're routing. I created the basix Index, Create, Edit, Details views. When I create an array of URL's to cache such as
var urlsToCache = [
'/App/Details',
'/App/Edit',
'/App/Create',
'/App/Index',
'/App/Content/bootstrap.css',
'/App/Content/site.css',
'/App/Scripts/jquery-1.10.2.js',
'/App/Scripts/jquery.form.js',
'/App/sw.js',
'/App/Scripts/bootstrap.js',
]
.. everything caches except for DETAILS and EDIT. Index and create cache fine. I'm actually surprised the latter two cache at all since they aren't physical files. I'm assuming Details and Edit don't cache because they don't work without querystring parameters.
Is it POSSIBLE to cache these two views at all? Or does anyone know of anything on NuGet that addresses this situation?
I changed this in the GET method for my Edit action to return an empty Model if there was no ID
if (id == null)
{
//return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
return View();
}
This allowed me to load the Edit page without a querystring variable and not get an error message. The page loads with no data but it allows me to cache it. At this point I suppose I would have to tell my service worker to check if the page is online. If it is, route the request normally, else query the local storage and manually plug the values into the fields.
So let this be a lesson to anyone creating Offline-enabled apps with MVC and using Cache API. Get rid of the lines that return bad request errors in your CRUD views if ID numbers aren't passed. Just pass back a blank model to the view (return View()). This allows you to cache your pages. And you'll obviously need to write code to handle the offline retrieval and presentation in code that executes when the page loads, but it will still allow you to utilize the MVC/Razor features when online.
One thing to note: "/App/Edit" will cache. If you load "/App/Edit/2", it won't match a url in your cache so you'll get an offline message. However, you can easily modify your Index page to send the ID via post. Just have a form on the page that goes to the Edit action and change the link to an underlined span with an onclick that sets the value of a hidden field to the ID. You'll have to pass another hidden field to let it know that it needs to retrieve instead of update (since the controller has different GET AND POST actions for Edit. The GET action is useless, but keep it for caching. You're retrieval that you normall would do int the GET is now going to be done in the POST with an if statement to check for your hidden field flag.

Script to fill a web form using a set of data

I am currently configuring software, however, the fields I am configuring requires a very simple set of data (3 variable fileds) to be entered into a form. However, this operation needs to be done approximately 2,500 times to cover all cases. I can easily genrate a csv containing all the fields for all the entries of this tabel.
I am looking for high level information as to how this can best be accomplished using a script. Could somebody provide a crash course on how to incorperate a custom script to load and submit this information using an external file. Things such as: what fields should I look for using the inspect element or how to load and iterate through a file using JS or python, etc. Or provide any resources that would be helpful on how to accomplish this. Thanks in advance!
In this case I suggest using python rather than javascript, which can be executed conveniently in local.
At the beginning, you need a I/O. In case you are not familiar, take a look on this.
Next, you need a way to send http request. The library for this is urllib, which is inbuilt. Then you need a way to make everything in json, which is well-accepted type for data transferring through http.
You can find the sample of using urllib here.
Please remember that you are 'passing the data', use 'POST' method instead of 'GET' method.
Your data should be encoded in
from json import dumps
data= dumps({
//data dictionary
})
...
urllib.urlencode({'login' : 'MyLogin', 'password' : 'MyPassword', 'data': data})
You can ignore login and password just in case your backend doesn't require verification.
Welcome to ask me if you have any problem about this.

How to update the page when file was updated? (js)

I have a json file on my ftp Server that's called "Series.json".
My question is like how can I update my website without reloading the page when I upload my json file?
There is actually no real answer to this questions as there are a lot of different ways to achieve it.
Check jQuery documentation (assume you use it by looking at question's tags) for the .ajax() method. Ideally you would also build some backend service like /getMySeriesJson?lastUpdate=<timestamp>. If it has changed the server will return the file (contents). Otherwise the server could return nothing and set the HTTP status to 304 Not modified. Your frontend/consumer would then have to handle this responses accordingly.

Is there a way to get the form data easily with JavaScript?

I was looking on how to get values of form data that are passed with POST requests and found this answer.
I know you you can get GET query parameters quite easily in JavaScript doing window.location.search but is there a way to do similar for POST request or document.forms is my only option?
To expand on what RUJordan said:
When you do a POST, the information is sent to the server using an entirely different method and does not show up in the URL or anywhere else that JavaScript can get access to it.
The server, and only the server, can see it.
Now, it is possible to take some of the form data and fill JavaScript variables and/or hidden form fields so the server can pass data back down to the client.
If you need more help, you'd be better off opening another question explaining exactly what problem you are trying to solve.
Do you want javascript to see the data was POSTed to load the current page?
JavaScript does not have access to the request body (where the POST content is) that loaded the page. If you want to be able to interact with the POSTed parameters, the server that received the request would need to respond with the necessary data written back out on the page where javascript can find it. This would be done after the form was submitted, as part of the response to that POST request.
Or do you want to know what your page could POST form the forms that are on it?
Inspecting document.forms will let you see what could be POSTed later if those forms were submitted. This would be done before the form was submitted, without a request being made.

Using the MVC3 AntiForgeryToken in non-authenticated scenarios?

Through several threads I can see that the use of the MVC antiforgery token is overkill on areas of a site where a user is not authenticated.
I have an application that posts some information to mysite.com from site1, site2, site3, etc. Each site has a unique identifier that gets sent in the POST request through an asynchronous Javascript POST. The Javascript that is executed on site1-3, is generated on mysite.com, then returned to the sites with some Javascript variables populated.
So the lifecycle is as follows:
A page on site1 has a Javascript reference to mysite.com.
That link reference is to a controller route that generates Javascript to return to site1.
The end of the JS that is returned contains a POST request that goes back to mysite.com containing Url, browser, etc., details for the visitor of the page on site1.
I can read in the POST parameters just fine in the accepting controller from the JS POST request, however, what I wanted to know is if there is any point in adding an antiforgery token to the parameter list.
If so, I would have to generate it on the initial request, and pass it back as a JS variable in the JS returned to site1, then pass it back along with the form POST in the second request.
Since any processing on mysite.com will only occur if a valid account is found, is there any point in going through this?
If so, how would I generate the antiforgery token on at the controller level?
I would say that it depends on the sensitivity of the data that is being posted. If another user could cause harm (or annoyance) by crafting forged requests and submitting them, then I would say that it would be appropriate. It sounds like you're just collecting some usage information so that's not likely to be the case.
A one-time, random nonce might be a better solution. That would make it difficult to forge a request and prevent erroneous multiple submits, say from the user using a cached copy. Generate a random value (a GUID might work) on mysite.com, inserting it in the database and marking it as unused. Send it back with the POST. Check whether it has been used or not. If not used, then mark it used and perform your logging action. If it has been used already, discard the request as a duplicate submission.
Note that you wouldn't need a POST for this, a simple GET with URL parameters would be sufficient since the nonce will prevent it from being accidentally repeated.

Categories

Resources