How to localize property name?

If you are using Html Helper to generate your form you may end up with label with the property name into it. You may also have error message with the property name. The problem is if your object contain English term, you would prefer not to show them in English if you write something in French.

public class Person
{
    public string Name { get; set; }
}

The example above could display the word “Name” in a localized string, which is not what we want. But, if we use the Display data annotation attribute, it’s possible to localize the property Name.

public class Person
{
    [Display(ResourceType = typeof(ResourceFileTypeHere), Name="NamePropertyKey")]
    public string Name { get; set; }
}

This will search inside the resource specified the key inside the Name attribute. That’s it, you have your property localized.

How to localize data attribute in MVC3?

If you are using the Data Annotation with Asp.Net MVC you might need to localize the message from these annotation.

Here is an example:

public class Person
{
    [Required(ErrorMessage="FirstName is required")]
    public string FirstName { get; set; }
    //...
}

If you want to have the Data Annotation translated in many languages, you should use two others properties that are : ErrorMessageResourceType and ErrorMessageResourceName. This will let you specify the resource type and the resouce name which is the key of inside the resource file.

public class Person
{
    [Required(ErrorMessageResourceType=typeof(MyResourcesNameSpace.ResourcesFile), ErrorMessageResourceName="FirstNameRequiredKey")]
    public string FirstName { get; set; }
    //...
}

This way, you will have your application localized from the Model to the View without any problem.

Html Extension Helper with generic access to object property

It’s possible to create a custom generic Html Extension Helper with the use of Expression Helper and if required the ModelMetadata to get the value.

    public static string MyExtensionFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> property)
	{
		var meta = ModelMetadata.FromLambdaExpression(property, this.HtmlHelper.ViewData);
		string fullPropertyName = HtmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(ExpressionHelper.GetExpressionText(property));
		
		//Do what you need to do
	}

The variable fullPropertyNamemeta data contain the value of the property if required.

@Html.MyExtensionFor(x=>x.MyClassProperty1)

With little or no code you can setup Html Helper that is strongly typed. This has the advantage to not write string. This of course is better to reduce the change to write a wrong string but also help the refactoring because all refactoring tools works with property name change.

How to save the ModelState into session following the good practice

Tim Barcz, Matt Hawley, Stephen Walther and Scott Guthrie (VP at Microsoft and lead for many project like Entity Framework, Asp.Net, etc) have already discussed about this problematic and created the PRG pattern to solve this problem. In fact, to solve this problem you should not handle manually the ModelState but simply use Import and Export attribute like the following example.

[AcceptVerbs(HttpVerbs.Get), ImportModelStateFromTempData]
public ActionResult MyAction(ModelObject myObject)
{
    return View();
}

[AcceptVerbs(HttpVerbs.Post), ExportModelStateToTempData]
public ActionResult MyActionSubmit(ModelObject  myObject)
{
   return View();
}

These attributes are not from the .Net framework and you need to have them inside your project by creating them. Once it’s done once, it’s done for the life time of your project.

First, you need to create the attributes. To do, you need to create a class that inherit the class ActionFilterAttribute. Since we are using 2 attributes that share the same information, we will create 3 classes. The first one will contain the sharing key for the session and the two others will be for the Import and Export.

public abstract class ModelStateTempDataTransfer : ActionFilterAttribute
{
    protected static readonly string Key = typeof(ModelStateTempDataTransfer).FullName;
}

Then, the class to export. Here you can add more custom code for your project. This version will all the ModelState only if this one contain errors.

public class ExportModelStateToTempData : ModelStateTempDataTransfer
{
    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        //Only export when ModelState is not valid
        if (!filterContext.Controller.ViewData.ModelState.IsValid)
        {
            //Export if we are redirecting
            if ((filterContext.Result is RedirectResult) || (filterContext.Result is RedirectToRouteResult))
            {
                filterContext.Controller.TempData[Key] = filterContext.Controller.ViewData.ModelState;
            }
        }

        base.OnActionExecuted(filterContext);
    }
}

The last class will import the ModelState. In fact, it will merge the new one with the old one in the session.

public class ImportModelStateFromTempData : ModelStateTempDataTransfer
{
    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        ModelStateDictionary modelState = filterContext.Controller.TempData[Key] as ModelStateDictionary;

