Archive for January, 2010

Code Contracts and Entity Framework

January 29th, 2010

Using Code Contracts in projects that use Entity Framework for data access is possible, but there are a few wrinkles to consider.

Although the designer emits partial classes, that isn’t enough to add contracts because we need to add pre and postconditions directly to the generated methods.

The answer is to use a reference assembly. This contains the contract information for the data access classes, but is otherwise not used by the client class.

Here’s how this is done:

1. Move the Entity Framework code into its own project. This isn’t absolutely essential, but will keep things simpler.

2. Make sure that we don’t attempt to emit contract information for this assembly. On the pojrect properties screen move to the Code Contracts tab and select ‘Do Not Build’.

3. Create a new project for the contract information. You should name the project MyModel.Contracts but the assembly name should be the same as the Model project, so you will need to move to the Application tab of project properties.

4. In the contract assembly create classes for each entity object you want to specify conditions for.  For example:

public partial class MyObject : EntityObject
{
    public void Foo()
    {
        Contract.Requires(Bar != null);
    }
}

Remember the code doesn’t need to do anything except specify contract conditions.  It won’t be run by the real application although it must compile.

5. Make sure the contract assembly emits contract information by selecting ‘Build’ on the Code Contracts tab of the assembly properties.

6. In your client class, make sure it picks up contract information from the contract assembly rather than looking in the model assembly itself. To do this go to the Code Contracts tab and check the ‘call-site requires checking’ box. Then in the Lib Paths section of the advanced settings on the contracts tab add the path to the contract assembly (e.g. ..\..\MyModel.Contract\bin\debug). The deployed code will now use the objects from the model assembly at runtime, but will obtain contract information from the contract assembly.

Share

ReSharper and Microsoft Code Contracts

January 27th, 2010

I’m using code contracts in an MVC RC / .NET 3.5 application and I don’t want ReSharper 5 complaining about potential null reference accesses that aren’t in fact possible due to the contracts.

The solution (pieced together from StackOverflow and JetBrains) is to add the following XML to a file named C:\Program Files\JetBrains\ReSharper\v5.0\Bin\ExternalAnnotations\Microsoft.Contracts\Microsoft.Contracts.xml.

<assembly name="Microsoft.Contracts">
  <member name="M:System.Diagnostics.Contracts.Contract.Requires(System.Boolean)">
    <attribute ctor="M:JetBrains.Annotations.AssertionMethodAttribute.#ctor"/>
    <parameter name="condition">
      <attribute ctor="M:JetBrains.Annotations.AssertionConditionAttribute.#ctor(JetBrains.Annotations.AssertionConditionType)">
        <argument>0</argument>
    </attribute>
    </parameter>
  </member>
  <member name="M:System.Diagnostics.Contracts.Contract.Requires``1(System.Boolean)">
    <attribute ctor="M:JetBrains.Annotations.AssertionMethodAttribute.#ctor"/>
    <parameter name="condition">
      <attribute ctor="M:JetBrains.Annotations.AssertionConditionAttribute.#ctor(JetBrains.Annotations.AssertionConditionType)">
        <argument>0</argument>
      </attribute>
    </parameter>
  </member>
  <member name="M:System.Diagnostics.Contracts.Contract.Requires(System.Boolean,System.String)">
    <attribute ctor="M:JetBrains.Annotations.AssertionMethodAttribute.#ctor"/>
    <parameter name="condition">
      <attribute ctor="M:JetBrains.Annotations.AssertionConditionAttribute.#ctor(JetBrains.Annotations.AssertionConditionType)">
        <argument>0</argument>
      </attribute>
    </parameter>
  </member>
  <member name="M:System.Diagnostics.Contracts.Contract.Requires``1(System.Boolean,System.String)">
    <attribute ctor="M:JetBrains.Annotations.AssertionMethodAttribute.#ctor"/>
    <parameter name="condition">
      <attribute ctor="M:JetBrains.Annotations.AssertionConditionAttribute.#ctor(JetBrains.Annotations.AssertionConditionType)">
        <argument>0</argument>
      </attribute>
    </parameter>
  </member>
  <member name="M:System.Diagnostics.Contracts.Contract.Invariant(System.Boolean)">
    <attribute ctor="M:JetBrains.Annotations.AssertionMethodAttribute.#ctor"/>
    <parameter name="condition">
      <attribute ctor="M:JetBrains.Annotations.AssertionConditionAttribute.#ctor(JetBrains.Annotations.AssertionConditionType)">
        <argument>0</argument>
      </attribute>
    </parameter>
  </member>
  <member name="M:System.Diagnostics.Contracts.Contract.Invariant(System.Boolean,System.String)">
    <attribute ctor="M:JetBrains.Annotations.AssertionMethodAttribute.#ctor"/>
    <parameter name="condition">
      <attribute ctor="M:JetBrains.Annotations.AssertionConditionAttribute.#ctor(JetBrains.Annotations.AssertionConditionType)">
        <argument>0</argument>
      </attribute>
    </parameter>
  </member>
  <member name="M:System.Diagnostics.Contracts.Contract.Assume(System.Boolean)">
    <attribute ctor="M:JetBrains.Annotations.AssertionMethodAttribute.#ctor"/>
    <parameter name="condition">
      <attribute ctor="M:JetBrains.Annotations.AssertionConditionAttribute.#ctor(JetBrains.Annotations.AssertionConditionType)">
        <argument>0</argument>
      </attribute>
    </parameter>
  </member>
