Friday, February 24, 2012

MVC4 Beta seems to work quite a bit better with Entity Framework DbValidationExceptiona

In MVC3, if you had an exception from the Fluent validation upon save, you had to specifically catch these exceptions and add them to modelstate. Check out the prior post, I have code in there to handle this case in MVC3 (see below)

I've tested MVC4 and it seems to now catch these validation errors automatically as expected. However I've had problems with fields such as
[Timestamp]
public byte[] Timestamp {get;set;}

no matter what I do these won't save and contain errors so I'll have to experiment a little more with those. Even using [ReadOnly(true)] is ignored and errors are still generated.

 /// 
    /// Author: Adam Tuliper
    /// adam.tuliper@gmail.com
    /// completedevelopment.blogspot.com
    /// www.secure-coding.com
    /// Use freely, just please retain original credit.
    /// 
    /// This filter will add errors to ModelState when an entity fails validation and raises DbEntityValidationException
    /// The properties in the entity should share the same name as the ViewModel properties otherwise
    /// the errors will show up in the validation summary as 'general' errors not assigned to a property
    /// Also note in MVC4 this IS NOT REQUIRED as this is finally handled by the framework then.
    /// 
    public class MapEntityExceptionsToModelErrorsAttribute : FilterAttribute, IExceptionFilter
    {

        public MapEntityExceptionsToModelErrorsAttribute()
        {
        }

        public void OnException(ExceptionContext filterContext)
        {
            if (!filterContext.ExceptionHandled && filterContext.Exception is DbEntityValidationException)
            {
                var model = filterContext.Controller.ViewData.Model;

                foreach (var error in ((System.Data.Entity.Validation.DbEntityValidationException)filterContext.Exception).EntityValidationErrors.First().ValidationErrors)
                {
                    //If the error does not exist in the modelstate, then we will simply add it as a general validation message.
                    var keys = filterContext.Controller.ViewData.ModelState.Keys;
                    if (filterContext.Controller.ViewData.ModelState[error.PropertyName].Errors.Count == 0)
                    {
                        filterContext.Controller.ViewData.ModelState.AddModelError(error.PropertyName, error.ErrorMessage);
                    }
                    else
                    {
                        //Ensure this same message doesn't already exist. If ModelState is detected to have failed,
                        //for instance from a [Required] field, then we don't want to re-add the error. However if we have
                        //a more serious validation error, possibly stemming from some other data validation maybe not related to 
                        //our viewmodel (invalid dat in db, or some other code error bypassing validations)
                        //then we want to add the error. This can happen on Save() and not caught in modelstate.
                        bool found = false;
                        foreach (var errorItem in filterContext.Controller.ViewData.ModelState[error.PropertyName].Errors)
                        {
                            if (errorItem.ErrorMessage == error.ErrorMessage)
                            {
                                found = true;
                                break;
                            }
                        }

                        if (!found)
                        {
                            filterContext.Controller.ViewData.ModelState.AddModelError("", error.ErrorMessage);
                        }
                    }
                }
                //No need to have other exception filters run
                filterContext.ExceptionHandled = true;

                filterContext.Result = new ViewResult() { ViewData = filterContext.Controller.ViewData };
            }
        }
    }

South Florida Code Camp Entity Framework Demo

This was a great event last weekend!
Please find the Entity Framework demo code here

My apologies on the web forms demo not validating, I had turned off 'validate on save'. This demo code should all work fine. Let me know if you have any question.
Thanks!

Monday, January 30, 2012

VSLive is coming to Vegas!!!

I'll be doing two sessions at VSLive Las Vegas
The popular "Hack Proofing your ASP.NET Applications" and
"Entity Framework 4.2 for Web Applications"

You'll get one on one time with me for any security or EF (or anything else for that matter) questions you might have as well.

Register with promo code VLSPK25 for some extra savings!!!


Visual Studio Live Las Vegas
Mirage Resort & Casino
March 26-30, 2012
Event web site: http://vslive.com/lasvegas

Visual Studio Live is five days of practical, Microsoft-supported training for developers to help solve your tough .NET development challenges. You'll find how-to advice and the tips and tricks that you'll be ready to implement as soon as you get back to the office. Our expert faculty - including many Microsoft instructors - makes each session interactive so you can discuss your particular development roadblocks and come away with actionable solutions.

Visual Studio Live Las Vegas offers in-depth training in:
Cloud Computing
Cross Platform Mobile
Data Management
HTML5
Silverlight / WPF
Visual Studio 2010+/.NET 4+
Web
Windows 8/WinRT
Windows Phone 7

Visual Studio Live Las Vegas – Expert Solutions for .NET Developers

Thursday, December 8, 2011

Using Dependency Injection with MVC

This is the code from the brief talk on Dependency Injection with MVC.
There are two projects here. This uses Unity, MVC3, and the UNity.MVC3 nuget package which has some additional code in it to handle lifetime management (ie objects that need disposal need special note in the bootstrapper.cs file.

IoC MVC Demos

Monday, December 5, 2011

Stop using MVC's ViewBag in most places, please!

Even the built in templates give us support for ViewBag. The scaffolding templates create ViewBag.SomeEnumerable to use for our pages.
Sure - its quick code and since it's auto-generated will likely work ok. The problem comes in from the fact that ViewBag is a dynamic object. There are no compile time type checks. If you misspell something you won't be notified from the compiler.

I've seen this used in such bad ways, I would love to see it's usage curbed and applications cleaned up.

So in a controller:
ViewBag.SomeProperty = "10"
and in the view:
@ViewBag.Som3Pr0p3rty
We won't ever know of this error. It won't even generate a runtime error since the misspelled name just generated a null.


Use ViewModels and save yourself from these potential problems. Our templates set a page title in ViewBag as well.


There are several options in setting a page title. Since this is a well known property one could argue that using it just for Title is ok. I wouldn't argue this. There are other options.
1. Set it in a section in the layout and render it from the client.
2. Use ViewBag.Title
3. Use a filter (seems much too complicated for a title)
4. Use a Model.Title field.

Since by default we have a ViewBag.Title field created and our templates also get it by default, I'll yield that in this case, its ok.

What about select lists?
Rather than the default

 ViewBag.CustomerId = new SelectList(db.Customers, "CustomerId", "FirstName", order.CustomerId);


Do something like
yourViewModel.Customers = customers; //a loaded collection

and in your view
@Html.DropDownListFor(x => x.CustomerId, new SelectList(Model.Customers, "CustomerId", "Name"))

Or if you prefer to set your ViewModel to contain the SelectList


yourViewModel.Customers = new SelectList(db.Customers, "CustomerId", "Name", order.CustomerId);

and now your view would be slightly cleaner as:
@Html.DropDownListFor(x => x.CustomerId, x.Customers)

See, that's not so difficult now is it? Enjoy!

Friday, October 7, 2011

CodeCamp NYC Entity Framework / MVC code

Thanks to all the attendees for a great event! Here is a link to the demo project used both for the MVC and Entity framework application. Some more advanced MVC samples are included in a prior posting in august, but for this demo everything is in the zip.
Files here - Note - Click 'download original' in the upper right hand corner once the view loads

Friday, August 19, 2011

Learning MVC for the Web Forms Developer - Code + Slides

There was a slightly older version of this posted, here's the slides (and code projects) from the current user group presentation. This is a 7-zip file for reduced size (yes - every time 7-zip wins out over zip in my tests!)

Code and slides