EF Code First/MVC NotNullAttribute

Unfortunately MVC3 doesn’t respect the [Required] attribute’s AllowEmptyStrings property. When using a class both as an MVC model and as an EF Code First entity this is a problem. What if I want to allow empty strings, but not null values in the database?

The problem lies in the client side validation performed by MVC3. If a property in the model is marked with [Required] the jquery required validator will be enabled. It requires a non-empty string. I would prefer MVC to not emit a required validation if AllowEmptyStrings is true. Unfortunately the MVC code doesn’t honor that flag, but there is a workaround. Create a small attribute derived from RequiredAttribute.

public sealed class NotNullAttribute : RequiredAttribute
{
    public NotNullAttribute()
    {
        AllowEmptyStrings = true;
    }
}

To make it work, another attribute has to be set on the property to prevent the model binder from converting an empty string to null.

[NotNull]
[DisplayFormat(ConvertEmptyStringToNull = false)]
public string SomeProperty { get; set; }

It is surprisingly simple, but works thanks to a difference in how EF Code First and MVC3 handles attributes.

Update-Database MSI Custom Action

In the Prevent EF Migrations from Creating or Changing the Database post I showed how to prevent the application from automatically creating or updating the database. Instead I want the installation program to do that. With a Web Setup Project for the installation an MSI Custom Action is needed.

The actual work of updating the database is done by the migrate.exe tool. To make the MSI package run it properly turned out to be a bit of a challenge. I first included migrate.exe in the installation package to have it deployed to the bin directory together with the assemblies of the system. There is support for running an exe file as a custom action in the web setup projects. Ufortunately I couldn’t get migrate.exe to work unless the working directory was set to the bin directory. The working directory for custom actions is c:\windows\system32 by default. To handle that, a small vb-script was used.

Type Safe SelectList Factory

I think that ASP.NET MVC is a huge step forward from ASP.NET Web Forms. Still, there are some parts of it that are disappointing. One is the SelectList constructor, that doesn’t use generics and has string parameters for field selection. To create a SelectList from an IEnumerable<> we would do something like this.

IEnumerable<person> people = GetPeople();
SelectList selectList = new SelectList(people, "Id", "FullName");</person>

This is again one of those places where the compiler won’t be able to help us. Writing member names as strings in the code is just horrible. To remedy this I wrote a factory method with those strings changed into lambdas.

IEnumerable<person> = GetPeople();
SelectList selectList = 
  people.ToSelectList(people, p => p.Id, p => p.FullName);</person>

jQuery UI Replacement for alert()

The Javascript alert(message) is a simple one-liner to show a message on a web page. It uses a standard system dialog box to display the message. On a site where most other UI elements are built using jQuery UI it is more natural to display the alerts in the same style. Unfortunately there is no built in one-liner for displaying a simple alert in jQuery UI, but it is easy to add an own one.


This is a standard jQuery UI dialog displayed using one line of code. It follows the same theme as the rest of the jQuery UI widgets used on the site and it behaves like a normal modal dialog. The code used for displaying the dialog is $.alert("message", "title"), which is a jQuery extension I added with a few lines of code.

Catch Errors in ASP.NET MVC Views

The compiler is my friend. It helps me check for simple spelling mistakes and alerts me when a change in one part of the code base breaks a reference somewhere else.

When developing in ASP.NET Web Forms I have had a hard time with the lack of  compilation of aspx pages. As long as the code is in the code behind,  errors are catched during compilation. If the code is in the aspx file itself (e.g. data binding code) it doesn’t fail until the page is accessed. A large application with hundreds of pages requires detailed testing to make sure all pages have been accessed.

In ASP.NET MVC (which I really recommend instead of Web Forms) there is a far better way. The views can be included in the project build, catching any simple mistakes when building. Unfortunately it is not a standard setting, but it is easy to add.

Software Development is a Job – Coding is a Passion

I'm Anders Abel, a systems architect and developer working for Kentor in Stockholm, Sweden.

profile for Anders Abel at Stack Overflow, Q&A for professional and enthusiast programmers

The complete code for all posts is available on GitHub.

Popular Posts

Archives

Series

Powered by WordPress with the Passion for Coding theme.