I have hit upon a problem with breeze validation.
It seems highly likely that the root cause of this particular problem is due to what looks like a design flaw in breeze. Specifically, that validation errors are not assigned a copy of the validation message generated by its validator. Instead the message is generated each time using the context last supplied to the validator.
This would not be a problem until you realise that validator errors generated from the same validator all share a reference to that same validator instance and that this validator instance uses the last context that was supplied to it to form the validation message.
The consequence of the above is probably best explained with the following scenario:
you have more than one instance of the same entity bound to a page
both entity instances break a rule defined by the SAME validator instance
for each entity instance, different context values are used
the two error messages generated for BOTH validation errors are determined by the last context supplied to the validator
therefore the message for the first validation error uses the context supplied for the second
Like I say, I think this is a design flaw but am happy for explanations why this isn't the case AND alternative means for avoiding the above scenario that don't feel like a hack.
Thanks
Related
I ran into this issue: our SpringMVC Validator validates a form (the normal case); this works OK.
Also, in a separate use case, it needs to be called remotely from a different location to put an exclamation point icon ("!") in front of some element on a different screen that refers to that form object.
I can validate any object of the class supported by the Validator, but the issue is how to add errors:
1) On the one hand, this Validator should reject errors for the path on its screen when it's used in the normal case:
errors.rejectValue("object.field.path", "errorCode", args, defaultMessage);
2) On the other hand, this will fail when it's called remotely, this path doesn't exist because the form is different. The only thing I can do here is something that doesn't depend on paths,
errors.rejectValue("errorCode");
Ideally the same Validator should respond to both cases... It should tell me there are validation errors on the form. In Case A it's specific, in Case B it's general. Can anyone advise how to approach this?
UPDATE The issue is general Bean Validation vs. GUI Validation. I understand is that SpringMVC's Validators are strongly tied to the GUI. But we also need a generic way to validate data beans, and hopefully reuse that. Or maybe I can create a "mock" BindingResult/JSP?
Most (almost all?) validation frameworks are based on reading object's property value and checking if it obeys validation rules.
Do we really need it?
If we pass valid parameters into object's constructor, property setters and other methods, object seems to be perfectly valid, and property value checks are not needed!
Isn't it better to validate parameters instead of properties?
What validation frameworks can be used to validate parameters before passing them into an object?
Update
I'm considering situation where client invokes service method and passes some data. Service method must check data, create / load domain objects, do business logic and persist changes.
It seems that most of the time data is passed by means of data transfer objects. And property validation is used because DTO can be validated only after it has been created by network infrastructure.
This question can spread out into wider topic. First, let's see what Martin Fowler has said:
One copy of data lies in the database itself. This copy is the lasting
record of the data, so I call it the record state.
A further copy lies inside in-memory Record Sets within the application. This data
was only relevant for one particular session between the application
and the database, so I call it session state.
The final copy lies
inside the GUI components themselves. This, strictly, is the data they
see on the screen, hence I call it the screen state.
Now I assume you are talking about validation at session state, whether it is better to validate the object property or validate the parameter. It depends. First, it depends on whether you use Anemic or Rich Domain Model. If you use anemic domain model, it will clear that the validation logic will reside at other class.
Second, it depends on what type of object do you build. An Framework / operation /utility object need to have validation against object property. e.g: C#'s FileStream object, in which the stream class need to have valid property of either file path, memory pointer, file access mode, etc. You wouldn't want every developer that use the utility to validate the input beforehand or it will crash in one operation, and giving wrong error message instead of fail fast.
Third, you need to consider that "parameter can come in many sources / forms", while "class / object property only has 1 definition". You need to place the parameter validation at every input source, while object property validation only need to be defined once. But you also need to understand the object's state. An object can be valid in some state (draft mode) and not in other state (submission mode).
Of course you can also add validation into other state level as well, such as database (record state) or UI (screen state), but it also have different pros/cons.
What validation frameworks can be used to validate parameters before passing them into an object?
C#'s ASP.Net MVC can do one kind of parameter validation (for data type) before constructing into an object, at controller level.
Conclusion
It depends entirely on what architecture and kind of object you want to make.
In my experience such validations were done when dealing with complex validation rules and Parameter object. Since we need to keep the Separation of concerns - the validation logic is not in the object itself. That's why - yes we
we really need it
What is more interesting - why construct expensive objects and later validate them.
It seems like official way to validate models in Laravel 4 is through Validator in Controller? Can somebody point out why is it so?
Wouldn't it make more sense to implement validation in Model?
I prefer the Ardent package for making validation of models as smooth and minimal as possible. To me it makes more sense to have the validation rules in the model as well.
It will return false when $model->save() is called and validation fails, then you can get the error messages through $model->errors()->all() for example.
It does make sense to have validation in the models, but this validation should only be there to make sure you don't save any corrupt data.
The Validator is in the Controller because it's used to handle Input, and generate Output.
If you would do the validation in the Model then you either have to return false, and show the user the most random of error messages about invalid data.
You could also return some kine of array containing all the errors that are generated, but that's something a Model shouldn't do.
Or you could throw an Exception, which is something that should be done when a model tries to consume invalid data, but it kills the application, which is not the wanted solution for a form validator.
When doing the form validation in the Controller, you can do everything you want with the error messages, without changing the purpose of a Model.
And in your model you can do a validation to make sure you didn't make a mistake, which will corrupt your database. Because if this happens the application should shut down.
So to put this in a real answer to your question:
Validation in the model makes sense to avoid corrupt data, but if you want to give feedback to the user about invalid input, it should be in the controller.
I wrestled with this for a while and settled on handling most of my validation in a validation service, based something along the lines of this. I can then have different validation rules based on the context.
As Nico mentions, validation in the model is good to avoid corrupt data, but I prefer thin controllers so I pass the functionality that would sit in controller into the service. This also has the benefit of being able to reuse the validation in different controllers/methods.
Why I prefer In-Model Validation: I've worked with both styles and each have pluses and minuses, but I prefer in-model validation. In our current app I don't see in-controller validation as an option, since we're altering our data in so many places (dedicated forms, inline edit, bulk edit, bulk upload, api, etc). I've never really worked with validation services (though they might be an option) but I personally like to keep logic as close to the model as possible, that way I know another developer won't bypass it. I also don't like adding lots of extra files on top of the MVC and basic Libraries folder because it just seems like more you have to think about organizing properly.
Issues with In-Model Validation: These are some things you need to consider to make In-Model work well. SOME OF THESE ARE ALREADY TAKEN INTO CONSIDERATION BY PLUGINS. I think other frameworks (CakePHP) already deal with these, but Laravel doesn't really.
Values that will be validated but not saved to the db (e.g.,
"accepted_agreement").
Many to many or belongs to many
relationships
Setting conditional defaults (not critical but
might want to think about at the same time)
Various form scenarios - sometimes you might need different validation
depending upon which form submits it. The form reference can be a
purgeable attribute for validation maybe?
How will you get back error messages (all in-model validation plugins handle this for you)
Different validation rulesets. Draft creation vs "real" creation. (Most handle this for you)
Ultimately, for simple applications that don't have lots of ways of interacting with the model, I'd say controller validation may be simpler, other then that I prefer in-model.
As far as I can see, the validation within Entity Framework is built entirely around the assumption that, if an item fails its validation, it must not be persisted to the database. Is there any mechanism, possibly running parallel to normal validation, of making a constraint on a field produce a warning to the user, rather than an error which prevents the record from being saved/updated?
To be more specific, I have a situation where a particular numerical field has limits on it, but these are advisory rather than hard-and-fast. If the user enters a value outside these limits, they should get a warning, but should still be able to save the record.
In theory, I could subclass the ValidationResult class to make, say, a ValidationWarning class, then create a custom subclass of ValidationResults whose IsValid property was sensitive to the presence of ValidationWarning messages, and ignored them in deciding whether the entity is valid. However, this requirement has arisen in a project which is already someway along in its development, and it would require a lot of refactoring to make this kind of custom subclassing work properly. I would prefer to find a mechanism which could be levered in without creating that much disruption/rework.
I had a similar requirement on a project and how I solved it was this. If (ModelState.IsValid) is false, I cleared out the errors out of the ModelState and sent it on its way again,then logged the "error" to another service. This is a bit of a hack and I would'nt recommend doing as it is not exactly best practice.
I'm creating interfaces and abstract classes that represent a messaging framework for short text-based messages like SMS, email, twitter, xml, etc.. and I was wondering where I should put the message validation code.
The thing is that I am only writing the superclasses and interfaces, so I'm not putting the actual implementation in, I'll just put the hooks in that allow others to validate the content of the messages. The way I see it, I could do it several ways:
in the abstract superclass "Message", have an abstract method 'isValid'. A variation on this would be to have isValid be called when the Message constructor is called, throwing a MalformedMessageException if the message is formatted incorrectly.
in the transport layer, immediately before sending, validate the message. I would have a send(Message) method that calls an isValid(Message) method immediately before it sends.
have a singleton message validator with a static method isValid(Message) that is called at some point.
I'm sure there are other options that I'm missing. Currently, I'm leaning towards the first one, but it doesn't feel right to me to have validation code in what should be a domain object.
Message is one thing. A container of data.
Validation is a separate thing. Validation is separate from the Message because validation depends on non-Message data. Validation includes one or more algorithms that establishes if a valid Message could be built from some data.
You want Messages to be built only when they're valid. You want all of the the methods of a message to require and depend on validity. That gives you easy-to-understand responsibility.
Therefore, a Message should not contain any validation logic. That logic lives just outside the boundaries of a valid Message. It's part of a MessageFactory or MessageValiadtor that determines if some given puddle of data could be used to build a valid Message.
You have two things: MessageValidator (or MessageFactory) and Message.
There is no isValid in a Message. It must be valid or it would not exist.
MessageValidator builds Messages from source data. If it cannot build a message can can throw an exception. It should also accumulate the list of errors it finds so it can be interrogated to determine what the various problems were.
Consider the possible mutations: Multiple variant subclasses of Message. The Validator may identify a specific subclass. No application changes are required to implement this.
Multiple Validators for special situations, exceptions, extensions, etc. It's just a subclass of MessageValidator with the same interface all validators have and emits an instance of Message (or one of it's subclasses.)
Since the validation rules are separate from a valid message, the Validator can provide different assumed defaults or derived data, also.