<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:copyright="http://blogs.law.harvard.edu/tech/rss" xmlns:image="http://purl.org/rss/1.0/modules/image/">
    <channel>
        <title>ASP.NET MVC</title>
        <link>http://ryanrivest.com/blog/category/7.aspx</link>
        <description>ASP.NET MVC</description>
        <language>en-US</language>
        <copyright>Ryan Rivest</copyright>
        <generator>Subtext Version 2.1.1.1</generator>
        <item>
            <title>Reusable Validation Error Message Resource Strings for DataAnnotations</title>
            <link>http://ryanrivest.com/blog/archive/2010/01/15/reusable-validation-error-message-resource-strings-for-dataannotations.aspx</link>
            <description>&lt;p&gt;There are quite a few examples of using the attributes from System.ComponentModel.DataAnnotations out there in your ASP.NET MVC applications.  If you haven’t been keeping up with what’s new in ASP.NET MVC 2, one of the biggest improvements is in the area of validation – which is now automatic if you decorate your models with the attributes.  I recommend you check out &lt;a href="http://weblogs.asp.net/scottgu/archive/2010/01/15/asp-net-mvc-2-model-validation.aspx" target="_blank"&gt;ScottGu’s latest epic post&lt;/a&gt; on the topic to get up to speed.&lt;/p&gt;  &lt;p&gt;Continuing with the Gu’s example, here is our Person class and the applied validation attributes:&lt;/p&gt;  &lt;pre class="brush: csharp;"&gt;    public class Person {
        [Required(ErrorMessage = "First Name is required.")]
        [StringLength(50, ErrorMessage = "First Name must be under 50 characters.")]
        public string FirstName { get; set; }

        [Required(ErrorMessage = "Last Name is required.")]
        [StringLength(50, ErrorMessage = "Last Name must be under 50 characters.")]
        public string LastName { get; set; }

        [Required(ErrorMessage = "Age is required.")]
        [Range(0, 120, ErrorMessage = "Age must be between 0 and 120.")]
        public int Age { get; set; }

        [Required(ErrorMessage = "Email is required.")]
        [Email(ErrorMessage = "You did not enter a valid email.")]
        public string Email { get; set; }
    }&lt;/pre&gt;

