I have a project, with a classic 3 tier structure: DataStore, BusinessLogic, Web-Frontend
In the DataStore I have a Model (simplified) e.g. ConfigModel.cs:
public class ConfigModel
{
[DataType(DataType.EmailAddress)]
public string DefaultSenderEmail { get; set; }
public IPAddress FallbackDNS { get; set; }
}
Here comes the question:
What's an elegant way to programmatically add Validators according to either the actual DataType, or the DataType Attribute?
A few answers that I have considered myself so far, but did not find them satisfactory:
Add an [EmailAddress] validation attribute to the parameter: I don't want duplication and I don't want any reference to MVC specific code in my DataStore Layer.
Make separate ViewModels and use AutoMapper: Since some of my models are a lot more complex than that, I'd hate to make specific ViewModels.
Thanks!
I would also consider using AutoMapper, but not as an answer to this solution.
Maybe you can consider this: http://weblogs.asp.net/srkirkland/archive/2011/02/15/adding-client-validation-to-dataannotations-datatype-attribute.aspx
That is not duplication. DataType is used for different purposes, and validation is different thing. Although they may sound the same (specifically for EmailAddress), you should not consider using both as duplication. Moreover, validation is automatically controlled for non nullable types - they are marked as Required. Datetimes are also checked for valid format automatically.
What you will definitely hate is controlling what properties of your domain model can be edited by users using BindAttribute and controlling different validations on same model, when using different views. So go for using ViewModels! Decorate them with all the attributes needed for your web application and map back to domain models using AutoMapper
You also may also want to check out FluentValidation
Related
I'm using entity framework. It auto generated an Answer class. But I cannot modify this class as it will be overwritten if code is regenerated.
Is there a way/technique to add data annotations using this class?
The reason I ask is that I have a Create Answer view that uses the Answer class. Hence, I want to add data annotations such as Required, etc.
If I cannot add data annotations to the Answer class, then I have to create an "AnswerDuplicate" class, pass that into the view, and also use that in my Create() method. However, I then have to map all the values from AnswerDuplicate to an instance of Answer, since Answer is what I "add" to the entity.
Seems like extra work since Answer is autocreated (class and the binding in Create() method). Would be nice if I can just add data annotations.
If this is not possible, then is my only option to create an "AnswerDuplicate" class and use that in place of the Answer class?
My suggestion is: Use ViewModels.
I always consider creating a ViewModel when editing/viewing data - rather than passing the model object directly down to the view.
How Will This Help?
The logic to display it in the view (with Required, DataType and validation such like) can be left down to the ViewModel; while your Model is just left as a normal all-intents-and-purposes class (in your case, a generated one).
As an example, you could have an AnswerViewModel, which contains all of your display/validation logic, to then use in your corresponding View.
How Do I Save Time Mapping Properties?
You can use AutoMapper (or other similar auto-mapping packages) to then automatically map the properties between your model and the view model, for easy updating of entities etc.
This then saves you time having to write lines-upon-lines of code to update entities - which may essentially need to change over time - this can be a big problem (and a huge PITA) if refactoring/adding extra properties across different classes.
How Does This Help Going Forward?
Well, because you are not leaving the logic up to your class:
Let's say you have 3 different views for different purposes (Add, Edit, Delete)
If (for some reason) you need to show/display something differently in only one particular view, you are able to just apply/change the logic in the relevant ViewModel; rather than worrying about updating the Model and having breaking changes affect everything else.
Here is a handy tutorial on How To Use ViewModels In MVC: http://rachelappel.com/use-viewmodels-to-manage-data-amp-organize-code-in-asp-net-mvc-applications/
I do hope this helps, somewhat :)
If you need me to provide any examples - just let me know.
I think the best solution is to use ViewModels as #Geoff James said, but if you don't like to add different classed you can write a partial class and add the MetadataType attribute to it and the add the attributes you want like Required to its properties.
public partial class Answer // this is auto-generated
{
public long AnswerID {set; get;}
}
[MetadataType(typeof(Answer ))]
public partial class Answer // this is what you can write
{
[Required]
public long AnswerID {set; get;}
}
remember that both class must have a same namespace.
And other solution to your problem is the you can switch to Code First
Background
I like Jeffrey Palermo's Onion Architecture model (similar to Hexagonal Architecture) which prescribes that the Domain Model be at the 'center' and the concrete implementations of infrastructure, specifically Concrete Repositories be on the periphery.
So say I have a Domain Model:
//https://libphonenumber.codeplex.com/
using libphonenumber;
namespace MyApplication.Domain
{
public class Speaker
{
public virtual string Name {get;set;}
public virtual PhoneNumber PhoneNumber {get;set;}
}
}
Now I need to expose this Domain Model to other teams:
The UI Team hypothetically wants to add several Data Validation attributes and custom JSON serialization attributes.
The Infrastructure Team hypothetically wants to add XML Serialization attributes and some custom attributes from a 3rd party Database implementation.
The Public API Team hypothetically wants to add WCF attributes.
I don't want to give every team carte blanche to add their Attributes to my Domain Model and I especially don't want them adding all of their "layer specific" dependencies to my model assembly.
And this case is made more complicated because I'm using 3rd party 'domain models' in my own (in this case using Google's LibPhoneNumber to handle the Phone Number).
Ideally, they'd each need to create their own wrapper class like:
using MyApplication.Domain;
namespace MyApplication.UI.DomainWrappers
{
public class UISpeaker
{
private Speaker _speaker;
public class UISpeaker(Speaker speaker = null)
{
_speaker = speaker ?? new Speaker();
}
[Required]
public virtual string Name {
get{ return _speaker.Name; }
set{ _speaker.Name = value; }
}
[Required]
public virtual PhoneNumber PhoneNumber {
get{ return _speaker.PhoneNumber ; }
set{ _speaker.PhoneNumber = value; }
}
//Conversion operators
public static implicit operator UISpeaker(Speaker s)
{
return new UISpeaker(s);
}
public static implicit operator Speaker(UISpeaker s)
{
return s._speaker;
}
}
}
Question
Writing and maintaining the UISpeaker class is a pain and is boring boilerplate code.
Is there either a better way to add the Attributes each team wants to add without letting them directly edit the Domain Model? Or is there some tooling that can help generate these wrapper classes (I was thinking possibly a weaving tool like Fody or T4 Templates, but I'm not familiar enough with either to know if they could help in this use case).
Research
I looked around Stackoverflow and found some similar questions, but none that hit the full scope I'm looking for:
Avoid using the JsonIgnore attribute in a domain model - Concluded to just use .NET native attributes on the Domain Model so you didn't have to take a dependency on Json.Net
Add an attribute to another assembly's class - Discussed using CustomReflectionContext to add Attributes to an existing type. This looks really cool, but unfortunatly, the model would be handed off to 3rd party code (ORMs, EF, Json.Net, etc) for reflection so I don't think this will work here.
Having Separate Domain Model and Persistence Model in DDD - Confirmed that each layer should have it's own version of the Domain Model, but didn't discuss if there's any tooling / strategies to make writing / maintaining that code any easier.
You can use these options to simplify the job:
Metadata Classes
Object to Object Mappers
Code Generation
Metadata Classes
You can create metadata classes and add attributes like data annotations and validation attributes to those metadata classes and then relate these metadata classes to your main domain classes using AssociatedMetadataTypeTypeDescriptionProvider. Such metadata classes are only attribute containers and using type descriptor mechanisms add attributes to your main classes.
For example, you can register a metadata class for your model this way, and let all infrastructures that benefit TypeDescriptor see your metadata attributes for your model:
var provider = new AssociatedMetadataTypeTypeDescriptionProvider(typeof(Model),
typeof(ModelMetadata));
TypeDescriptor.AddProvider(provider, typeof(Model));
Object to Object Mappers
You can have view models, business models and domain models in different layers and using decorate them with attributes that you need for each layer, then using an object to object mapper like AutoMapper simplify the task of mapping those classes to each other.
AutoMapper is an object-object mapper. Object-object mapping works by
transforming an input object of one type into an output object of a
different type. What makes AutoMapper interesting is that it provides
some interesting conventions to take the dirty work out of figuring
out how to map type A to type B. As long as type B follows
AutoMapper's established convention, almost zero configuration is
needed to map two types.
Code Generation
You can make creating metadata classes or view model classes more easy using some code generation tools. For example you can create the wrapper classes simply using a code generation mechanism like T4 Templates.
In Visual Studio, a T4 text template is a mixture of text blocks and
control logic that can generate a text file. The control logic is
written as fragments of program code in Visual C# or Visual Basic. The
generated file can be text of any kind, such as a Web page, or a
resource file, or program source code in any language.
I'm using DataAnnotation for client and server validation of my view model. I would like to ask you about the best practices of using custom validation.
I have two forms, which use the same view model:
public class RecipientViewModel
{
[Required]
public string Address1 { get; set; }
public string Address2 { get; set; }
}
What I want to achieve, it is that the first form should validate the Address2 field, but the second form did not. Of course my view model is much bigger and I want to do it generic as much as possible.
Is there any possibility to pass a list of fields to be validated and how? For example view could pass it to view model somehow?
Please clarify your question or show more code.
In general the Annotations are very good to check expected structures or a certain kind of expected data. Like length, presence, type.
For other more complicated, complex business cases. Good implementation will have a business layer or a domain design which handles these use cases.
So define your use cases and think about an layer between controller and data model. Maybe something like a validation Services which gets injected into the viewmodel.
HTH
EDIT: You probably want to take a look at - Validating with a Service Layer from the ASP.NET site - http://www.asp.net/mvc/overview/older-versions-1/models-(data)/validating-with-a-service-layer-cs] which shows some of the conepts - the technology might have changed slightly since the article is from 2009 but you got the idea.
I have just started working on an MVC project and things are going ok but it looks like I am creating alot of spaghetti code with just too many objects. Can anyone see how I can simplify this solution before the whole projects gets out of hand?
ok, here's my set up:
DAL - has Entity framework connections and methods to obtain data then convert the data to my model objects in the model layer
BLL - sends the data back up to the UI
Model - this contains all the model objects that are used throughout the site, anything coming from the DAL is converted into these objects by creating a new object then populating the variables.
UI - my MVC solution
The DAL,BLL and Model are also used by other solutions.
Now with MVC, I am trying to use the validation annotations ([Required], etc) which means I have to re-create the model objects with the annotations. This is fine but if I want to save the data back into the database I need to convert the classes which is just messy.
Can anyone see how I can use my current model class library with MVC model objects that use the validation annotations?
If I have not explained myself clearly please let me know and I will provide more details.
Thanks
Ideally there needs to be a separation from the domain models on one hand and MVC models (they are really ViewModels) on the other hand. This separation is really crucial and strongly advised.
These will look a lot similar in most cases although ViewModel can contain extra stuff. Then you can use AutoMapper to convert from one to the other.
For example:
public class User // in entity DLL
{
[Required]
public string Name {get; set;}
}
public class UserViewModel : User // in MVC DLL
{
public string LastVisitedPage {get; set;} // which only MVC needs to know
}
Mapper.Map<User, UserViewModel>();
Mapper.Map<UserViewModel, User>();
you can put the metadata in metadata objects without recreating the model objects. Here is a very simple way of doing it, however it does require that the model objects themselves are marked as partial. I hope that is OK if not this solution will not work for you.
[MetadataType(typeof(PreviousResultsMetaData))]
public partial class PreviousResults
{
public class PreviousResultsMetaData
{
[DisplayName("Class Ranking Score")]
[Required]
[Range(0.0, 100.0)]
public object ClassRankingScore { get; set; }
}
}
in the example above there is a data model object called PreviousResults that is created elsewhere by some scaffolding code. It defines the POCO object that is sent to and from database using LINQ. The MetadataType attribute indicates the class that will be used to hold the metadata. Then you simply create plain objects that match the names of your real data members and annotate them.
I hope this helps.
You can use FluentValidation framework for validation. Look here
http://fluentvalidation.codeplex.com/
You can perfectly add attributes to your BLL (the business entities). Just add a reference and add a using statement for System.ComponentModel.DataAnnotations. Apart from that, you can implement the IValidatableObject interface (which is pretty easy, see below).
For the mapping, you can use for example AutoMapper, so you don't have to write to much of mapping logic yourself (if you can take advantage of the name mapping magic).
Validate example:
ICollection<ValidationResult> validationErrors = new List<ValidationResult>();
var validationContext = new ValidationContext(this, null, null);
Validator.TryValidateObject(this, validationContext, ValidationErrors, true);
return validationErrors;
I have a business model with many classes in, some logical entities within this model consist of many different classes (Parent-child-grandchild.) On these various classes I define constraints which are invariant, for example that the root of the composite should have a value for Code.
I currently have each class implement an interface like so...
public interface IValidatable
{
IEnumerable<ValidationError> GetErrors(string path);
}
The parent would add a validation error if Code is not set, and then execute GetErrors on each child, which in turn would call GetErrors on each grandchild.
Now I need to validate different constraints for different operations, for example
Some constraints should always be checked because they are invariant
Some constraints should be checked when I want to perform operation X on the root.
Some additional constraints might be checked when performing operation Y.
I have considered adding a "Reason" parameter to the GetErrors method but for a reason I can't quite put my finger on this doesn't feel right. I have also considered creating a visitor and having a concrete implementation to validate for OperationX and another for OperationY but dislike this because some of the constraint checks would be required for multiple operations but not all of them (e.g. a Date is required for OperationX+OperationY but not OperationZ) and I wouldn't like to have to duplicate the code which checks.
Any suggestions would be appreciated.
You have an insulation problem here, as your classes are in charge of doing their own validation, yet the nature of that validation depends on the type of operation you're doing. This means the classes need to know about the kinds of operations that can be performed on them, which creates a fairly tight coupling between the classes and the operations that use them.
One possible design is to create a parallel set of classes like this:
public interface IValidate<T>
{
IEnumerable<ValidationError> GetErrors(T instance, string path);
}
public sealed class InvariantEntityValidator : IValidate<Entity>
{
public IEnumerable<ValidationError> GetErrors(Entity entity, string path)
{
//Do simple (invariant) validation...
}
}
public sealed class ComplexEntityValidator : IValidate<Entity>
{
public IEnumerable<ValidationError> GetErrors(Entity entity, string path)
{
var validator = new InvariantEntityValidator();
foreach (var error in validator.GetErrors(entity, path))
yield return error;
//Do additional validation for this complex case
}
}
You'll still need to resolve how you want to associate the validation classes with the various classes being validated. It sounds like this should occur at the level of the operations somehow, as this is where you know what type of validation needs to occur. It's difficult to say without a better understanding of your architecture.
I would do a kind of attribute-based validation:
public class Entity
{
[Required, MaxStringLength(50)]
public string Property1 { get; set; }
[Between(5, 20)]
public int Property2 { get; set; }
[ValidateAlways, Between(0, 5)]
public int SomeOtherProperty { get; set; }
[Requires("Property1, Property2")]
public void OperationX()
{
}
}
Each property which is passed to the Requires-attribute needs to be valid to perform the operation.
The properties which have the ValidateAlways-attribute, must be valid always - no matter what operation.
In my pseudo-code Property1, Property2 and SomeOtherProperty must be valid to execute OperationX.
Of course you have to add an option to the Requires-attribute to check validation attributes on a child, too. But I'm not able to suggest how to do that without seeing some example code.
Maybe something like that:
[Requires("Property1, Property2, Child2: Property3")]
If needed you can also reach strongly typed property pointers with lambda expressions instead of strings (Example).
I would suggest using the Fluent Validation For .Net library. This library allows you to setup validators pretty easily and flexibly, and if you need different validations for different operations you can use the one that applies for that specific operation (and change them out) very easily.
I've used Sptring.NET's validation engine for exactly the same reason - It allows you to use Conditional Validators. You just define rules - what validation to apply and under what conditions and Spring does the rest. The good thing is that your business logic is no longer polluted by interfaces for validation
You can find more information in documentation at springframework.net I will just copy the sample for the their doc to show how it looks like:
<v:condition test="StartingFrom.Date >= DateTime.Today" when="StartingFrom.Date != DateTime.MinValue">
<v:message id="error.departureDate.inThePast" providers="departureDateErrors, validationSummary"/>
</v:condition>
In this example the StartingFrom property of the Trip object is compared to see if it is later than the current date, i.e. DateTime but only when the date has been set (the initial value of StartingFrom.Date was set to DateTime.MinValue).
The condition validator could be considered "the mother of all validators". You can use it to achieve almost anything that can be achieved by using other validator types, but in some cases the test expression might be very complex, which is why you should use more specific validator type if possible. However, condition validator is still your best bet if you need to check whether particular value belongs to a particular range, or perform a similar test, as those conditions are fairly easy to write.
If you're using .Net 4.0, you can use Code Contracts to control some of this.
Try to read this article from top to bottom, I've gained quite a few ideas from this.
http://codebetter.com/jeremymiller/2007/06/13/build-your-own-cab-part-9-domain-centric-validation-with-the-notification-pattern/
It is attribute based domain validation with a Notification that wraps those validations up to higher layers.
I would separate the variant validation logic out, perhaps with a Visitor as you mentioned. By separating the validation from the classes, you will be keeping your operations separate from your data, and that can really help to keep things clean.
Think about it this way too -- if you mix-in your validation and operations with your data classes, think of what are things going to look like a year from now, when you are doing an enhancement and you need to add a new operation. If each operation's validation rules and operation logic are separate, it's largely just an "add" -- you create a new operation, and a new validation visitor to go with it. On the other hand, if you have to go back and touch alot of "if operation == x" logic in each of your data classes, then you have some added risk for regression bugs/etc.
I rely on proven validation strategy which has implemented in .net framework in 'System.ComponentModel.DataAnnotations Namespace' and for example used in ASP.NET MVC.
This one provides unobtrusive way to apply validation rules (using attributes or implementing IValidatableObject) and facilities to validate rules.
Scott Allen described this way in great article 'Manual Validation with Data Annotations'.
if you want to apply validation attributes on interface then look at MetadataTypeAttribute
to get better understanding how it works look at MS source code