</assembly>
Share

Adobe BrowserLab

January 20th, 2010

I got forwarded this link to Adobe BrowserLab.  Is a great way of seeing how your site looks in different browsers.  Thanks Nick!

Adobe Labs – Adobe BrowserLab.

Share

Using the ASP.NET MVC source code to debug your app « Steve Sanderson’s blog

January 20th, 2010

Found this useful hint for debugging MVC 2 RC applications.  hopefully MS will publish the source code on their source server soon.  In the meantime…

Using the ASP.NET MVC source code to debug your app « Steve Sanderson’s blog.

Share

Using SQL Express Databases

January 18th, 2010

If you use a SQL Express database for LINQ to SQL in an MVC application Studio will create an App_Data directory and put the database there. However, when you copy your solution up to a web host you might get connection problems. This is likely to be because the LINQ designer has embedded a path to the database that isn’t valid on the server.
The fix is really simple – just use the |DataDirectory| keyword in your Web.config.

<connectionStrings>
    <add name="ApplicationServices" connectionString="data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|aspnetdb.mdf;User Instance=true" providerName="System.Data.SqlClient"/>
</connectionStrings>
Share

MVC 2 Cross-field Validation

January 18th, 2010

The built in annotation-based validation in MVC is fine, but sometimes you need to validate a property relative to other properties on the page.  For example, you might want to make sure that two properties are the same (password and confirm password) for example.

This post explains how to extend the validation model to cater for this.

First we need to create new validation attributes to annotate our data model with.  I use the following interface for all attributes that require more than one field to validate:

/// summary>
/// All validation data annotation attributes that require more than one
/// property to validate (or additional context) should implement this
/// interface.
// </summary>
public interface IRichValidationAttribute
{
    /// <summary>
    /// Determines whether the specified property is valid.
    /// </summary>
    /// <param name="controllerContext">Complete controller context (if required).</param>
    /// <param name="model">The model object to which the property belongs.</param>
    /// <param name="modelMetadata">Model metadata relating to the property holding
    /// the validation data annotation.</param>
    /// <returns>
    /// <c>true</c> if the specified property is valid; otherwise, <c>false</c>.
    /// </returns>
    bool IsValid(ControllerContext controllerContext, object model, ModelMetadata modelMetadata);
}

Now we can create a new attribute that implements this interface:

[AttributeUsage(AttributeTargets.Property |   AttributeTargets.Field, AllowMultiple = false)]
public class NotEqualToPropertyAttribute : ValidationAttribute, IRichValidationAttribute
{
   /// <summary>
    /// Gets or sets the other property we are validating against.
    /// </summary>
    public string OtherProperty { get; set; }

   /// <summary>
    /// Determines whether the specified value of the object is valid.
    /// </summary>
    /// <param name="value">
    /// The value of the specified validation object on which the attribute is declared.
    /// </param>
    /// <returns>
    /// true if the specified value is valid; otherwise, false.
    /// </returns>
    public override bool IsValid(object value)
    {
        // Work done in other IsValid
        return true;
    }

    /// <summary>
    /// Determines whether the specified property is valid.
    /// </summary>
    /// <param name="controller">Complete controller context (if required).</param>
    /// <param name="model">The model object to which the property belongs.</param>
     /// <param name="modelMetadata">Model metadata relating to the property holding the validation data annotation. </param>
     /// <returns>
     /// true if the specified property is valid; otherwise, false.
     /// </returns>
     public bool IsValid(ControllerContext controllerContext, object model, ModelMetadata modelMetadata)
     {
        if (model == null)
        {
             throw new ArgumentNullException("model");
        }
        // Find the value of the other property.
        var propertyInfo = model.GetType().GetProperty(OtherProperty);
        if (propertyInfo == null)
        {
           throw new InvalidOperationException(string.Format("Couldn't find {0} property on {1}.", OtherProperty, model));
        }
        var otherValue = propertyInfo.GetGetMethod().Invoke(model, null);
        return modelMetadata.Model.ToString() != otherValue.ToString();
    }
}

This can then be applied to the model:

[NotEqualToProperty(ErrorMessage = "Other occupation cannot be the same as the main occupation",
OtherProperty = "Occupation")]
public Occupation OtherOccupation { get; set; }