&lt;p&gt;This works great, but we can take it one step further and eliminate all the explicit error message strings by using a resource file.  To add one, hit &lt;strong&gt;Ctrl+Shift+A &lt;/strong&gt;to launch the &lt;strong&gt;Add New Item &lt;/strong&gt;dialog.  You can enter any name you like, I choose to keep it simple and named it Resources.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://ryanrivest.com/blog/images/ryanrivest_com/blog/WindowsLiveWriter/ReusableValidationErrorMessageResourceSt_14381/AddResourceFile_4.gif" rel="lightbox"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="AddResourceFile" border="0" alt="AddResourceFile" src="http://ryanrivest.com/blog/images/ryanrivest_com/blog/WindowsLiveWriter/ReusableValidationErrorMessageResourceSt_14381/AddResourceFile_thumb_1.gif" width="585" height="362" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;Next, we’ll add our error message strings to the resource file.  Make note of the format items ({0}, {1}, etc.), as this is how the property names and validation attribute parameters are added to the error message.  I’ll explain how this works later in this post.  It’s also important to make sure the &lt;strong&gt;Access Modifier&lt;/strong&gt; is set to &lt;strong&gt;Public&lt;/strong&gt;.  If it’s set to Internal, ASP.NET MVC 2’s DataAnnotations Model Binder won’t validate the property at all.  This took me a few minutes to figure out what was happening, so don’t make the same mistake I did.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://ryanrivest.com/blog/images/ryanrivest_com/blog/WindowsLiveWriter/ReusableValidationErrorMessageResourceSt_14381/ValidationErrorStrings_4.gif" rel="lightbox"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="ValidationErrorStrings" border="0" alt="ValidationErrorStrings" src="http://ryanrivest.com/blog/images/ryanrivest_com/blog/WindowsLiveWriter/ReusableValidationErrorMessageResourceSt_14381/ValidationErrorStrings_thumb_1.gif" width="541" height="208" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Now that we have our Resource file created and the validation error messages defined, we can change our Person class to make use of them.  To get this working, all you need to do is specify the &lt;strong&gt;ErrorMessageResourceName&lt;/strong&gt; and &lt;strong&gt;ErrorMessageResourceType&lt;/strong&gt; when applying a validation attribute.  Here’s our new Person class making use of the resources.&lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;    public class Person {
        [Required(ErrorMessageResourceName = "Required_ValidationError", ErrorMessageResourceType = typeof(Resources))]
        [StringLength(50, ErrorMessageResourceName = "Required_ValidationError", ErrorMessageResourceType = typeof(Resources))]
        public string FirstName { get; set; }

        [Required(ErrorMessageResourceName = "Required_ValidationError", ErrorMessageResourceType = typeof(Resources))]
        [StringLength(50, ErrorMessageResourceName = "StringLength_ValidationError", ErrorMessageResourceType = typeof(Resources))]
        public string LastName { get; set; }

        [Required(ErrorMessageResourceName = "Required_ValidationError", ErrorMessageResourceType = typeof(Resources))]
        [Range(0, 120, ErrorMessageResourceName = "Range_ValidationError", ErrorMessageResourceType = typeof(Resources))]
        public int Age { get; set; }

        [Required(ErrorMessageResourceName = "Required_ValidationError", ErrorMessageResourceType = typeof(Resources))]
        [Email(ErrorMessageResourceName = "Email_ValidationError", ErrorMessageResourceType = typeof(Resources))]
        public string Email { get; set; }
    }&lt;/pre&gt;

&lt;p&gt;When we test the validation, we should see that the validation still works, and it’s now using our generalized error messages, substituting the property name and, if the validation attribute has any, the attribute parameters (as in the case of StringLength or the Range attributes).&lt;/p&gt;

&lt;p&gt;&lt;a href="http://ryanrivest.com/blog/images/ryanrivest_com/blog/WindowsLiveWriter/ReusableValidationErrorMessageResourceSt_14381/ValidationTest_2.gif" rel="lightbox"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="ValidationTest" border="0" alt="ValidationTest" src="http://ryanrivest.com/blog/images/ryanrivest_com/blog/WindowsLiveWriter/ReusableValidationErrorMessageResourceSt_14381/ValidationTest_thumb.gif" width="623" height="480" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;It works great now, but that code still looks a little verbose to me.  I don’t want to specify the resource string name and resource type every time I use one of the attributes.  My preferred approach is to subclass the validation attributes with my own of the same name.  Let’s do that now.  The strategy here is to pass the heavy lifting off to the original attribute’s constructor (if necessary), and initialize the 2 properties that we were hard-coding before.&lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;    public class RequiredAttribute : System.ComponentModel.DataAnnotations.RequiredAttribute {
        public RequiredAttribute() {
            ErrorMessageResourceName = "Required_ValidationError";
            ErrorMessageResourceType = typeof (Resources);
        }
    }

    public class StringLengthAttribute : System.ComponentModel.DataAnnotations.StringLengthAttribute {
        public StringLengthAttribute(int maximumLength) : base(maximumLength) {
            ErrorMessageResourceName = "StringLength_ValidationError";
            ErrorMessageResourceType = typeof (Resources);
        }
    }

    public class RangeAttribute : System.ComponentModel.DataAnnotations.RangeAttribute {
        public RangeAttribute(int minimum, int maximum) : base(minimum, maximum) {
            InitializeErrorMessageResource();
        }

        public RangeAttribute(double minimum, double maximum) : base(minimum, maximum) {
            InitializeErrorMessageResource();
        }

        public RangeAttribute(Type type, string minimum, string maximum) : base(type, minimum, maximum) {
            InitializeErrorMessageResource();
        }

        private void InitializeErrorMessageResource() {
            ErrorMessageResourceName = "Range_ValidationError";
            ErrorMessageResourceType = typeof(Resources);
        }
    }

    public class EmailAttribute : RegularExpressionAttribute {
        public EmailAttribute() : base("^[a-z0-9_\\+-]+(\\.[a-z0-9_\\+-]+)*@[a-z0-9-]+(\\.[a-z0-9-]+)*\\.([a-z]{2,4})$") {
            ErrorMessageResourceName = "Email_ValidationError";
            ErrorMessageResourceType = typeof (Resources);
        }
    }&lt;/pre&gt;

