How to maintain serverside validation and clientside validation - javascript

When we have some controls in ASP.NET, it's of course preferable to use both clientside and serverside validation. Clientside for usability purposes, and serverside for security purposes.
However, this easily gets quite ugly. Of course, if your validation is a length check or a regular expression, it is easy to maintain. However, let's say that your validation is more advanced - what to do?
One way is to implement the exact same functionality in both server code and Javascript. Another way is that both calls a webservice with the same logic, but then your AJAX call has to be synchronous which in general is bad practice.
So, my question is, what's the best way to perform both serverside and clientside validation?

Your ajax call does not have to be synchronous for validation; it just needs to be quick:
When the user tabs off a field, say, an ajax call is made to the service and the field displays a spinner next to it, indicating the server is validating the data.
If the service returns success, the spinner is replaced by a green check mark.
If the service returns failure, a red X, perhaps with explanatory text.
When the user finally clicks submit, the same validation takes place on the server (synchronously or not).
Another option (besides #user133811's of using JS is both places) is to find a cross-compiler, which will compile your language of choice into JavaScript. These may or may not be available, however.
I've generally found that doing complex validation on the client is unnecessary and undesirable. Yes, let me know a field is required, or if a username exists (via ajax), or simple things, but if this is a complex mortgage application or something, I expect I'll have to submit before finding out I need to include my W2 if I declare my pet goldfish as co-signatory (or whatever, you get the point).

the same code for server and client would mean that your server needs to use JS. Node could be something you could potentially use.

Related

Angular JS and Symfony2

I am currently working on a project using Symfony2 and seeking some advice on that.
I am thinking of a hybrid application in two(2) different ways a) Login Page shall use traditional form with CRF Token and let symfonty2 handle it. b) All Inner pages ( which potentially are modules ) I want them to be non AJAX, but the other activities inside that shall behave like a Single Page.
For example I have an employee module. When user clicks on that it is entirely loaded from Server ( all the templates and forms etc ) now each activity under employee module like add/update delete/view etc shall be loaded through AJAX and response to be returned in JSON i.e AngularJS.
I am currently thinking of using FOSUserBundle to return html on initial request and then based on request type Accept: application/json it will return the JSON ( remember the add/updat delete/view part? ).
My question is it a better idea to use Angular Partials (html) files or Symfony2 Twig? or would it be better to use Angular JS, but let those partials be rendered by Symfony2 twig? ( I am thinking of Forms here, would want to validate that both from client and server side )
Has any one been through similar problem, if yes then what approach was used to develop HYBRID application using AngularJS and Symfony2 or any other framework? any relevant ideas are appreciated.
I was in the same situation you are. AngularJS+Symfony2 project, REST API, login using FOSUserBundle, etc.
... And every way has pros and cons, so there is no right way, i'm just gonna say exactly what i did.
I choose AngularJS native templates, no CSRF validation, a base template built using Twig, server-side validation, use of the FOSJSRoutingBundle, and some helpers (BuiltResponse and BaseController).
Why native templates?
With the use of verbatim, we solve the variable problems, but we gonna have a more complex logic in our templates.
We also will have a less scalable application. All our forms templates are doing a request in the Symfony application, and one of the best pros of the AngularJS is load our controllers, templates, etc from a storage service, like S3, or CDN, like Cloudfront. As there is no server-side processing, our templates would load so much faster. Even with caching, Twig is slower, obviously.
And both, Twig and AngularJS templates, are really complex to manage, in my own experience. I started making them together, but was painful to manage.
What i did?
I created static templates in front-end, with the same field names, it's not really good. We need to update the templates every time we update the forms, manually. But was the best way i found. As the field names are equal, we won't have problems to ajust the model names in the Angular controllers.
And if you are creating the software as a service, you will need to do it anyway. Will you not load the form templates from the application in a mobile app, right?
Why no CSRF validation?
We don't use CSRF validation in a REST API, obviously. But, if you wanna do it, you need to make a request every time you load a form, to get the CSRF token. It's really, really bad. So, we create a CRUD, and also we need to create a "csrf-CRUD", 4 routes more. That doesn't make any sense.
What i did?
I disabled the CSRF in the forms.
Base template?!
Yep. A base template is just to load any route in our application. Here is what i'm doing:
This will help us to avoid errors when users are going directly to some Application URL if you are using html5 angularjs urls. Simple like that.
Server-side validation, why?
If we do a validation in the Angular, we need to do the same in the server-side, so we have 2 validation codes to maintain. That is painful. Every change we do in the form, we need to change the validation in the front, validation in the back and also the Angular static form. Really, really painful.
What i did?
I basically did a server-side validation using the Symfony constraints. For every request, the application validates the form and check if any error was found, if yes, it gets the first one and send it as a response.
In the AngularJS, the application checks if there is any error inside of the errors key. So, we have a proccess used in all application to do any form request. It's like that:
And the routes?
There is another problem: the routes. Put the url directly is not a reliable way. If we change anything in the url, that route is gone and the users won't like that.
To fix that, we can use the FOSJsRoutingBundle. With that library, we can put the route name directly in the Angular controller, and it will fill with the exact url of the route. It's completely integrated with the Symfony, so parameters will work very well.
Instead using the url directly, we can do it:
Routing.generate('panel_products_show', {id: $routeParams.product_id});
And voilá! We get the route url.
That will solve the biggest part of the problems you have. But there are more.
Problem 1 - Form inputs
The forms from Symfony generally have a prefix, like "publish_product", so every field has a name like [publish_product]name. Ah, how that was a problem for me.
In the Angular, publish_product is not considered a array. You need to put the single quote to do this, like ['publish_product']name. And it's really bad, we need to change every key to use this format. In AngularJS, i was doing like that:
{{ formData('[publish_product]name') }}
Absolutely stupid.
The best solution was simply remove the form prefix in the Symfony, using the createNamedBuilder method instead just createBuilder. I let the first parameter null, and yeah, we don't need to use the prefix anymore. Now, we use:
{{ formData.name }}
So much better.
Problem 2 - Routes hard do maintain
Every request can return anything, i need to repeat much code. That is really hard to maintain, so i just create some application rules, built responses, a BaseController, etc.
createNamedBuilder
createNamedBuilder is a big method. We need to do this, for every form we have:
It's simple to solve. I just created a BaseController and i'm extending every controller from it. I created a simple method that does it.
For every route, we do not need to repeat 3 lines, much better.
Responses
When my application started growing, i had a serious problem: all my responses are different. That was really hard to maintain. For every request i was doing, sometimes i was using "response", sometimes "data", the error messages were lost in the response, etc.
So, i decided to create a buildResponse, that i just need to set some parameters and i get the same result for every route, even GET routes.
response key shows me the status and the message. It can be error or success, and the message os a optional field, that can come blank. For example, a success status with the message "You created the product".
data key shows me any information i need. For example, the user added the product, and now he needs the link to see it. In the data, i put the url of the post, and i easily can get it from the AngularJS controller.
notifications is a specific key for my business logic. Every action can return a notification to the user.
It doesn't matter what keys you have. The most important thing is have a standardized response, because when your application grows, it will be really helpful.
That is a route from my controller:
Completely standardized. The Scrutinizer code quality tool says all my routes are duplicated. :D
Have a BaseController and a builtResponse will help you so much. When i started refactoring my code, each route lost about 4-10 lines.
Details: getFormError return the first error of the form. Here is my method:
public function getFormError(FormInterface $form)
{
if ($form->getErrors()->current()) {
return $form->getErrors()->current()->getMessage();
}
return 'errors.unknown';
}
... And the parameters from the buildResponse are:
1. Status. I get it from a constant in the BaseController. It can be changed, so i believe is important do not use a string value in each route.
2. The translation message. (I use a preg_match to check if it has a translation format, because getFormError already translates the error).
3. The data (array) parameter.
4. The notifications (array) parameter.
Other problem i'm gonna have
The project just have one supported language until now. When i start to work in a multilingual version, i'm gonna have another big problem: maintain 2 versions of the translations: the back-end messages and validations and the text from the front-end. That probably will be a big problem. When i get the best approach, i'll update this answer.
I took some months to get the this approach. So many code refactorings and probaly much more in the future. So i hope it help someone to do not need to do the same.
1. If i get a better way to do this, i'll update this answer.
2. I'm not good at writing english, so this answer probably will have many grammatical errors. Sorry, i'm fixing what i'm seeing.