        if (modelState != null)
        {
            //Only Import if we are viewing
            if (filterContext.Result is ViewResult)
            {
                filterContext.Controller.ViewData.ModelState.Merge(modelState);
            }
            else
            {
                //Otherwise remove it.
                filterContext.Controller.TempData.Remove(Key);
            }
        }

        base.OnActionExecuted(filterContext);
    }
}

As you can see, we do not use the session directly but we store everything into the TempData which use the session but handle the life cycle for us. This mean that it won’t stay for 20 minutes (default value of a session life time). It will stay until the next post back and be there if the request is redirected.

You can see it in the MVC open source project called MVCContrib (slightly modified version of this one). You can also find the source of the code in this blog post at this website.

Entity Framework 4.3 delete cascade with code first (Poco)

If you have a parent->child relationship between two of your classes and you delete the parent, you may want to delete all children. To do, you need to have a “DELETE CASCADE” statement on your foreign key. Here is a simple example:

CREATE TABLE [Parent](
	[ID] [int] IDENTITY(1,1) NOT NULL,
	[Description] [nvarchar](100) NULL,
CONSTRAINT [PK_Parent] PRIMARY KEY CLUSTERED 
GO

CREATE TABLE [ParentDetail](
	[ID] [int] IDENTITY(1,1) NOT NULL,
	[Parent_ID] [int] NOT NULL,
CONSTRAINT [PK_ParentDetail] PRIMARY KEY CLUSTERED 
GO

ALTER TABLE [ParentDetail]  WITH CHECK ADD  CONSTRAINT [FK_ParentDetail_Parent] FOREIGN KEY([Parent_ID])
REFERENCES [Parent] ([ID])
ON DELETE CASCADE
GO

The problem is that if you are using Entity Framework 4.3 and try to delete a Parent entity, you will end having this error :

An error occurred while saving entities that do not expose foreign key properties for their relationships. The EntityEntries property will return null because a single entity cannot be identified as the source of the exception. Handling of exceptions while saving can be made easier by exposing foreign key properties in your entity types. See the InnerException for details.

The inner exception message will contain something similar to this:

Cannot insert the value NULL into column ‘Parent_ID’, table ‘ParentDetail’; column does not allow nulls. UPDATE fails. The statement has been terminated.

So, what does it means? It tries to delete the Parent and to set into each ParentDetail the ID NULL because it’s been erased. This is not what we want. In fact, we would like to have all ParentDetail to me removed as well. This is a little bit the reason why we have specify on the SQL to have a cascade.

You can do it manually in your project:

var listDetail = parent.ParentDetails.ToList();
foreach (var ParentDetail in listDetail){
	Database.ParentDetails.Remove(ParentDetail);
}

Database.Parents.Remove(Parent);
Database.SaveChanges();

This will produce multiple amount of SQL statement on the SQL Server. One for each details and 1 for the Parent itself.

But, if you go to your database context and you specify in the OnModelCreating a rule about the cascade it will work as it’s suppose to do.

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//...
modelBuilder.Entity<Parent>().HasMany(e => e.ParentDetails).WithOptional(s => s.Parent).WillCascadeOnDelete(true);
//...

That’s it! Now you can simply delete the Parent without having to delete manually every children.

Database.Parents.Remove(Parent);
Database.SaveChanges();

On the SQL server side, you can see the database to have the same amount of delete statement executed. So, you do not save on the amount of query but save on the amount of logic to handle on the C# side because you do not have to care to delete every details.

On a special note, you do not need to have the table having a reference with the On Delete Cascade. You can handle the cascade only on the Entity DbContext with OnModelCreating. If you specify it on the Sql Server Database side, this only will enforce the integrity on the database side but won’t be automatically applied on the delete with EF.

ModelState.Clear() is required to display back your model object

If you are getting your Model from a form and you want to manipulate the data that came from the client form and write it back to a view, you need to call ModelState.Clear() to clean the ModelState values.

The reason is that normally, you want to postback to the client the form with all the errors. So, when you put back the parameter that contain your model to the view to be returned, this one use the value of the ModelState.

So, for example, if I change a property and sent it back to the client :

[HttpPost]
public ActionResult Edit(MyObject objModel) 
{
	objModel.Property1 = "NEW VALUE";
	//...
	return View(objModel)
}

This won’t put on the UI the new value for the property1 because the ModelState values doesn’t contain this value but the one entered by the user.

To be able to override the model state you need to remove all the data from it.

[HttpPost]
public ActionResult Edit(MyObject objModel) 
{
	objModel.Property1 = "NEW VALUE";
	//...
	ModelState.Clear();
	return View(objModel)
}

To clear the memory of the model state you need to use ModelState.Clear(). You could also remove only the desired field by using method of ModelState.

ModelState.Remove("Property1");

Also, if you always want to not use the ModelState, you may want not to use HtmlHelper and directly use the model with Html code.

My Property: <input type="text" name="Property1" value="@Model.Property1" />

In all situation, what you need to remember is that ModelState is the default mechanism and will by default be the one that will be used to display information back to the form.

HTMLInputElement’s defaultValue

Did you know that you can know the original value written by the server to the client by calling:

var originalName =document.getElementById("txtUserName").defaultValue;

Yes, the Dom contain for every Html element of type HTMLInputElement and HTMLTextAreaElement the possibility to access the original value. This is interesting to know if a form has dirty inputs. It’s also interesting because it removes the need to hide values into hidden fields or to hide into a Javascript object all original values.

From the ECMAScript’s specification we can see that it’s a property that return a string. It’s also possible to know if the value was originally checked in the case of a checkbox with defaultChecked.

From here it’s easy to know if a Html form is dirty (has something changed). We just need to loop through all inputs and compare.

function TestDirty(){
 var formDirty = false;
 $('#frm :input').each(
        function(){

            if($(this).is("input"))
            {
                //alert('Name :' + $(this).attr('name') + ">" +$(this).val()+ " != " + $(this)[0].defaultValue);
                var type = $(this).attr('type');
                if (type == "checkbox" || type == "radio")
                {

                    if ($(this).is(':checked') != $(this)[0].defaultChecked)
                    {
                        //alert('Form dirty by' + $(this).attr('name') + ">" +$(this).is(':checked')+ " != " + $(this)[0].defaultChecked);
                        formDirty = true;
                    }
                }
                else if (type == "hidden" || type == "password" || type == "text")
                {
                    if ($(this).val() != $(this)[0].defaultValue)
                    {
                        //alert('Form dirty by' + $(this).attr('name') + ">" +$(this).val()+ " != " + $(this)[0].defaultValue);
                        formDirty  =true;
                    }
                }
            }
            else
            {
                var type = $(this).get(0).tagName;
                if (type == "TEXTAREA")
                {
                    if ($(this).val() != $(this)[0].defaultValue)
                    {
                        //alert('Form dirty by' + $(this).attr('name') + ">" +$(this).val()+ " != " + $(this)[0].defaultValue);
                        return formDirty;
                    }
                }
                else(type == "SELECT")
                {
                    alert('Form dirty by ' + $(this).attr('name') + ">" +$(this).val()+ " != " + $(this)[0].defaultSelected);
                     if ($(this).val() != $(this)[0].defaultSelected)
                    {
                        //alert('Form dirty by' + $(this).attr('name') + ">" +$(this).val()+ " != " + $(this)[0].defaultValue);
                        return formDirty;
                    }
                }
            }             
        });    

return formDirty;    
}

You can have the above code functional here. The only case that doesn’t seem to work is the select box which the value is undefined. If someone has the code to fix it, feel free to post it.

ECMAScript specification about defaultValue
DefaultValue W3C reference

Entity Framework 4.3: An object with the same key already exists in the ObjectStateManager

This situation occur if you have already the object inside the DbContext and you try to Attach your instance. Most of the time you can manage it but just remove the Attach method but in some case that you might not know if the instance is inside the DbContext you may would like to check it before attaching.

This can be done with the help of DbSet and its Local property which is a collection of Locally attached entity.

if (!Database.Set<MyObject>().Local.Any(e => e.ID == myObject.ID))
    Database.MyObjects.Attach(myObject);
else
    myObject = Database.Set<MyObject>().Local.Single(e => e.ID ==  myObject.ID);

The first line verify if the Local repositor contains or not your object. This line use the primary has identifier (ID). If it doesn’t contain anything, the object is attached. Otherwise, your object will takes the reference of the one of the Local repository. This way, it won’t create a new instance of your object. Without the fourth line, you could end up with a new entry into the database even if the primary key is the same as an existing one (Entity Framework will do an Insert and the ID will auto-increment).

I am still curious to know why in some simple project, I can simply attach and never having the possibility to have twice the same object in the Local property.

Model validation and Entity Framework 4.3

In a previous post concerning the IValidatableObject with Asp.Net MV3 we have discussed the powerful of the IValidatableObject interface with MVC framework which is a fast solution to handle error in the model, error in the model binding and error in the controller.

What is great by using Microsoft ecosystem is that most of the framework work well together. If you are using the ORM Entity Framework and you are validating your business logic with the IValidatableObject interface you can benefit that before executing SaveChanges() on you database context that Entity Framework will call all model validation. This mean that you cannot forget to call it or it means that you do not need to explicitly check for the validation. If something is wrong with the model validation, when the SaveChanges() is called, Entity Framework will throw an exception.

Here is an example that we try to save an entity which fail because a business logic added into the Validate method of the inherited class IValidateObject fail. Without having to check if the ModelState.IsValid, Entity Framework call the Validate method of all changed entity and raise an exception of DbEntityValidationException. This is an awesome protection that ensure that nothing goes beyond the controller if something is wrong with the model; the database is clean.

I am pretty sure that at this point, someone will say that the exception defeat the purpose in many scenario where you would like to handle particularly all errors from all models objects and display something to the user (or to log them). Well, you can skip the exception and go directly to the model error.

            var fromDatabase = dContext.Cars.Single(p => p.Id == car.Id);
            dContext.Entry(fromDatabase).CurrentValues.SetValues(car);
            if (!dContext.GetValidationErrors().Any())
            {
                dContext.SaveChanges();
            }
            else
            {
                //Display the error in the list dContext.GetValidationErrors()
            }

As you can see, this way, you check if they are any problem and then you save if none. On the other side, if errors occur you can display them. This is very powerful because you have the entity which is problematic, all its properties that is in error and all its errors messages. This is possible because the GetValidationErrors function return a DbEntityValidationResult which contain the Entry itself, the state if it’s valid or not and a collection of error in the DbValidationError format which mean that you know what property is in error with the message.

That’s it. At this point, you know that Entity Framework work in a team with MVC’s ModelState. You do not need to add custom code in a generic model class that will contain validation method. It’s already built in. Also, if you are using Entity Framework as ORM, you can benefit of extra security that your database won’t be altered by wrong data because Entity Framework takes care to call the Validate method of all your object before using them.

How to validate model object with Asp.Net MVC correctly?

They are a lot of way to validate model object in object oriented world. Most of the time, we see that we can check the information inside the Setter (which in C# is the SET of a property). This is interesting and personally my favorite way to do it. The main reason is that you never have any model object in a dirty state which could fail on future use. My second reason is that it’s easier to control what goes in the model. Everything that goes into the object has to pass through setters and this way, everything is clean inside the model.

In my last two years of development, I had to do development with Silverlight few times and also had the use Asp.Net MVC which pushed me to use a different approach. Instead of using setter to validate input, I had to use a custom function to do it. Not that Silverlight force you to validate outside the setter, in fact, it’s still easier in my opinion with the MVVM pattern to use setter to handle exception and business rules from setter. In fact, the modification was that most of those project were already started this way, and second is that sometime, you need to validate stuff that has interdependency. Let say that you have a “Car” class which need to have special rule concerning the Color depending of the Type of this one. This mean that you need to set every time the Type before the Color. Also, with ORM that load your object directly, you may come in some situation where this one, doesn’t load your object in the right order for properties which will raise error.

In the same time, Asp.Net MVC encourage a lot to not validate directly with the setter. What motivate me to like more and more the validation outside setter is that Microsoft has implemented since the first version of ASP.Net MVC the ModelState that handle all errors from the model binding, to annotation validation in your model to your own business logic error. This is built-in. This mechanism is used by the model binding to let you know if something has not be binded correctly if you use the automatic model binding. Here is an example of automatic model binding.

public ActionResult Edit(Car car){...

.Net framework let you add you own error into the model binding. This way, inside the controller you will be able to validate if everything is fine before saving your creation or edition of your model.

        [HttpPost]
        public ActionResult Edit(Car car)
        {
            if(ModelState.IsValid)
            {
                //Update code to be placed here

                return RedirectToAction("CarList");
            }
            else
            {
                return View("CarEdit",car);
            }
        }

The code above, demonstrate the edition of a “Car” class. Two things appears in the first line. The IsValid function will return true if nothing has been added to the ModelState and will return false if Model Binding error occur OR if you have business logic error. That’s right, Asp.Net MVC will call your object business logic validation IF you use a single specific interface called “IValidatableObject“. This interface let you inherit from a method called Validate. Inside this method you need to validate your business logic. Every times an error is found, you need to add it to a collection to return it at the end of this method. This let you add many error if desired. Here is the example of the Car model object.

    public class Car: IValidatableObject
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Type { get; set; }
        public string Color { get; set; }

        public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
        {
            if(string.IsNullOrEmpty(Name))
            {
                yield return new ValidationResult("Name is mandatory", new[] {"Name"});
            }
            if (string.IsNullOrEmpty(Type))
            {
                yield return new ValidationResult("Type is mandatory", new[] { "Type" });
            }
            if (string.IsNullOrEmpty(Color))
            {
                yield return new ValidationResult("Color is mandatory", new[] { "Color" });
            }
        }
    }

As you can see, we have 3 errors that are added to the return collection with the yield statement. We could have declared a variable of IEnumerable but for the sake of the simplicity we can use yield. This collection of error is generic. The type is ValidationResult. The class ValidationResult let you add a message that will be go next to the control that has the erroneous property which is specified in the second parameter. This mean that you could set instead of “Color is mandatory” simply a star symbol and a second generic error message without specifying the property like the example below.

    public class Car: IValidatableObject
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Type { get; set; }
        public string Color { get; set; }

        public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
        {
            if(string.IsNullOrEmpty(Name))
            {
                yield return new ValidationResult("Name is mandatory", new[] {"Name"});
            }
            if (string.IsNullOrEmpty(Type))
            {
                yield return new ValidationResult("Type is mandatory", new[] { "Type" });
            }
            if (string.IsNullOrEmpty(Color))
            {
                yield return new ValidationResult("*", new[] { "Color" });
                yield return new ValidationResult("Color is mandatory"});
            }
        }
    }

So, from here you have validation from the Model Binding and from the Model class. What’s about validation that need to be done inside the action of the controller. This could be that maybe we do not want any one to edit a car that is not available. This require a call to the database and of course won’t be inside the model object. The controller can be a good position to check. No problem for the ModelState because this one doesn’t only have the IsValid property but also have the method “AddModelError” that let you add any error message.

        [HttpPost]
        public ActionResult Edit(Car car)
        {
            if(IsCarAvailable())
            {
                ModelState.AddModelError(string.Empty,"Car cannot be edited because not available anymore");
            }

            if(ModelState.IsValid)
            {
                //Update code to be placed here

                return RedirectToAction("CarList");
            }
            else
            {
                return View("CarEdit",car);
            }
        }

Some scenario remain like what about partial view or Ajax call. For partial view, no problem, everything will be stored in the ModelView which contain a dictionary of all error during the life cycle of the request to the server. The Ajax situation is not really more complex because the Ajax call will call the action method which will store all error in the ModelState. The action method will return a JsonResult for most of the time which contain, for most of the time, a partial view in a string that will be injected into a Html div. For the case that you want to get back only a positive message if it’s a success and all errors when it fails you can always return the collection of errors. Here is the way to retrieve a collection of String that contains all messages of the ModelState.

var allErrors = ModelState.Values.SelectMany(e => e.Errors).Select(gh => gh.ErrorMessage);

This can then be used where you want.

The final scenario is the one that you need to store all errors messages in a session. Well, since you can have a the list of error, it shouldn’t be hard to just store them into a session. But, let say that you desire to store the whole ModelState into a session. What is the good way to do it? This is an other story and it’s not only feasible but good pattern already been discussed about how to do it by some Microsoft MVP and Microsoft’s employees. This will be discussed in a future blog post.