&lt;p /&gt;

&lt;p /&gt;

&lt;p /&gt;

&lt;p&gt;This really cleans up our model class, which now looks like this:&lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;    public class Person {
        [Required]
        [StringLength(50)]
        public string FirstName { get; set; }

        [Required]
        [StringLength(50)]
        public string LastName { get; set; }

        [Required]
        [Range(0, 120)]
        public int Age { get; set; }

        [Required]
        [Email]
        public string Email { get; set; }
    }&lt;/pre&gt;

&lt;p&gt;Much better, and our validation still works as we expected, without all the string and type duplication.  The only problem I see now is that our error messages use the exact property name, which isn’t always what we want.  For example, when the user submits the form without entering a value in the FirstName field, they receive the error message “&lt;strong&gt;&lt;span style="color: #ff0000"&gt;FirstName is required.&lt;/span&gt;&lt;/strong&gt;”  I would much rather see “First Name is required.” instead.  Good news!  They made this really easy to change for nitpickers like me.&lt;/p&gt;

&lt;p&gt;To get our property name showing up nicely, all we have to do is apply the &lt;strong&gt;DisplayName &lt;/strong&gt;attribute to the &lt;strong&gt;FirstName &lt;/strong&gt;property.&lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;    [DisplayName("First Name")]
    public string FirstName { get; set; }&lt;/pre&gt;

&lt;p&gt;This also has the added benefit of updating the FirstName field’s label as well, since we’re using ASP.NET MVC 2’s strongly typed label HTML helper (which uses the property name if no display name is available).&lt;/p&gt;

&lt;p&gt;&lt;a href="http://ryanrivest.com/blog/images/ryanrivest_com/blog/WindowsLiveWriter/ReusableValidationErrorMessageResourceSt_14381/DisplayNameError_2.gif" rel="lightbox"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="DisplayNameError" border="0" alt="DisplayNameError" src="http://ryanrivest.com/blog/images/ryanrivest_com/blog/WindowsLiveWriter/ReusableValidationErrorMessageResourceSt_14381/DisplayNameError_thumb.gif" width="623" height="455" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;As a bonus, if we enable client side validation, everything still works!  You can see an example of this in the sample code (link below).&lt;/p&gt;

&lt;h2 /&gt;

&lt;h3&gt;How it Works:  FormatErrorMessage()&lt;/h3&gt;

&lt;p&gt;Let’s take a peek inside the FormatErrorMessage() method on the &lt;strong&gt;StringLengthAttribute&lt;/strong&gt;:&lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;public override string FormatErrorMessage(string name) {
    return string.Format(CultureInfo.CurrentCulture, base.ErrorMessageString, new object[] { name, this.MaximumLength });
}&lt;/pre&gt;