Client-side validation based on models with Rails

I just want to use jQuery validation to show "real-time" errors for the user. The point is: I don't want to have a duplex-direction (client-side/server-side) validation for maintenance purposes.
So I ask: there's a way to communicate jQuery validation to ask just for the model's validation that is provided by Rails?
Or even better: we don't need to use jQuery validation specifically. Just tell me another/better way to solve my problem smoothly.
The simplest way to do this would be by creating a function in your controller that responds to JS requests. In that function you validate the data with the model and respond with any errors (which you can then process in JQuery).

inline editing with ajax (insert value to database)

This can be a UX question but it can also be technical. I'm building a list with ajax and PHP. I doubt I should manipulate the DOM before the backend is finish. What will be the problem if I don't use a loader to indicate the backend activities?
Well in general, as a concept of usability, you have to inform your user about the status of his/her requests. If an action takes too long and no indication exists that the request is being processed then the user might think that something doesn't work or got stuck. As a result the user will repeat the request a number of times. This won't give a chance to your site/app/program to complete its task resulting to frustration and even a belief that your product does not work.

Practical use cases for returning javascript from an XHR/Ajax request?

I've never really had to return javascript from an XHR request. In the times I've needed to apply behaviour to dynamically loaded content I could always do it within my script making the call.
Could someone provide actual real world cases just so I'm aware, of when you'd actually need to do this ( not for convenience ), or some reasons of why in some cases it's better to return js along with the other content instead of building that functionality in your callback?
The only scenario that's coming to my head is on a heavily customized site, if the site supports multiple languages for example and the functionality changes depending on the language, and ajax is used to pull in dynamic content and perhaps in some languages a certain behavior needs to happen while in others another needs to happen and it's more efficient returning js in script blocks instead of dumping all that logic into a callback.
Sometimes it is more convenient to "prepare" the JavaScript code on the server side. You can use the server's programming or scripting language to generate the code and you can fill it with values from the database. This way most of the logic takes place on the server and not the client. But it is really a matter of taste. OK, that wasn't a real world case but maybe my opinion is helpful anyway.
We use XHR to request an entire web page that includes java script for menus etc. We then replace the current page with the new one that has been sent over XHR

