How to prevent from DataAnnotations Attributes being deleted in DataBase First Model - asp.net-mvc

I have my asp.net mvc 3 application with entity framework and i used the Database First model to set it up.
My Steps below:
1. Genarated a database with tables
2. Created ADO.NET Entity Data Model file (.edmx) and imported the tables
3. inside the design i added a Code Generation item and used ADO.NET DbContext Generator
4. a Model1.tt holder as been made with all of the tables Models
I have edited the models and updated them with DataAnnotations Attributes (just for the example a well known one)
public class LogOnModel
{
[Required]
[Display(Name = "User name")]
public string UserName { get; set; }
[Required]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }
[Display(Name = "Remember me?")]
public bool RememberMe { get; set; }
}
Now when im making changes to the database and updating it to the edmx file all the models will be overwritten and the DataAnnotations Attributes will disapear.
my question:
how can i use database first model and still edit the models for speciific validation like im free to do with code first model?
(please no third party tools solution)
thanks

You need to use buddy classes. See my dated but still useful article http://msdn.microsoft.com/en-us/library/ee256141(v=vs.98).aspx

Use ViewModels in your Views. This will decouple your EF entities from your UI logic.

Related

ASP.NET MVC Entity Framework: Data Annotations

I'm working with Entity Framework with a database-first approach. I already defined the model inside my application. Now I'm working with controllers and views. I used scaffolding in order to create controllers. Now I want to create rows.
Let's say I want to create employees, and let's say the DBA and EF made this possible:
public partial class TBL_EMPLOYEE
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public TBL_EMPLOYEE()
{
this.TBL_EMPLOYEE = new HashSet<TBL_EMPLOYEE>();
}
public int EMPLOYEE_ID { get; set; }
public String CO_WORKER_NUMBER { get; set; }
public string NAME { get; set; }
public string LAST_NAME { get; set; }
public string SALARY { get; set; }
public string PHONE_NUMBER { get; set; }
public string EMAIL { get; set; }
public string { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
}
Now, I need a view to create an employee, let's call this view VIEW 1
In this view, the user only needs to specify name and last name values. Both are required.
Now, in this VIEW 1 case I could use the following data annotations attributes in the same class, that'd be:
[Required]
public string NAME { get; set; }
[Required]
public string LAST_NAME { get; set; }
Now, let's go to the next case. I need another View, let's call this VIEW 2
In this one, the user needs to specify all values for all attributes. All of them are required except for name and last name.
THE REAL QUESTION
How can I use the same model class for both views? The example above here might seem a bit silly and trivial validations but I've been in bigger projects where entities are bigger and the idea of having different ViewModel classes is just so much work.
I've stumbled upon this in my .NET developments, to the point I had to create a ViewModel class per view in order to be specific with what the user needs to input and their validation. Is this the only way?
To avoid duplicating models with minor variations, try this:
https://stackoverflow.com/a/18898112/6850962
Basically, create a base model with data annotations that apply in all situations (eg: DisplayName) and then extend the model for variations (eg: Required attribute).
If you are trying to use your Entity Framework entities approach, I wouldn't put validation attributes on those entities. I would either:
create separate distinct classes and then copy data from the EF entities to the models, and vice versa on update (either by writing the code explicitly, or using a tool like AutoMapper or many others). Then you can define the validation rules anyway you want. Unfortunately this approach does tightly couple validation to the model and thus model reuse may not be as possible.
Use a more fluid validation framework like FluentValidation (https://github.com/JeremySkinner/FluentValidation). The benefit to this is that you define an external class with the rules internal, which can be applied differently depending on the situation. The model may still need some indicator on the model itself to figure out which rules apply, but this is another functional approach to handling the scenario you describe.

Where is UserProfile or ApplicationUser model class inside MVC 5 application

I have a hard time finding UserProfile/ApplicationUser in the MVC 5 application. I would like to add this field: public virtual ICollection<Meeting> Meetings { get; set; } to UserProfile/ApplicationUser class.
I want do this to use Mr. Chris Pratt's advice: How to associate list of objects with user(Account) in ASP .NET MVC
EDIT: Will Entity Framework will understand the association between Meeting and USER if I add in class Meeting field public int ApplicationUserId { get; set; } in code first approach?
I got only this:

If you are using Entity Framework, how to do you use the EF Model classes instead of having to make custom View Models?

I am new to MVC. If one imports all of their existing tables in a database, they can created Entity Framework models. My question is, how do I actually use these models instead of having to fall back on creating custom View Models of the table data? Here is what I mean:
My understanding is that model classes that Entity Framework automatically generates should not be modified (example: a model of a Products table). Because of this, I have to create a whole new View Model of the Products table in order to be able to add things like [Display] and [Required] tags to the model so that I can have a custom name displayed to the user (e.g. "Store Products") and validation (e.g. the product name field is required).
See what I mean? Do you always have to manually create a View Model in order to get needed functionality like validation and user-understandable display names?
Side question: the models that Entity Framework automatically creates (based on your existing tables in the database) are called "Domain Models" right?
If the only reason you want to make separate view model is because you want to add data annotations then you can just use partial classes
eg: Given an EF generated class
public partial class MyClass
{
public int Id { get; set; }
public string SomeText { get; set; }
}
you can add a new file with:
[MetadataType(typeof(MyClassMetadata))]
public partial class MyClass
{
}
public class MyClassMetadata
{
[Required]
[Display(Name = "An Id")]
public int Id { get; set; }
[AllowHtml]
[Display(Name = "Some HTML text")]
public string SomeText { get; set; }
}
to decorate your EF classes.
Yes, this looks a bit clunky. There might be a neater way to do this in the newer versions.

How can I reuse Model Metadata for custom View Models?

I'm working on an ASP.NET MVC 2 project with some business entities that have metadata dataannotations attributes applied to them (Validation attributes, Display attributes, etc.).
Something like:
//User entity
public class User
{
[DisplayName("Vorname")]
[Required(ErrorMessage = "Vorname fehlt")]
[StringLength(MaxNameLength, ErrorMessage = "Vorname ist zu lang")]
public string FirstName { get; set; }
[DisplayName("Nachname")]
[Required(ErrorMessage = "Nachnamefehlt")]
[StringLength(MaxNameLength, ErrorMessage = "Nachname ist zu lang")]
public string LastName { get; set; }
[Required]
public string Password{ get; set; }
}
Using the metadata from different views is no problem, as long as I am using my business entities as viewmodels or as part of a viewmodel like this:
//custom viewmodel with a user entity
public class CustomViewModel
{
public User{get;set;}
//some more properties...
}
However, sometimes I need to code a view for editing some, but not all fields of an entity. For those fields I want to reuse the metadata already specified in my user entity. The other fields should be ignored. I'm talking about custom view models like this:
[MetadataType(typeof(User))]
public class UserNameViewModel
{
public string FirstName { get; set; }
public string LastName { get; set; }
//no password on purpose, the user should only
//edit his first and last name in this view
}
That's where I am running into problems. The custom view model above leads to an exception when the view is generated, because it has no password property.
The associated metadata type for type
'Zeiterfassung.Models.ViewModels.Users.UserNameViewModel+UserModel'
contains the following unknown
properties or fields: Password. Please make sure
that the names of these members match
the names of the properties on the
main type.
Also, even if this exception did not occur, I expect to get into even more trouble with model validation on form submit because Password is marked as required in my business entity.
I can think of several workarounds, but none seem really ideal. In any case I can't change the database layout so that the password field would be in a separate entity in my example above.
How would you handle this scenario?
The only recommendation I could give you is to have view models specific to each view and have only the necessary properties and validation attributes on those view models. Don't worry if you repeat some validation attributes and properties on your view models. That's what they are meant for: reflect the logic of a given view.

Mapping Validation Attributes From Domain Entity to DTO

I have a standard Domain Layer entity:
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set;}
}
which has some kind of validation attributes applied:
public class Product
{
public int Id { get; set; }
[NotEmpty, NotShorterThan10Characters, NotLongerThan100Characters]
public string Name { get; set; }
[NotLessThan0]
public decimal Price { get; set;}
}
As you can see, I have made up these attributes completely. Which validation framework (NHibernate Validator, DataAnnotations, ValidationApplicationBlock, Castle Validator, etc) in use here is not important.
In my client layer, I also have a standard setup where I don't use the Domain entities themselves, but instead map them to ViewModels (aka DTO) which my view layer uses:
public class ProductViewModel
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set;}
}
Let's then say that I want my client/view to be able to perform some basic property-level validations.
The only way I see I can do this is to repeat the validation definitions in the ViewModel object:
public class ProductViewModel
{
public int Id { get; set; }
// validation attributes copied from Domain entity
[NotEmpty, NotShorterThan10Characters, NotLongerThan100Characters]
public string Name { get; set; }
// validation attributes copied from Domain entity
[NotLessThan0]
public decimal Price { get; set;}
}
This is clearly not satisfactory, as I have now repeated business logic (property-level validation) in the ViewModel (DTO) layer.
So what can be done?
Assuming that I use an automation tool like AutoMapper to map my Domain entities to my ViewModel DTOs, wouldn't it also be cool to somehow transfer the validation logic for the mapped properties to the ViewModel as well?
The questions are:
1) Is this a good idea?
2) If so, can it be done? If not, what are the alternatives, if any?
Thank you in advance for any input!
If you're using something supporting DataAnnotations, you should be able to use a metadata class to contain your validation attributes:
public class ProductMetadata
{
[NotEmpty, NotShorterThan10Characters, NotLongerThan100Characters]
public string Name { get; set; }
[NotLessThan0]
public decimal Price { get; set;}
}
and add it in the MetadataTypeAttribute on both the domain entity & DTO:
[MetadataType(typeof(ProductMetadata))]
public class Product
and
[MetadataType(typeof(ProductMetadata))]
public class ProductViewModel
This won't work out of the box with all validators - you may need to extend your validation framework of choice to implement a similar approach.
The purpose of validation is to ensure that data coming into your application meets certain criteria, with that in mind, the only place it makes sense to validate property constraints, like those you have identified here, is at the point where you accept data from an untrusted source ( i.e. the user ).
You can use something like the "money pattern" to elevate validation into your domain type system and use these domain types in the view model where it makes sense. If you have more complex validation (i.e. you are expressing business rules that require greater knowledge than that expressed in a single property), these belong in methods on the domain model that apply the changes.
In short, put data validation attributes on your view models and leave them off your domain models.
Why not use an interface to express your intent? Eg:
public interface IProductValidationAttributes {
[NotEmpty, NotShorterThan10Characters, NotLongerThan100Characters]
string Name { get; set; }
[NotLessThan0]
decimal Price { get; set;}
}
It turns out that AutoMapper may be able to do this for us automagically, which is the best case scenario.
AutoMapper-users: Transfer validation attributes to the viewmodel?
http://groups.google.com/group/automapper-users/browse_thread/thread/efa1d551e498311c/db4e7f6c93a77302?lnk=gst&q=validation#db4e7f6c93a77302
I haven't got around to trying out the proposed solutions there, but intend to shortly.
If you use hand-written domain entities, why not put your domain entities in their own assembly and use that same assembly both on the client and server. You can reuse the same validations.
I've been considering this as well for a while now. I totally understand Brad's reply. However, let's assume I want to use another validation framework that is suitable for annotating both domain entities and view models.
The only solution I can come up with on paper that still works with attributes would be to create another attribute that "points" to a domain entity's property that you are mirroring in your view model. Here's an example:
// In UI as a view model.
public class UserRegistration {
[ValidationDependency<Person>(x => x.FirstName)]
public string FirstName { get; set; }
[ValidationDependency<Person>(x => x.LastName)]
public string LastName { get; set; }
[ValidationDependency<Membership>(x => x.Username)]
public string Username { get; set; }
[ValidationDependency<Membership>(x => x.Password)]
public string Password { get; set; }
}
A framework like xVal could possibly be extended to handle this new attribute and run the validation attributes on the dependency class' property, but with your view model's property value. I just haven't had time to flesh this out more.
Any thoughts?
First of all, there is no notion of "standard" domain entity. For me, standard domain entity does not have any setters to begin with. If you take that approach, you can have more meaningful api, that actually conveys something about your domain. So, you can have application service that processes your DTO, creates commands that you can execute directly against you domain objects, like SetContactInfo, ChangePrice etc. Each one of these can raise ValidationException, which in turn you can collect in your service and present to the user. You can still leave your attributes on the properties of dto for simple attribute/property level validation. For anything else, consult your domain. And even if this is CRUD application, i would avoid exposing my domain entities to presentation layer.
Disclaimer: I know this is an old discussion, but it was closest to what I was looking for: Keeping DRY by reusing validation attributes. I hope it is not too far from the original question.
In my situation I wanted to make error messages availible in .NET views and in other viewmodels. Our entities have little to no business logic and are mainly targeted for data storage. Instead we have a large viewmodel with validation and business logic were I want to reuse error messages. Since the users are only conserned with error messages, I find this to be relevant as that is what is important to maintain easily.
I could not find a feasible way to remove logic from the partial ViewModels, but I found a way to convey the same ErrorMessage, such that it can be maintained from a single point. Since ErrorMessages are tied to the view, it can just as well be part of the ViewModel. Consts are considered static members, so defining the error messages as public string constants, we can access them outside the class.
public class LargeViewModel
{
public const string TopicIdsErrorMessage = "My error message";
[Required(ErrorMessage = TopicIdsErrorMessage)]
[MinimumCount(1, ErrorMessage = TopicIdsErrorMessage)]
[WithValidIndex(ErrorMessage = TopicIdsErrorMessage)]
public List<int> TopicIds { get; set; }
}
public class PartialViewModel
{
[Required(ErrorMessage = LargeViewModel.TopicIdsErrorMessage]
public List<int> TopicIds { get; set; }
}
In our project we were using custom html for dropdownlists, such that we could not use #Html.EditorFor helper in razor, thus we could not use unobtrusive validation. With the error message availible we could now apply the necessary attributes:
#(Html.Kendo().DropDownList()
.Name("TopicIds")
.HtmlAttributes(new {
#class = "form-control",
data_val = "true",
data_val_required = SupervisionViewModel.TopicIdsErrorMessage
})
)
Warning: You might need to recompile all related projects that rely on const values...

Resources