Now we need to create a validator for the attribute. I’ve created a base class for all validators than used the enhanced validation interface:

/// <summary>
/// A base class for validators that have attributes that require more
/// than one property to check for validity.
/// The standard <see cref="ValidationAttribute.IsValid"/> method
/// isn't sufficient because this method can't see the rest of the model.
/// </summary>
/// <typeparam name="TAttribute">The type of the attribute.</typeparam>
public abstract class CrossFieldValidator<TAttribute> : DataAnnotationsModelValidator<TAttribute> where TAttribute : ValidationAttribute
{
    protected CrossFieldValidator(ModelMetadata metadata, ControllerContext context, TAttribute attribute) : base(metadata, context, attribute)
    {
    }
}

/// <summary>
/// Returns a list of validation error messages for the model.
/// </summary>
/// <param name="container">The container for the model.</param>
/// <returns>
/// A list of validation error messages for the model, or an empty list if no errors have occurred.
/// </returns>
public override IEnumerable<ModelValidationResult> Validate(object container)
{
var attribute = Attribute as IRichValidationAttribute;
if (attribute != null)
{
if (!attribute.IsValid(ControllerContext, container, Metadata))
{
yield return new ModelValidationResult { Message = ErrorMessage };
}
}
else if (!Attribute.IsValid(container))
{
yield return new ModelValidationResult { Message = ErrorMessage };
}
}

Finally we need to create the client-side script:

jQuery.validator.addMethod("notequaltoproperty", function(value, element, params) {
    if (this.optional(element)) {
        return true;
    }

   var otherPropertyControl = $("#" + params.otherProperty);
    if (otherPropertyControl == null) {
       return false;
    }

    var otherPropertyValue = otherPropertyControl[0].value;
    return otherPropertyValue != value;
});

And that’s it.

Share

Testing Validation Attributes

January 14th, 2010

This code illustrates how to unit test your MVC 2 data annotation validation attributes.

In this example we are using this model object:

public class Foo
{
    [Required(ErrorMessage= "Must give a name")]
    public string Name { get; set; }

  
    [Required(ErrorMessage = "Must give a DOB")]
    [Range(typeof(DateTime), "2009/01/01", "2011/01/01",Â
        
ErrorMessage = "Must be in range")]
    public DateTime DateOfBirth { get; set; }
}

This examples shows two simple test cases: if a name is given validation is successful, but if it isn’t we get a validation error.  Using RhinoMocks and the MS Test framework we end up with this test class:

[TestClass]
public class FooTest
{
    private const string originalName = "Barry Bar";
    private const string newName = "Fred Foo";

    [TestMethod]
    public void NameIsValid()
    {
        var foo = new Foo {Name = originalName};
        var name = new ValueProviderResult(newName, newName, CultureInfo.CurrentCulture);


        var binder = new DefaultModelBinder();
        var controllerContext = new ControllerContext();

        var bindingContext = new ModelBindingContext
        {
            ModelMetadata =
                ModelMetadataProviders.Current.GetMetadataForType(() => foo, foo.GetType()),
            ValueProvider = new Dictionary<string, ValueProviderResult> { { "Name", name } }
        };

        var boundFoo = binder.BindModel(controllerContext, bindingContext) as Foo;
        Assert.AreEqual(newName, boundFoo.Name);
        Assert.IsTrue(bindingContext.ModelState.IsValid);
    }


    [TestMethod]
    public void NameIsRequired()
    {
        var foo = new Foo { Name = originalName };
        var name = new ValueProviderResult(null, null, CultureInfo.CurrentCulture);


        var binder = new DefaultModelBinder();
        var controllerContext = new ControllerContext();

Â
        var bindingContext = new ModelBindingContext
        {
            ModelMetadata =
                ModelMetadataProviders.Current.GetMetadataForType(() => foo, foo.GetType()),
            ValueProvider = new Dictionary<string, ValueProviderResult> { { "Name", name } }
        };


        var boundFoo = binder.BindModel(controllerContext, bindingContext) as Foo;
        Assert.AreEqual(originalName, boundFoo.Name);
        Assert.IsFalse(bindingContext.ModelState.IsValid);
        }
    }
}

And that’s all there is to it.

Share

Validating dropdown lists in MVC 2 RC

January 12th, 2010

Here's a couple of gotchas when validating dropdown lists in MVC using jQuery validation.

Implicit [Required] Attribute

Doing any kind of validation on a dropdown list, or even just creating a validation message for it, implicit makes the list a required value. This is only a problem if the issue below affects you.

List Options Must Have a Value

Every option in the Select must have a value, e.g.:

 

<option value="1">Mr</option>

 

rather than

 

<option>Mr</option>

 

If it doesn't, the jQuery required validation will fail.

Share