ajax and no forms, what will happen?

I notice my site does not have a single <form> with the exception of logging in. I am not sure how or why it happened but i found i use jquery and ajax to post everything then refresh (or not if i dont need to). How and why would the user suffer from this?
Some of my 'forms' include
Leaving a comment on a page
Removing messages
Sending a private message (which i then do document.location=nextPage)
Marking as a favourite.
Forgetting for a moment that none of the site would work without javascript disabled, another side effect you might not realize, is that there is no default submit behavior anymore. This means a user cannot finish typing their entry and hit enter to submit the form. This is important for search forms and the like, but less important for comment forms.
Wrapping form fields in a form tag and having a submit input element (even if it is display:none) allows for a default submit action on enter or return. If you do this, you simply call preventDefault() into the submit() event handler to stop the real submit, and make an AJAX one instead.
Ok, back to the JS disabled thought. You have to make a choice:
Work backwards to implement unobtrusive JS on your site. Basically, the site works with or without JS, but it will work better (or more refined) with JS enabled
Or place a prominent message alerting your users to the fact that your site requires JS for the site to work. The cons to this method is you might limit the usefulness of your site in some corporate networks and on some mobile devices. As far as people who willingly turn of JS, the alert can let them decide if they want to stay around or not.
Given that the site is already coded, take a look at your target audience and make your best decision given the time and energy required to make the site work without JS.
From your comment, I see that you don't intend to support users without JavaScript, so the accessibility and backward compatibility argument is moot.
However, you are likely creating a lot of unnecessary requests by posting with AJAX and then refreshing the page. This is not how AJAX was intended to be used and is possibly an anti-pattern. The idea of AJAX is to send specific and receive specific data, and to update the page based on that received data, not refreshing.
Also, by not using form's, you disable the default submit functionality (pressing <enter>) as Doug Neiner pointed out

Categories