I'm using MVC with entity framework for a while.
and now i need to make a wpf application and I'm looking for a way to validate like the model-state in WPF
This is how my class looks
public class Customer
{
public int Id { get; set; }
[Required]
[MaxLength(100)]
public string Name { get; set; }
[MaxLength(100)]
public string Address { get; set; }
[MaxLength(20)]
public string PhoneNumber { get; set; }
[EmailAddress]
public string Email { get; set; }
public List<Order> Orders { get; set; }
}
Is there any easy way for me to check if its valid?
what I'm really trying to avoid is to have to write all the validation rules
Unfortunately no, I had to create a interface called IValidateable which extends INotifyDataErrorInfo where I define a method Validate that I can pass the property name to or leave it blank to validate the entire object.
The INotifyDataErrorInfo is an .Net interface that allows the validation to be asynchronous and has already a property HasErrors to check the object after it has been validated.
I then implemented all of the required methods in a base class, when I need to validate the entire object, this base class uses reflection to list the properties and then validate each one.
In the base class I have an virtual method like so:
protected virtual void PerformValidation (String Property) {}
My models override this method and do the specific validation required. This method is not required to be override and as I said, you can add support to attributes in the base class.
You can extend the IDataErrorInfo instead of the INotifyDataErrorInfo if you don't need asynchronous validation.
Then I can just do something like this:
SomeModel.Validate ();
if (SomeModel.HasErrors)
Do Something...
Or:
if (!SomeModel.Validate ())
Do Something...
Related
The issue:
Entity object has it properties related to databases on its own, but the needs in the programming area is differ, sometimes we want to add it some more:
Properties – that is for temporary logic.
Methods – for clean code and for programming necessaries.
Finally yet importantly – Attribute for authorization, display, filters etc.
However, obviously we do not want our program to be maintainability without needs to rewrite code just after we update the model.
For properties and methods, the Entity Framework platform generated all the object from model as partial classes and the .NET environment allow us to extend them as we wish:
Remember to check that our partial sit in same namespaces (Notice that when we create them in model directory or in them own directory Visual Studio create addition namespace).
public partial class ErrorLog
{
public long pk { get; set; }
public int lineNumber { get; set; }
public Nullable<int> error { get; set; }
}
Our partial:
public partial class ErrorLog
{
public string getErrorDescription()
{
return d[(int)error];
}
private static Dictionary<int, string> d = new Dictionary<int, string>()
{
{1,"desc1" },
{2,"desc2" },
{3,"desc3" },
{4,"desc4" }
};
}
For attributes:
We can add new interface
public interface IErrorLogsMetaData
{
[Display(Name = "Id")]
long pk { get; set; }
[Display(Name = "The line Number")]
int lineNumber { get; set; }
[Display(Name = "The Error")]
Nullable<int> error { get; set; }
}
Implement them on our Entity (even extended) object.
For that we need to reflect and book it in global.asax by using:
TypeDescriptor.AddProviderTransparent(
new AssociatedMetadataTypeTypeDescriptionProvider(typeof(ErrorLog), typeof(IErrorLogsMetaData)), typeof(ErrorLog));
TypeDescriptor – familiar for us from reflection, its get information about type.
AddProviderTransparent – is the method called from my partially trusted code and get metadata from associated class.
The first parameter is the provider and it TypeDescriptionProvider from the type we want to decorate and the attributed interface, the second parameter is the target type for decription.
Another Option
Make your partial view to implement the IErrorLogsMetaData and then you don't need to associate at Global.asax
As you can see, the database first entity model classes are partial, so you can create your own partial class, for example if you have:
public partial class SomeClass
{
public string Prop1 { get; set; }
public string Prop2 { get; set; }
}
You can do something like this:
Add some class to your project, name it SomeClassPartial:
//SomeClassPartial.cs
namespace YourNamespace
{
[MetadataType(typeof(SomeClassMetadata))]
public partial class SomeClass
{
//add your new properties/some_logic here
public string NewPropX { get; set; }
public string NewPropY { get; set; }
}
public partial class SomeClassMetadata
{
//metadata for your existing model properties
[Display(Name = "Property 1")]
public string Prop1 { get; set; }
[Display(Name = "Property 2")]
public string Prop2 { get; set; }
}
}
In your SomeClassMetadata class you can add data annotation attributes to your existing properties with MetadataType attribute, which will specify the metadata class to associate with a data model class, and with that you can tell you partial SomeClass class to get that attributes from SomeClassMetadata class. To add new custom properties, you can use SomeClass partial class.
MSDN Link: MetadataTypeAttribute Class
To explain it better, I have an object that has property of interface type that can be carrying a variety of different objects.
public class RequestParameters {
public IRequest Request { get; set; }
}
Say the interface looks something like this:
public interface IRequest {
string Username { get; set; }
string Password { get; set; }
}
Now upon receiving the RequestParameters object, I want to get the value of a property PersonId from the object inside Request property. The interface doesn't and shouldn't contain this property, as not all of the Request types have that property. And I don't know which of the dozens of types will the Request object correspond to, so casting isn't a solution.
So how can I possibly fetch the property PersonId in such a case? I suppose some sort of reflection is the only way, but how exactly can it be done?
What about creating an intermediate interface?
public class RequestParameters
{
public IRequest Request { get; set; }
}
public interface IRequest {
string Username { get; set; }
string Password { get; set; }
}
public interface IRequestWithId : IRequest
{
string ID {get; set; }
}
Now you can check against that interface instead of a concrete class to check if there is an ID or not.
Other than that there is only reflection which is a really bad idea here. When defining interfaces you want to reduce code-coupling which means you don´t want to rely on actual types (that define how things are done) but only their behaviour (what can be done with them). Using reflection would circumvent this as you indirectly rely on the actual types. Furthermore using reflection is bad for maintainance, in particular when you refactor the methods (renaming for example).
first of all, in c# there is another type called abstract class which in my opinion would be a better suit for your situation. take a look at this question. interfaces are not meant to hold variables, only functions.
public abstract class ARequest
{
string Username { get; set; }
string Password { get; set; }
public abstract int GetId() {}
}
Is there a way of using EF and/or C# code to migrate data to a new table (and entity), or would I have to use some plain old-fashioned SQL in my EF-Migration?
Here's my situation:
I have an existing OldCarLog class that as used to log user actions on an entity we'll call Car, but now I want to allow logging on other entities and I've created an abstract/generic class BrandSpankingNewActivityLog<TEntity> to make logging of any class easy. So I have Car_Log : BrandSpankingNewActivityLog<Car> along with PartInfo_Log and RepairProcedure_Log.
I want to take all the OldCarLog entities and convert them into their replacement Car_Log
this way I can refactor the OldCarLog into Car_Log and have a standard API for the newly implemented logs without having OldCarLog get confused with any logs derived from BrandSpankingNewActivityLog<TEntity>.
public abstract class BrandSpankingNewActivityLog<TEntity>
{
public long Id { get; set; }
public DateTime ActivityTime { get; set; }
public virtual User User { get; set; }
public virtual TEntity Entity { get; set; }
}
public class Car_Log : BrandSpankingNewActivityLog<Car>
{
//Nothing to see here!
}
public class Car
{
public long Id {get; set;}
//Other car info you don't care about ....
//Yada, Yada, Yada....
public virtual ICollection<Car_Logs> {get;set;}
}
Does that all make sense?
In the DbMigration::Up() make a call using the SQL("TODO: Add SQL"); method.
http://msdn.microsoft.com/en-us/library/system.data.entity.migrations.dbmigration.sql(v=vs.113).aspx
I'm creating a web api program using entity framework. So as the basis, I have an sql server database which I'm connected to with entity framework trought my web api program. Using an add-on for entity framework, I'v generated classes according to my database tables. However i don't want to use these classes for my webservices because I don't need to display some of the attributes generated by the entity framework and little bit tricky with all the proxies problems. These attributes are especially generated because of the foreign keys. As below, for this generated class, I don't need to display "Societe" object and "Utilisateur" object:
public partial class FonctionnalitePerUser
{
public int FonctionUserLngId { get; set; }
public int FonctionUserLngUserId { get; set; }
public int FonctionUserLngSocieteId { get; set; }
public virtual Societe Societe { get; set; }
public virtual Utilisateur Utilisateur { get; set; }
}
I would need some advice to avoid displaying that entities in my webservices.
I was thinking about 3 possibilities:
As it's a partial class, I might create an other partial class with the same name where I put the attributes that I need and override the constructor.
I might inherit a custom class from that one to override the constructor in order to get one structured as I need.
I might create Management classes with functions that create the perfect objects that I need for my webservices. I mean functions that convert "FonctionnalitePerUser" object to "FonctionnalitePerUserCustom" objects.
These are the 3 solutions that I've found. In order to get the best performance, I was wondering if anyone can give me some advise about that or either propose some other solutions.
Thanks in advance
If your using Newtonsoft Json.NET which I think is the default in MVC5 then you can attribute your properties to tell newtonsoft what to serialize and what to ignore.
public class Car
{
// included in JSON
public string Model { get; set; }
public DateTime Year { get; set; }
public List<string> Features { get; set; }
// ignored
[JsonIgnore]
public DateTime LastModified { get; set; }
}
or if you have more properties you want to ignore than you want to serialize you can do this:
[DataContract]
public class Computer
{
// included in JSON
[DataMember]
public string Name { get; set; }
[DataMember]
public decimal SalePrice { get; set; }
// ignored
public string Manufacture { get; set; }
public int StockCount { get; set; }
public decimal WholeSalePrice { get; set; }
public DateTime NextShipmentDate { get; set; }
}
this information was taken from here.
In general, it is often useful to expose a different type of object for a web service API than for persistence. This is for exactly the reason you state: because you don't need to expose all of that persistence stuff to the rest of the world (clients).
Usually, you would map the information that you want to expose from your persistence model (EF entities etc) to a view model object (or DTO).
So, I would say your option 3 is on the right track.
I might create Management classes with functions that create the
perfect objects that I need for my webservices. I mean functions that
convert "FonctionnalitePerUser" object to
"FonctionnalitePerUserCustom" objects
There are several tools out there that help with the converting or mapping of the objects. One is AutoMapper which will map by convention. This can save a lot of mapping code.
I have DTOs that are mapped to ViewModels. To avoid having to manage validation attributes (and other attributes), I wanted to write the validation attributes for all the properties on a single class and reuse it on my ViewModels. However, when I try to use the Metadata on a ViewModel that does not have all the properties of the DTO (all of them really...), it gives me an System.InvalidOperationException exception.
Exception:
Le type de métadonnées associé pour le type 'MyProject.EntityViewModel' contient les propriétés ou champs inconnus suivants : AnotherProperty. Vérifiez que les noms de ces membres correspondent aux noms des propriétés du type principal.
Google translated:
The type associated metadata for type 'MyProject.EntityViewModel' contains the following unknown properties or fields: AnotherProperty. Verify that the names of these members match the names of the properties of the main type.
Simplified example:
public class Entity {
public string A { get; set; }
public string B { get; set; }
public string C { get; set; }
}
public class EntityDTO {
public string A { get; set; }
public string B { get; set; }
public string C { get; set; }
}
//This class is used to add validation attributes for input-related view models
public class EntityInputValidation {
[Required]
public string A { get; set; }
[Required]
public string B { get; set; }
//Notice that we dont have a validation for C
}
//This class is a ViewModel used to create a new Entity
[MetadataType(typeof(EntityInputValidation))]
public class EntityCreateViewModel {
//Required because we use the InputValidation metadata
public string A { get; set; }
//Notice that we do not have the B property here, even if we are using the Input Validation which has a required attribute for this property. This is where the exception comes from.
//C is only required in this View/ViewModel
[Required]
public string C { get; set; }
}
Because EntityViewModel does not have AnotherProperty, it will throw an exception. Is there a way to prevent this?
I would certainly reconsider having those annotations directly on your entity. As you can already see, this is going to cause you problems whenever you need to use that entity in a view which doesn't need to adhere to those validation rules. That will likely get worse in the long run if more views are added which use your entity.
Pretty much whatever solution you come up with to stop that throwing the exception is going to be a hack.
Updated per comments
I did not want to search into 20 view models whenever we have to change a validation rule... We currently have 2 websites and soon to be 3 that are part of the solution using the same DAL and business logic. Thats a lot of view models to keep updated.
That is certainly a valid concern, and this is also a valid question to be asking. The problem is more that there is no well-defined solution, at least that I've found.
Taking a look at the inheritance idea, it seems reasonable at first. However, this is only going to work if your properties fit into neat groups, which from your updated question seems may not be the case.
Let's take a simple example:
public class LoginValidation
{
[Required]
public string Username { get; set; }
[Required]
public string Password { get; set; }
}
You could then derive a view model from that:
public class ViewModelA : LoginValidation
{
public string SomeOtherProperty { get; set; }
}
However, this comes with a problem. What if you want to inherit another set of validation properties? You can't, as we're restricted to inheriting from one class. We also cannot inherit data annotations from interfaces:
The product team does not want to implement this feature, for two main reasons:
Consistency with DataAnnotations.Validator
Consistency with validation behavior in ASP.Net MVC
tricky scenario: a class implements two interfaces that have the same property, but with conflicting attributes on them. Which attribute would take precedence?
(Source: http://social.msdn.microsoft.com/Forums/en-US/1748587a-f13c-4dd7-9fec-c8d57014632c/code-first-dataannotations-in-interfaces?forum=adonetefx)
So what if you need LoginValidation and some dates validation for a specific view? You'd have to create an inheritance chain from both in an intermediary class, just to be able to inherit from that for your view model:
public class LoginAndDateValidation : LoginValidation
{
[Required]
public DateTime StartDate { get; set; }
[Required]
public DateTime EndDate { get; set; }
}
public class ViewModelA : LoginAndDateValidation
{
public string SomeOtherProperty { get; set; }
}
Do you see where this is going? This would turn into a complete mess. So, as I said earlier, this will only work if your properties fit into, and are used in, well-defined groups, but it doesn't seem that is the case in your scenario.
To finish up, let me just link to an answer Mystere Man posted a few years back that I've always liked: https://stackoverflow.com/a/8075115/729541