&lt;p&gt;Every ValidationAttribute will either inherit this method, or implement their own (if it has additional parameters, like String Length, which has a maximum length that is supplied to the attribute.  As you can see, this method is simply using string.Format, and supplying the name as {0} and the MaximumLength property as {1}.  Simple enough, right?&lt;/p&gt;

&lt;p&gt;If you want to poke around in the code, you can &lt;strong&gt;&lt;a href="http://ryanrivest.com/downloads/ReusableValidationStrings.zip" target="_blank"&gt;download the sample&lt;/a&gt;&lt;/strong&gt; here.&lt;/p&gt;&lt;img src="http://ryanrivest.com/blog/aggbug/13.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Ryan Rivest</dc:creator>
            <guid>http://ryanrivest.com/blog/archive/2010/01/15/reusable-validation-error-message-resource-strings-for-dataannotations.aspx</guid>
            <pubDate>Sat, 16 Jan 2010 07:00:21 GMT</pubDate>
            <wfw:comment>http://ryanrivest.com/blog/comments/13.aspx</wfw:comment>
            <comments>http://ryanrivest.com/blog/archive/2010/01/15/reusable-validation-error-message-resource-strings-for-dataannotations.aspx#feedback</comments>
            <wfw:commentRss>http://ryanrivest.com/blog/comments/commentRss/13.aspx</wfw:commentRss>
        </item>
        <item>
            <title>Book Review: ASP.NET MVC 1.0 Test Driven Development</title>
            <link>http://ryanrivest.com/blog/archive/2009/09/24/book-review-asp.net-mvc-1.0-test-driven-development.aspx</link>
            <description>&lt;p&gt;When I first discovered ASP.NET MVC, I was about to begin development on a brand new project at work.  Since I come from a more “pure” background of web development (not Web Forms), I immediately got excited when I heard about this new framework.  The pieces began to click in my mind.. *finally* an ASP.NET that doesn’t rely on the drag and drop experience and hide the true nature of the web, I thought.&lt;/p&gt;  &lt;p&gt;Day after day I would read articles and watch conference videos about this new and exciting way to build web apps with ASP.NET.  Around the same time, I started learning about unit testing and Test Driven Development (TDD).  It just so happens that the authors of ASP.NET MVC designed their framework with testability as a first-class citizen, so TDD is a natural fit.  So natural, in fact, that you were sometimes hard-pressed to find an introduction to ASP.NET MVC without a cameo by TDD.  Often people wondered whether you were required to use TDD to build apps with ASP.NET MVC.&lt;/p&gt;  &lt;p&gt;Everyone mentions how well the framework lends itself to TDD, but few actually explain how you would go about building an application with TDD straightaway.  Steven Anderson’s book Pro ASP.NET MVC has a great introductory tutorial for building a working application with a test-first approach, but his book is so in depth (a &lt;em&gt;good&lt;/em&gt; thing!), that sometimes the process gets a little lost in the background.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.amazon.com/ASP-NET-MVC-Test-Driven-Development/dp/0470447621/ref=cm_cr_pr_product_top" target="_blank"&gt;&lt;img src="http://ecx.images-amazon.com/images/I/41g3WLv6asL._SL160_.jpg" /&gt; &lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Recently I picked up a copy of &lt;a href="http://www.amazon.com/ASP-NET-MVC-Test-Driven-Development/dp/0470447621/ref=cm_cr_pr_product_top" target="_blank"&gt;ASP.NET MVC 1.0 Test Driven Development: Problem - Design - Solution&lt;/a&gt; by Emad Ibrahim&lt;/p&gt;  &lt;p&gt;This is the book that I have been waiting for since ASP.NET MVC came out.  I’ve already read books explaining the details of ASP.NET MVC, so I wasn’t looking for another book to explain every aspect of the framework.  This isn’t an in-depth book on TDD or ASP.NET MVC, so if you’re looking for reference material on ASP.NET MVC, I recommend you look elsewhere, as there are &lt;a href="http://www.amazon.com/Professional-ASP-NET-MVC-Wrox-Programmer/dp/0470384611%3FSubscriptionId%3D0JTCV5ZMHMF7ZYTXGFR2%26tag%3Dbrdicr-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3D0470384611" target="_blank"&gt;&lt;strong&gt;several&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;&lt;a href="http://www.amazon.com/ASP-NET-MVC-Action-Jeffrey-Palermo/dp/1933988622%3FSubscriptionId%3D0JTCV5ZMHMF7ZYTXGFR2%26tag%3Dbrdicr-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3D1933988622" target="_blank"&gt;excellent&lt;/a&gt;&lt;/strong&gt; &lt;a href="http://www.amazon.com/Pro-ASP-NET-Framework-Steven-Sanderson/dp/1430210079%3FSubscriptionId%3D0JTCV5ZMHMF7ZYTXGFR2%26tag%3Dbrdicr-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3D1430210079" target="_blank"&gt;&lt;strong&gt;books&lt;/strong&gt;&lt;/a&gt; that have been out for a while.  I’ve had the pleasure of reading all three of the books I linked, and they’re all very good, in-depth technical resources if you’re looking for a book to explain every aspect of the framework.&lt;/p&gt;  &lt;p&gt;ASP.NET MVC 1.0 Test Driven Development is essentially a ~260 page tutorial for building an application with ASP.NET MVC using the TDD process.  Some familiarity with both of them is necessary to get the most of this book.  If you’re not at least mildly comfortable with unit testing, you will have a problem reading this book.  The same goes for ASP.NET MVC.&lt;/p&gt;  &lt;p&gt;The theme is centered around a bulk email/newsletter distribution web application called EvenContact and the author takes us through the entire development process, starting with the high-level requirements for what the application needs to do.  &lt;/p&gt;  &lt;p&gt;This was the first Problem – Design – Solution title I’ve read from Wrox, and I really appreciated the structure of each chapter.  It highlighted the goals for each chapter by defining what the requirements were for a certain feature, the high-level design, and the author’s implementation.  It made things really clear.&lt;/p&gt;  &lt;p&gt;Even though it was surface level, I enjoyed the overview of methodologies and design patterns in chapter 1.  It was a good introduction to the tools and practices that he would be using throughout the book, and I appreciated the introduction, which would be perfect if I had not seen the patterns before.&lt;/p&gt;  &lt;p&gt;There were some artifacts left behind from pre-release versions of ASP.NET MVC 1.0 that I would have liked to see accurately reflected in the text.  Luckily for me, it was a non-issue because I followed most of the development changes from the CTP’s, but I can see this being confusing to newcomers.&lt;/p&gt;  &lt;p&gt;One other important point to note – if you’re the type of person who gets lost easily when details are left out, this may not be the book for you.  The author leaves out a lot of fluff when he’s explaining new concepts and features.  Personally, I appreciated not having to go through the same steps for every single new feature in the application, but it may be something to consider for you.  I should also note that because of this fact, there are a lot of features that appear out of thin air in the text.&lt;/p&gt;  &lt;p&gt;Even with the author’s intent to keep the book interesting by not repeating the same steps, the book does feel a bit repetitive.  We end up seeing the same tests repeated often for each new feature, and I found myself skim-reading through a lot of the second half, because it was things I had seen in the book already.&lt;/p&gt;  &lt;p&gt;There were quite a few other typos and errors here and there in the text as well, which was surprising for a published book, but I guess it’s acceptable for a first edition.  Nonetheless, looking past the nitpicking, I still feel that it was a pretty good book, and may be a good reference for the combination of TDD and ASP.NET MVC.  There were definitely some takeaways that I got from the book and will be putting into use immediately.&lt;/p&gt;&lt;img src="http://ryanrivest.com/blog/aggbug/12.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Ryan Rivest</dc:creator>
            <guid>http://ryanrivest.com/blog/archive/2009/09/24/book-review-asp.net-mvc-1.0-test-driven-development.aspx</guid>
            <pubDate>Fri, 25 Sep 2009 04:04:19 GMT</pubDate>
            <wfw:comment>http://ryanrivest.com/blog/comments/12.aspx</wfw:comment>
            <comments>http://ryanrivest.com/blog/archive/2009/09/24/book-review-asp.net-mvc-1.0-test-driven-development.aspx#feedback</comments>
            <wfw:commentRss>http://ryanrivest.com/blog/comments/commentRss/12.aspx</wfw:commentRss>
        </item>
    </channel>
</rss>