I have a hierarchical model in MVC3. All my basic validation is working, but I have a special validation that I can't figure out how to implement.
In my particular tree-hierarchy model, I have a field which must be unique/not repeat the values in any of its ancestral nodes. In my case, peers do not have to be unique.
I've tried to inherit ValidationAttribute and use validationContext.Items to store a stack of parent nodes, but it doesn't seem to me that the validationContext.Items is shared between the validation of each level. I don't know how to recursively call the validation on each child correctly, if that is appropriate.
If I'm Validating a particular node, I need access to the ancestral nodes, or some stack I create of the ancestral nodes passed to each child.
The solution shouldn't interfere with other validators or binders and should provide field-level errors rather than root-model level errors. I also want to avoid ThreadStatic, reserved strings, and other magic tricks. Yes, the entire hierarchy is bound in a single view using this technique.
Thanks!
Could you create an action filter? This give you access to the modelstate and valueProvider so you could check the data and then adjust the Errors collection as necessary.
public class ValidateForUniqueAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
// filterContext.Controller.ViewData.Model
// modelState[key].Errors.Add( .... )
}
}
[ValidateForUnique]
public class YourController : Controller
Related
If Controller first validates ViewModel properties and then uses ViewModel properties, there may be small chance that ViewModel state may change to invalid between validation and usage, resulting in exceptional control flow.
Is there any common practice or pattern to ensure ViewModel state doesn't change and / or properties can be safely used after validation?
By keeping the state immutable, you can ensure that there is no change between validation and usage.
For instance:
class MyViewModel {
property MyImmutableState state;
}
class MyController {
private MyViewModel viewModel;
private doSomething() {
MyImmutableState state = viewModel.state;
if (isValid(state))
// because state is immutable, this is thread-safe
doSomething(state);
}
}
The key to making this work efficiently is that MyImmutableState should be not only immutable but also a persistent data structure (i.e. a data structure that keeps its old versions while being modified, typically via structural sharing). Libraries for such immutable collections exist in different languages.
Javascript: Immutable.js
.Net: System.Collections.Immutable
Java: http://www.javaslang.io/
Python: pyrsistent
Any function you apply to such a collection will return a new collection and leave the original one untouched. This way, the collection can be shared safely, without the need for locking.
It is a good practice to load as less data as possible from the database through business operations. And sometimes using directly the entity(model) object as the command object is not secure. So what should be the approach on selecting the command object? Using a separate command object for each view does not make sense.
Use cases or a nice resource is appreciated. Thanks.
It's true you may have some security concerns when using domain objects as command objects, Spring tries to bind every single parameter to the command fields, so a user could add extra parameters in the request to modify fields that were not supposed to be bound. In case you go for this approach, make sure to define either a white list or a black list of parameters to be bound:
#InitBinder
public void initBinder(WebDataBinder binder) {
binder.setAllowedFields("firstName", "lastName");
}
or
#InitBinder
public void initBinder(WebDataBinder binder) {
binder.setDisallowedFields("id", "creationDate");
}
The alternative is to create an extra class for the form. This class can adapt better to the UI needs if your domain objects don't match what you need in the view layer. This class can encapsulate any web logic, validation and the logic to copy to/from a domain object.
So I would say, going for domain objects is fine as long as you set a white / black list and you don't modify it because of UI needs (adding extra fields or extra logic in the domain object), otherwise you should create an additional command object.
After my wonderings on the events registration (you can find here ViewModel Event Registration and ViewModel Lifetime), now I'm thinking about viewmodel tombstoning:
In case of Tombstoning, is the ViewModel serialization a good approach ?
I'm thinking about the case in which different viewmodels have a reference to the same class. In case of Viewmodels serialization and deserialization the referenced class instance could have duplicated instance, isn't it ?
Wouldn't be better to have specialized state classes whose unique purpose in to contain all the app data, everyviewmodel get data (i mean reference to the data) from there and update the data in there and the app think only to serialize those specialized class ?
Any experience on this subject is appreciated.
Regards
SkyG
Caliburn Micro has a lot of this built in to the framwork allowing you to save properties of a view model or the entire graph to both phone state and app settings. You just need to create a class and inherit from StorageHandler.
public class PivotPageModelStorage : StorageHandler<PivotPageViewModel>
{
public override void Configure()
{
this.ActiveItemIndex().InPhoneState().RestoreAfterViewLoad();
}
}
And to your other posted question. CM has a nice way of handling the forced view first approach on the phone. It allows you to do page navigation by specifying the VM and it will handle the rest. And as a bonus, if you specify parameters to pass CM will pull them off the query string and populate properties on the target VM.
public void GotoPageTwo()
{
navigationService.UriFor<PivotPageViewModel>().WithParam(x => x.NumberOfTabs, 5).Navigate();
}
We are working on an ASP.NET MVC 3 using ext.net and EF 4.
Data model is mapped using EF4.
Views’ content is rendered from customizable XML files.
Example: Within one view, I can display fields that are related to both objects “customer” and “order”, so from this view I can modify the customer data and also add a new order.
How can we bind the view to the custom model that contains 2 objects (customer and order)? Using non strongly typed views will require a source code that will check all different possibilities (If I remove/add a field to display from the XML file, object constructor and CRUD operations parameters will change also.
We are wondering how can we handle such dynamic application?
Is this a common issue that was raised before? Or is there any solution to use dynamic views bound to custom model (object, xml, etc.)?
Your help is very appreciated, please enlighten me.
Based on what you replied to my comment, I can defenitely say that you need strongly typed views. That said, you decide what the model of your view is. If your view needs to manage users and orders at the same time, you can make a class like this:
public class MyCustomViewData
{
public IEnumerable<User> Users {get;set;}
public IEnumerable<Order> Orders {get;set;}
}
and then strongly type your view to MyCustomViewData and you're set. My example is oversimplified but I think you can get the point.
Unless I'm missing something, I believe the normal way round this would be to strongly type your view to say 'user' and then on the user object, define a property which is a collection of 'orders'.
I have two fields and I need to generate an attribute, using Microsoft Enterprise Library validation, so that either or has to have a value, but both can not be null at the same time.
Use a custom validator.
[HasSelfValidation]
public class ValidateMe {
[SelfValidation]
public void ValidateFieldNotNul(ValidationResults validationResults)
{
.. start psudo code
if( xor)
validationResults.AddResult( new ValidationResult("One must not be null",...));
}
}
The Validation Application Block has a PropertyComparisonValidator which will let you compare one property with another. Unfortunately, this validator only allows a ComparisonType of: Equal, NotEqual, GreaterThan, GreaterThanEqual, LessThan, LessThanEqual so this doesn't actually help you.
I think you have 2 options:
Self Validation
Custom Validator
Self Validation (shown by #Nix) is probably the easiest but would require this to be reimplemented for every scenario where you have that requirement (at least to put the hooks to call a common method).
Creating a custom validator would result in code that could be added to the configuration or attributed directly on entities and that could easily be reused.
A custom validator will definitely be more work but may be worth it if you need the reuse (it can be reused across applications, for example) or prefer that design.