<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss1full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:admin="http://webns.net/mvcb/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:cc="http://web.resource.org/cc/" xmlns="http://purl.org/rss/1.0/" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">

<channel rdf:about="http://bradwilson.typepad.com/blog/">
<title>Brad Wilson</title>
<link>http://bradwilson.typepad.com/blog/</link>
<description>Technologist. Agile Evangelist. Poker Player. Amateur Neologist. Metalhead.</description>
<dc:language>en-US</dc:language>
<dc:creator />
<dc:date>2009-10-29T15:11:31-07:00</dc:date>
<admin:generatorAgent rdf:resource="http://www.typepad.com/" />


<items>
<rdf:Seq><rdf:li rdf:resource="http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-5-master-page-templates.html" />
<rdf:li rdf:resource="http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-4-custom-object-templates.html" />
<rdf:li rdf:resource="http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-3-default-templates.html" />
<rdf:li rdf:resource="http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-2-modelmetadata.html" />
<rdf:li rdf:resource="http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-1-introduction.html" />
<rdf:li rdf:resource="http://bradwilson.typepad.com/blog/2009/10/enterprise-library-validation-example-for-aspnet-mvc-2.html" />
<rdf:li rdf:resource="http://bradwilson.typepad.com/blog/2009/09/xunitnet-15-shipped.html" />
<rdf:li rdf:resource="http://bradwilson.typepad.com/blog/2009/09/movie-server-handbrake-and-interlacing.html" />
<rdf:li rdf:resource="http://bradwilson.typepad.com/blog/2009/08/pauseps1.html" />
<rdf:li rdf:resource="http://bradwilson.typepad.com/blog/2009/08/xunitnet-15-beta-released.html" />
</rdf:Seq>
</items>

<geo:lat>47.677471</geo:lat><geo:long>-122.121383</geo:long><feedburner:feedFlare href="http://add.my.yahoo.com/rss?url=http%3A%2F%2Ffeeds.feedburner.com%2FBradWilson" src="http://us.i1.yimg.com/us.yimg.com/i/us/my/addtomyyahoo4.gif">Subscribe with My Yahoo!</feedburner:feedFlare><feedburner:feedFlare href="http://www.newsgator.com/ngs/subscriber/subext.aspx?url=http%3A%2F%2Ffeeds.feedburner.com%2FBradWilson" src="http://www.newsgator.com/images/ngsub1.gif">Subscribe with NewsGator</feedburner:feedFlare><feedburner:feedFlare href="http://feeds.my.aol.com/add.jsp?url=http%3A%2F%2Ffeeds.feedburner.com%2FBradWilson" src="http://o.aolcdn.com/favorites.my.aol.com/webmaster/ffclient/webroot/locale/en-US/images/myAOLButtonSmall.gif">Subscribe with My AOL</feedburner:feedFlare><feedburner:feedFlare href="http://www.bloglines.com/sub/http://feeds.feedburner.com/BradWilson" src="http://www.bloglines.com/images/sub_modern11.gif">Subscribe with Bloglines</feedburner:feedFlare><feedburner:feedFlare href="http://www.netvibes.com/subscribe.php?url=http%3A%2F%2Ffeeds.feedburner.com%2FBradWilson" src="http://www.netvibes.com/img/add2netvibes.gif">Subscribe with Netvibes</feedburner:feedFlare><feedburner:feedFlare href="http://fusion.google.com/add?feedurl=http%3A%2F%2Ffeeds.feedburner.com%2FBradWilson" src="http://buttons.googlesyndication.com/fusion/add.gif">Subscribe with Google</feedburner:feedFlare><feedburner:feedFlare href="http://www.pageflakes.com/subscribe.aspx?url=http%3A%2F%2Ffeeds.feedburner.com%2FBradWilson" src="http://www.pageflakes.com/ImageFile.ashx?instanceId=Static_4&amp;fileName=ATP_blu_91x17.gif">Subscribe with Pageflakes</feedburner:feedFlare><geo:lat>47.677471</geo:lat><geo:long>-122.121383</geo:long><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/BradWilson-ThenetGuy" type="application/rss+xml" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /></channel>

<item rdf:about="http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-5-master-page-templates.html">
<title>ASP.NET MVC 2 Templates, Part 5: Master Page Templates</title>
<link>http://feedproxy.google.com/~r/BradWilson-ThenetGuy/~3/vEh4GdOArhI/aspnet-mvc-2-templates-part-5-master-page-templates.html</link>
<description>Series Index Part 1: Introduction Part 2: ModelMetadata Part 3: Default Templates Part 4: Custom Object Templates Part 5: Master Page Templates Opinionated Input Builders During the last TechEd, Eric Hexter talked with David Fowler from the ASP.NET team about...</description>
<content:encoded><![CDATA[<h3><strong>Series Index</strong></h3>  <ul>   <li><a href="http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-1-introduction.html">Part 1: Introduction</a> </li>    <li><a href="http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-2-modelmetadata.html">Part 2: ModelMetadata</a> </li>    <li><a href="http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-3-default-templates.html">Part 3: Default Templates</a> </li>    <li><a href="http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-4-custom-object-templates.html">Part 4: Custom Object Templates</a> </li>    <li><em>Part 5: Master Page Templates</em> </li> </ul>  <h3><strong>Opinionated Input Builders</strong></h3>  <p>During the last TechEd, <a href="http://www.lostechies.com/blogs/hex">Eric Hexter</a> talked with <a href="http://weblogs.asp.net/davidfowler/">David Fowler</a> from the ASP.NET team about the previous examples we’d released showing Dynamic Data-like functionality for MVC applications. After that talk, Eric ran a multi-part blog post series titled <a href="http://www.lostechies.com/blogs/hex/archive/2009/06/09/opinionated-input-builders-for-asp-net-mvc-using-partials-part-i.aspx">Opinionated Input Builders</a> where he showed functionality that was similar to the Templates feature that we’d been working on for MVC 2.</p>  <p>One of my design goals when I did our Templates feature was to make sure we enabled the kinds of scenarios that Eric used in his example. The primary difference is that he relies on Master Pages to do the actual layout of the items. This means that you can always just call DisplayXxx or EditorXxx, and whether you have a simple or a complex object, you get the complete “chrome” included: labels, inputs, and validation messages.</p>  <p>This blog post shows how to use Eric’s technique with the MVC 2 Templates feature. For demonstration purposes, I'm going to use a table-style layout like he did (and like I showed in Part 4 of this series), but this could just as easily use a linear display like the default templates use.</p>  <h3><strong>The Master Pages</strong></h3>  <p>The first thing we need to define is the master pages that will be used by the templates. There is one each for Display and Editor templates. These master pages will be used by the individual item templates to display one item from the model.</p>  <p><strong><em>DisplayTemplates/Template.master</em></strong></p>  <pre class="brush:html">&lt;%@ Master Language=&quot;C#&quot; Inherits=&quot;System.Web.Mvc.ViewMasterPage&quot; %&gt;
&lt;script runat=&quot;server&quot;&gt;
    protected override void OnInit(EventArgs e) {
        base.OnInit(e);

        if (ViewData.ModelMetadata.HideSurroundingHtml) {
            TablePlaceholder.Visible = false;
        }
        else {
            Controls.Remove(Data);
            DataPlaceholder.Controls.Add(Data);
        }
    }
&lt;/script&gt;
&lt;asp:ContentPlaceHolder runat=&quot;server&quot; id=&quot;Data&quot; /&gt;
&lt;asp:PlaceHolder runat=&quot;server&quot; id=&quot;TablePlaceholder&quot;&gt;
    &lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; border=&quot;0&quot; width=&quot;100%&quot;&gt;
        &lt;tr&gt;
            &lt;td style=&quot;width: 10em;&quot;&gt;
                &lt;div class=&quot;display-label&quot; style=&quot;text-align: right;&quot;&gt;
                    &lt;asp:ContentPlaceHolder runat=&quot;server&quot; id=&quot;Label&quot;&gt;
                        &lt;%= ViewData.ModelMetadata.GetDisplayName() %&gt;
                    &lt;/asp:ContentPlaceHolder&gt;
                &lt;/div&gt;
            &lt;/td&gt;
            &lt;td&gt;
                &lt;div class=&quot;display-field&quot;&gt;
                    &lt;asp:PlaceHolder runat=&quot;server&quot; id=&quot;DataPlaceholder&quot; /&gt;
                &lt;/div&gt;
            &lt;/td&gt;
        &lt;/tr&gt;
    &lt;/table&gt;
&lt;/asp:PlaceHolder&gt;</pre>

<p>The core behavior of this master page is that it defines two content placeholders named “Label” and “Data”. The “Label” placeholder has default content which shows the display name of the property in question, which is usually the right answer for labels (but by making it a placeholder, then each individual template can make that decision for themselves).</p>

<p>This template uses a little WebForms magic during OnInit to rearrange the page depending on whether you’re interested in showing the surrounding HTML or not. If you want to hide the surrounding HTML, then we hide the table and leave the data placeholder outside where it gets displayed on it own; if you want to preserve the surrounding HTML, then we move the data placeholder into its proper place in the table.</p>

<p><strong><em>EditorTemplates/Template.master</em></strong></p>

<pre class="brush:html">&lt;%@ Master Language=&quot;C#&quot; Inherits=&quot;System.Web.Mvc.ViewMasterPage&quot; %&gt;
&lt;script runat=&quot;server&quot;&gt;
    protected override void OnInit(EventArgs e) {
        base.OnInit(e);

        if (ViewData.ModelMetadata.HideSurroundingHtml) {
            TablePlaceholder.Visible = false;
        }
        else {
            Controls.Remove(Data);
            DataPlaceholder.Controls.Add(Data);
        }
    }
&lt;/script&gt;
&lt;asp:ContentPlaceHolder runat=&quot;server&quot; id=&quot;Data&quot; /&gt;
&lt;asp:PlaceHolder runat=&quot;server&quot; id=&quot;TablePlaceholder&quot;&gt;
    &lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; border=&quot;0&quot; width=&quot;100%&quot;&gt;
        &lt;tr&gt;
            &lt;td style=&quot;width: 10em;&quot;&gt;
                &lt;asp:ContentPlaceHolder runat=&quot;server&quot; id=&quot;Label&quot;&gt;
                     &lt;div class=&quot;editor-label&quot; style=&quot;text-align: right;&quot;&gt;
                        &lt;%= ViewData.ModelMetadata.IsRequired ? &quot;*&quot; : &quot;&quot; %&gt;
                        &lt;%= Html.Label(&quot;&quot;) %&gt;
                    &lt;/div&gt;
                &lt;/asp:ContentPlaceHolder&gt;
            &lt;/td&gt;
            &lt;td&gt;
                &lt;div class=&quot;editor-field&quot;&gt;
                    &lt;asp:PlaceHolder runat=&quot;server&quot; id=&quot;DataPlaceholder&quot; /&gt;
                    &lt;asp:ContentPlaceHolder runat=&quot;server&quot; ID=&quot;Validation&quot;&gt;
                        &lt;%= Html.ValidationMessage(&quot;&quot;, &quot;*&quot;) %&gt;
                    &lt;/asp:ContentPlaceHolder&gt;
                &lt;/div&gt;
            &lt;/td&gt;
        &lt;/tr&gt;
    &lt;/table&gt;
&lt;/asp:PlaceHolder&gt;</pre>

<p>The editor version of this template is nearly identical, except that now we’ve introduced a third content placeholder named “Validation”, with default content that calls Html.ValidationMessage(). We’ve also added asterisks for required fields, just like we did with our previous tabular template.</p>

<h3><strong>The Simple Type Templates</strong></h3>

<p>The simple type templates will look nearly identical to the previous versions we’ve seen, except that they will be wrapped into &lt;asp:Content&gt; blocks and reference the master page. For demonstration purposes, I’ll show the Display and Editor templates for String, and leave the porting of the rest of the templates as an exercise for the reader.</p>

<p><strong><em>DisplayTemplates/String.aspx</em></strong></p>

<pre class="brush:html">&lt;%@ Page Language=&quot;C#&quot; MasterPageFile=&quot;Template.Master&quot; Inherits=&quot;System.Web.Mvc.ViewPage&quot; %&gt;
&lt;asp:Content ContentPlaceHolderID=&quot;Data&quot; runat=&quot;server&quot;&gt;
    &lt;%= Html.Encode(ViewData.TemplateInfo.FormattedModelValue) %&gt;
&lt;/asp:Content&gt;</pre>

<p><strong><em>EditorTemplates/String.aspx</em></strong></p>

<pre class="brush:html">&lt;%@ Page Language=&quot;C#&quot; MasterPageFile=&quot;Template.Master&quot; Inherits=&quot;System.Web.Mvc.ViewPage&quot; %&gt;
&lt;asp:Content ContentPlaceHolderID=&quot;Data&quot; runat=&quot;server&quot;&gt;
    &lt;%= Html.TextBox(&quot;&quot;, ViewData.TemplateInfo.FormattedModelValue,
                     new { @class = &quot;text-box single-line&quot; }) %&gt;
&lt;/asp:Content&gt;</pre>

<h3><strong>The Object Templates</strong></h3>

<p>When we examine the Object templates, we’ll see that they are significantly simpler than the older versions, because there is no actual HTML generation going on in here; that’s left to the master pages as appropriate. We’re just left with our shallow dive logic and the property loop.</p>

<p><strong><em>DisplayTemplates/Object.aspx</em></strong></p>

<pre class="brush:html">&lt;%@ Page Language=&quot;C#&quot; Inherits=&quot;System.Web.Mvc.ViewPage&quot; %&gt;
&lt;% if (ViewData.TemplateInfo.TemplateDepth &gt; 1) { %&gt;
    &lt;%= ViewData.ModelMetadata.SimpleDisplayText %&gt;
&lt;% } else { %&gt;
    &lt;% foreach (var prop in ViewData.ModelMetadata.Properties.Where(pm =&gt; pm.ShowForDisplay &amp;&amp; !ViewData.TemplateInfo.Visited(pm))) { %&gt;
        &lt;%= Html.Display(prop.PropertyName) %&gt;
    &lt;% } %&gt;
&lt;% } %&gt;</pre>

<p><strong><em>EditorTemplates/Object.aspx</em></strong></p>

<pre class="brush:html">&lt;%@ Page Language=&quot;C#&quot; Inherits=&quot;System.Web.Mvc.ViewPage&quot; %&gt;
&lt;% if (ViewData.TemplateInfo.TemplateDepth &gt; 1) { %&gt;
    &lt;%= ViewData.ModelMetadata.SimpleDisplayText %&gt;
&lt;% } else { %&gt;
    &lt;% foreach (var prop in ViewData.ModelMetadata.Properties.Where(pm =&gt; pm.ShowForEdit &amp;&amp; !ViewData.TemplateInfo.Visited(pm))) { %&gt;
        &lt;%= Html.Editor(prop.PropertyName) %&gt;
    &lt;% } %&gt;
&lt;% } %&gt;</pre>

<p>The only difference between the Editor and Display templates is the call to Html.Editor vs. Html.Display.</p>

<p>Also notice that these templates don’t use the master page. That’s because they’re not generating any UI of their own, and they rely on the individual items to use the master page to get their own surrounding UI.</p>

<h3><strong>Wrapping Up</strong></h3>

<p>After we apply all these changes, the resulting display is identical to the tabular display we had in the previous blog post, except that now we’ve centralized all the layout decisions into the master pages. This would allow us, for instance, to change layout at runtime just by dynamically changing the master page each template referenced; it’s also a nice separation of responsibilities because the layout is now separated from the shallow vs. deep dive and property iteration decisions.</p>

<p>I think this will probably be the last blog post in this series, unless there is some feedback about anything people would like covered that hasn’t been shown yet. I hope they’ve helped you understand the new Templates feature in ASP.NET MVC 2.</p>

<p>Happy Web Developing!</p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/BradWilson?a=Y6f8ZjVqHFA:SSox_vo8fps:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/BradWilson?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/BradWilson?a=Y6f8ZjVqHFA:SSox_vo8fps:dnMXMwOfBR0"><img src="http://feeds.feedburner.com/~ff/BradWilson?d=dnMXMwOfBR0" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/BradWilson?a=Y6f8ZjVqHFA:SSox_vo8fps:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/BradWilson?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/BradWilson?a=Y6f8ZjVqHFA:SSox_vo8fps:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/BradWilson?i=Y6f8ZjVqHFA:SSox_vo8fps:V_sGLiPBpWU" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/BradWilson/~4/Y6f8ZjVqHFA" height="1" width="1"/><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?a=vEh4GdOArhI:Y6f8ZjVqHFA:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?a=vEh4GdOArhI:Y6f8ZjVqHFA:dnMXMwOfBR0"><img src="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?d=dnMXMwOfBR0" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?a=vEh4GdOArhI:Y6f8ZjVqHFA:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?a=vEh4GdOArhI:Y6f8ZjVqHFA:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?i=vEh4GdOArhI:Y6f8ZjVqHFA:V_sGLiPBpWU" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/BradWilson-ThenetGuy/~4/vEh4GdOArhI" height="1" width="1"/>]]></content:encoded>


<dc:subject>ASP.NET</dc:subject>
<dc:subject>ASP.NET MVC</dc:subject>
<dc:subject>Technical</dc:subject>

<dc:creator>Brad Wilson</dc:creator>
<dc:date>2009-10-29T15:11:31-07:00</dc:date>
<feedburner:origLink>http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-5-master-page-templates.html</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/BradWilson/~3/Y6f8ZjVqHFA/aspnet-mvc-2-templates-part-5-master-page-templates.html</feedburner:origLink></item>
<item rdf:about="http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-4-custom-object-templates.html">
<title>ASP.NET MVC 2 Templates, Part 4: Custom Object Templates</title>
<link>http://feedproxy.google.com/~r/BradWilson-ThenetGuy/~3/_d38KumI7ZM/aspnet-mvc-2-templates-part-4-custom-object-templates.html</link>
<description>Series Index Part 1: Introduction Part 2: ModelMetadata Part 3: Default Templates Part 4: Custom Object Templates Part 5: Master Page Templates Customizing Templates In Part 3, we saw what the default templates would look like if we’d written them...</description>
<content:encoded><![CDATA[<h3><strong>Series Index</strong></h3>  <ul>   <li><a href="http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-1-introduction.html">Part 1: Introduction</a> </li>    <li><a href="http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-2-modelmetadata.html">Part 2: ModelMetadata</a> </li>    <li><a href="http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-3-default-templates.html">Part 3: Default Templates</a> </li>    <li><em>Part 4: Custom Object Templates</em></li>    <li><a href="http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-5-master-page-templates.html">Part 5: Master Page Templates</a>&#160;</li> </ul>  <h3><strong>Customizing Templates</strong></h3>  <p>In Part 3, we saw what the default templates would look like if we’d written them as .ascx files. In this blog post, we’ll discuss some of the customizations you can make to the Object templates to enable different features and different displays for your template-based UI.</p>  <p>For these examples, here are the models, controller, and views that we’ll be using.</p>  <p><strong><em>Models/SampleModel.cs</em></strong></p>  <pre class="brush:csharp">using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;

public class SampleModel {
    public static SampleModel Create() {
        return new SampleModel {
            Boolean = true,
            EmailAddress = &quot;admin@contoso.com&quot;,
            Decimal = 21.1234M,
            Integer = 42,
            Hidden = &quot;Uneditable&quot;,
            HiddenAndInvisible = &quot;Also uneditable&quot;,
            Html = &quot;This is &lt;b&gt;HTML&lt;/b&gt; enabled&quot;,
            MultilineText = &quot;This\r\nhas\r\nmultiple\r\nlines&quot;,
            NullableBoolean = null,
            Password = &quot;supersecret&quot;,
            String = &quot;A simple string&quot;,
            Url = &quot;http://www.microsoft.com/&quot;,
        };
    }

    public bool Boolean { get; set; }

    [DataType(DataType.EmailAddress)]
    public string EmailAddress { get; set; }

    public decimal Decimal { get; set; }

    [HiddenInput]
    public string Hidden { get; set; }

    [HiddenInput(DisplayValue = false)]
    public string HiddenAndInvisible { get; set; }

    [DataType(DataType.Html)]
    public string Html { get; set; }

    [Required]
    [Range(10, 100)]
    public int Integer { get; set; }

    [DataType(DataType.MultilineText)]
    public string MultilineText { get; set; }

    public bool? NullableBoolean { get; set; }

    [DataType(DataType.Password)]
    public string Password { get; set; }

    public string String { get; set; }

    [DataType(DataType.Url)]
    public string Url { get; set; }

    [DisplayFormat(NullDisplayText = &quot;(null value)&quot;)]
    public ChildModel ChildModel { get; set; }
}</pre>

<p><strong><em>Models/ChildModel.cs</em></strong></p>

<pre class="brush:csharp">using System.ComponentModel.DataAnnotations;

[DisplayColumn(&quot;FullName&quot;)]
public class ChildModel {
    [Required, StringLength(25)]
    public string FirstName { get; set; }

    [Required, StringLength(25)]
    public string LastName { get; set; }

    [ScaffoldColumn(false)]
    public string FullName {
        get {
            return FirstName + &quot; &quot; + LastName;
        }
    }
}</pre>

<p><strong><em>Controllers/HomeController.cs</em></strong></p>

<pre class="brush:csharp">using System.Web.Mvc;

public class HomeController : Controller {
    static SampleModel model = SampleModel.Create();

    public ViewResult Index() {
        return View(model);
    }

    public ViewResult Edit() {
        return View(model);
    }

    [HttpPost]
    [ValidateInput(false)]
    public ActionResult Edit(SampleModel editedModel) {
        if (ModelState.IsValid) {
            model = editedModel;
            return RedirectToAction(&quot;Details&quot;);
        }

        return View(editedModel);
    }
}</pre>

<p><strong><em>Views/Home/Index.aspx</em></strong></p>

<pre class="brush:html">&lt;%@ Page 
    Language=&quot;C#&quot;
    MasterPageFile=&quot;~/Views/shared/Site.master&quot;
    Inherits=&quot;ViewPage&lt;SampleModel&gt;&quot; %&gt;

&lt;asp:Content ContentPlaceHolderID=&quot;MainContent&quot; runat=&quot;server&quot;&gt;
    &lt;h3&gt;Details&lt;/h3&gt;
    &lt;fieldset style=&quot;padding: 1em; margin: 0; border: solid 1px #999;&quot;&gt;
        &lt;%= Html.DisplayForModel() %&gt;
    &lt;/fieldset&gt;
    &lt;p&gt;&lt;%= Html.ActionLink(&quot;Edit&quot;, &quot;Edit&quot;) %&gt;&lt;/p&gt;
&lt;/asp:Content&gt;</pre>

<p><strong><em>Views/Home/Edit.aspx</em></strong></p>

<pre class="brush:html">&lt;%@ Page 
    Language=&quot;C#&quot;
    MasterPageFile=&quot;~/Views/shared/Site.master&quot;
    Inherits=&quot;ViewPage&lt;SampleModel&gt;&quot; %&gt;

&lt;asp:Content ID=&quot;Content2&quot; ContentPlaceHolderID=&quot;MainContent&quot; runat=&quot;server&quot;&gt;
    &lt;h3&gt;Edit&lt;/h3&gt;
    &lt;% using (Html.BeginForm()) { %&gt;
        &lt;fieldset style=&quot;padding: 1em; margin: 0; border: solid 1px #999;&quot;&gt;
            &lt;%= Html.ValidationSummary(&quot;Broken stuff:&quot;) %&gt;
            &lt;%= Html.EditorForModel() %&gt;
            &lt;input type=&quot;submit&quot; value=&quot;  Submit  &quot; /&gt;
        &lt;/fieldset&gt;
    &lt;% } %&gt;
    &lt;p&gt;&lt;%= Html.ActionLink(&quot;Details&quot;, &quot;Index&quot;) %&gt;&lt;/p&gt;
&lt;/asp:Content&gt;</pre>

<h3></h3>

<h3><strong>The Default Display</strong></h3>

<p>When we show this home controller without any customizations, this is what the details page looks like:</p>

<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Default Display" border="0" alt="Default Display" src="http://bradwilson.typepad.com/.a/6a00e54fbd8c4988340120a6362bb5970b-pi" width="489" height="663" /> </p>

<p>And this is our edit page:</p>

<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Default Editor" border="0" alt="Default Editor" src="http://bradwilson.typepad.com/.a/6a00e54fbd8c4988340120a68c7893970c-pi" width="491" height="824" /> </p>

<p></p>

<h3><strong>Tabular Layout</strong></h3>

<p>One of the more commonly requested layouts is to do a tabular layout inside of the linear name/value, name/value layout that we do by default. Notice that the editor version of this layout also adds asterisks to the label for required fields.</p>

<p><strong><em>Views/Shared/DisplayTemplates/Object.ascx</em></strong></p>

<pre class="brush:html">&lt;%@ Control Language=&quot;C#&quot; Inherits=&quot;System.Web.Mvc.ViewUserControl&quot; %&gt;
&lt;% if (Model == null) { %&gt;
    &lt;%= ViewData.ModelMetadata.NullDisplayText %&gt;
&lt;% } else if (ViewData.TemplateInfo.TemplateDepth &gt; 1) { %&gt;
    &lt;%= ViewData.ModelMetadata.SimpleDisplayText %&gt;
&lt;% } else { %&gt;
    &lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; border=&quot;0&quot;&gt;
    &lt;% foreach (var prop in ViewData.ModelMetadata.Properties.Where(pm =&gt; pm.ShowForDisplay &amp;&amp; !ViewData.TemplateInfo.Visited(pm))) { %&gt;
        &lt;% if (prop.HideSurroundingHtml) { %&gt;
            &lt;%= Html.Display(prop.PropertyName) %&gt;
        &lt;% } else { %&gt;
            &lt;tr&gt;
                &lt;td&gt;
                    &lt;div class=&quot;display-label&quot; style=&quot;text-align: right;&quot;&gt;
                        &lt;%= prop.GetDisplayName() %&gt;
                    &lt;/div&gt;
                &lt;/td&gt;
                &lt;td&gt;
                    &lt;div class=&quot;display-field&quot;&gt;
                        &lt;%= Html.Display(prop.PropertyName) %&gt;
                    &lt;/div&gt;
                &lt;/td&gt;
            &lt;/tr&gt;
        &lt;% } %&gt;
    &lt;% } %&gt;
    &lt;/table&gt;
&lt;% } %&gt;</pre>

<p>Which creates this layout:</p>

<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Tabular Display" border="0" alt="Tabular Display" src="http://bradwilson.typepad.com/.a/6a00e54fbd8c4988340120a68c7898970c-pi" width="385" height="562" /> </p>

<p><strong><em>Views/Shared/EditorTemplates/Object.ascx</em></strong></p>

<pre class="brush:html">&lt;%@ Control Language=&quot;C#&quot; Inherits=&quot;System.Web.Mvc.ViewUserControl&quot; %&gt;
&lt;% if (ViewData.TemplateInfo.TemplateDepth &gt; 1) { %&gt;
    &lt;%= ViewData.ModelMetadata.SimpleDisplayText %&gt;
&lt;% } else { %&gt;
    &lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; border=&quot;0&quot;&gt;
    &lt;% foreach (var prop in ViewData.ModelMetadata.Properties.Where(pm =&gt; pm.ShowForEdit &amp;&amp; !ViewData.TemplateInfo.Visited(pm))) { %&gt;
        &lt;% if (prop.HideSurroundingHtml) { %&gt;
            &lt;%= Html.Editor(prop.PropertyName) %&gt;
        &lt;% } else { %&gt;
            &lt;tr&gt;
                &lt;td&gt;
                    &lt;div class=&quot;editor-label&quot; style=&quot;text-align: right;&quot;&gt;
                        &lt;%= prop.IsRequired ? &quot;*&quot; : &quot;&quot; %&gt;
                        &lt;%= Html.Label(prop.PropertyName) %&gt;
                    &lt;/div&gt;
                &lt;/td&gt;
                &lt;td&gt;
                    &lt;div class=&quot;editor-field&quot;&gt;
                        &lt;%= Html.Editor(prop.PropertyName) %&gt;
                        &lt;%= Html.ValidationMessage(prop.PropertyName, &quot;*&quot;) %&gt;
                    &lt;/div&gt;
                &lt;/td&gt;
            &lt;/tr&gt;
        &lt;% } %&gt;
    &lt;% } %&gt;
    &lt;/table&gt;
&lt;% } %&gt;</pre>

<p>Which creates this layout:</p>

<p></p>

<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Tabular Editor" border="0" alt="Tabular Editor" src="http://bradwilson.typepad.com/.a/6a00e54fbd8c4988340120a6362bc0970b-pi" width="623" height="726" /> </p>

<h3><strong>Shallow Dive vs. Deep Dive</strong></h3>

<p>In the screenshots above, ChildModel is showing as “(null value)”. ChildModel is itself a complex model, so it follows the rules for shallow dive vs. deep dive. Before we have a child model object, it’s showing the NullDisplayText as we set in the attribute in the model above.</p>

<p>Notice that even in edit mode above, we can’t edit the child model. That’s because the shallow dive logic prevents us from presenting a recursive editing UI.</p>

<p>If we change the Editor template above and remove the first “if” statement (which is what prevents the deep dive), then the editor will now show us editing fields for the child model:</p>

<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Tabular Editor with Deep Dive enabled" border="0" alt="Tabular Editor with Deep Dive enabled" src="http://bradwilson.typepad.com/.a/6a00e54fbd8c4988340120a68c789d970c-pi" width="670" height="153" /> </p>

<p>And now our display shows:</p>

<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Tabular Display with child model (shallow dive)" border="0" alt="Tabular Display with child model (shallow dive)" src="http://bradwilson.typepad.com/.a/6a00e54fbd8c4988340120a68c78a3970c-pi" width="390" height="92" /> </p>

<p>Since we haven’t changed our Object Display template, we still get a shallow dive on this object. Further, it’s showing us the full name because we’ve used the DataAnnotations [DisplayColumn] attribute to say “display this property when showing this complex object in shallow form”. We’ve pointed [DisplayColumn] to a synthesized property called FullName, which we don’t normally show because we’ve annotated it with [ScaffoldColumn(false)].</p>

<p>If we change the Object Display template to do a deep dive, then we would see this:</p>

<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Tabular Display with Deep Dive" border="0" alt="Tabular Display with Deep Dive" src="http://bradwilson.typepad.com/.a/6a00e54fbd8c4988340120a6362bc7970b-pi" width="387" height="140" /> </p>

<h3><strong>Wrapping Up</strong></h3>

<p>In this blog post, I’ve shown you some of the ways you can customize the Object template to get different displays for your templates. That includes a tabular display instead of a linear display, adding asterisks to field names when fields are required, as well as enabling Deep Dive scenarios for complex objects inside of complex objects. In the next blog post, I’ll examine changing all the templates to enable an entirely different layout system centered around Master pages, inspired by Eric Hexter’s <a href="http://www.lostechies.com/blogs/hex/archive/2009/06/09/opinionated-input-builders-for-asp-net-mvc-using-partials-part-i.aspx">Opinionated Input Builders</a> blog post series.</p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/BradWilson?a=r58jGsrWSL0:eOU3j8gXOcc:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/BradWilson?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/BradWilson?a=r58jGsrWSL0:eOU3j8gXOcc:dnMXMwOfBR0"><img src="http://feeds.feedburner.com/~ff/BradWilson?d=dnMXMwOfBR0" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/BradWilson?a=r58jGsrWSL0:eOU3j8gXOcc:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/BradWilson?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/BradWilson?a=r58jGsrWSL0:eOU3j8gXOcc:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/BradWilson?i=r58jGsrWSL0:eOU3j8gXOcc:V_sGLiPBpWU" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/BradWilson/~4/r58jGsrWSL0" height="1" width="1"/><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?a=_d38KumI7ZM:r58jGsrWSL0:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?a=_d38KumI7ZM:r58jGsrWSL0:dnMXMwOfBR0"><img src="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?d=dnMXMwOfBR0" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?a=_d38KumI7ZM:r58jGsrWSL0:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?a=_d38KumI7ZM:r58jGsrWSL0:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?i=_d38KumI7ZM:r58jGsrWSL0:V_sGLiPBpWU" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/BradWilson-ThenetGuy/~4/_d38KumI7ZM" height="1" width="1"/>]]></content:encoded>


<dc:subject>ASP.NET</dc:subject>
<dc:subject>ASP.NET MVC</dc:subject>
<dc:subject>Technical</dc:subject>

<dc:creator>Brad Wilson</dc:creator>
<dc:date>2009-10-29T12:47:07-07:00</dc:date>
<feedburner:origLink>http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-4-custom-object-templates.html</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/BradWilson/~3/r58jGsrWSL0/aspnet-mvc-2-templates-part-4-custom-object-templates.html</feedburner:origLink></item>
<item rdf:about="http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-3-default-templates.html">
<title>ASP.NET MVC 2 Templates, Part 3: Default Templates</title>
<link>http://feedproxy.google.com/~r/BradWilson-ThenetGuy/~3/CFTyLbOSfIw/aspnet-mvc-2-templates-part-3-default-templates.html</link>
<description>Series Index Part 1: Introduction Part 2: ModelMetadata Part 3: Default Templates Part 4: Custom Object Templates Part 5: Master Page Templates Template Resolution Before we talk about the built-in templates, we need to spend a few minutes understanding how...</description>
<content:encoded><![CDATA[<h3><strong>Series Index</strong></h3>  <ul>   <li><a href="http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-1-introduction.html">Part 1: Introduction</a> </li>    <li><a href="http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-2-modelmetadata.html">Part 2: ModelMetadata</a> </li>    <li><em>Part 3: Default Templates</em> </li>    <li><a href="http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-4-custom-object-templates.html">Part 4: Custom Object Templates</a></li>    <li><a href="http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-5-master-page-templates.html">Part 5: Master Page Templates</a>&#160; </li> </ul>  <h3><strong>Template Resolution</strong></h3>  <p>Before we talk about the built-in templates, we need to spend a few minutes understanding how template resolution works, so you’ll know how to override the template properly.</p>  <p><strong>Paths</strong></p>  <p>When a template is resolved, the system iterates over several names, looking for a template which matches. For each of the names, it asks the view engines to find a partial view named “DisplayTemplates/<em>TemplateName</em>” or “EditorTemplates/<em>TemplateName</em>”, depending on whether you’ve asked for a display or editor template.</p>  <p>If you’re using the WebForms view engine, that means it searches for display templates in the following locations:</p>  <ul>   <li>~/Areas/<em>AreaName</em>/Views/<em>ControllerName</em>/DisplayTemplates/<em>TemplateName</em>.aspx &amp; .ascx </li>    <li>~/Areas/<em>AreaName</em>/Views/Shared/DisplayTemplates/<em>TemplateName</em>.aspx &amp; .ascx </li>    <li>~/Views/<em>ControllerName</em>/DisplayTemplates/<em>TemplateName</em>.aspx &amp; .ascx </li>    <li>~/Views/Shared/DisplayTemplates/<em>TemplateName</em>.aspx &amp; .ascx </li> </ul>  <p>(Replace DisplayTemplates with EditorTemplates for the search paths for editor templates.)</p>  <p><strong>Template Names</strong></p>  <p>The following template names are tried in order:</p>  <ul>   <li>TemplateHint from ModelMetadata </li>    <li>DataTypeName from ModelMetadata </li>    <li>The name of the type <em>(see notes below)</em> </li>    <li>If the object is not complex: “String” </li>    <li>If the object is complex and an interface: “Object” </li>    <li>If the object is complex and not an interface: Recurse through the inheritance hiearchy for the type, trying every type name </li> </ul>  <p>When searching for the type name, the simple name is used (i.e., Type.Name) without namespace. Also, if the type is Nullable&lt;T&gt;, we search for T (so you’ll get the Boolean template whether you’re using “bool” or “Nullable&lt;bool&gt;”). This means if you’re writing templates for value types, you will need to account for whether the value is nullable or not. You can use the IsNullableValueType property of ModelMetadata to determine if the value is nullable. We’ll see an example of this below with the built-in Boolean template.</p>  <h3><strong>The TemplateInfo Class</strong></h3>  <p>One last thing we need to talk about before diving into the template implementations is the TemplateInfo class. The TemplateInfo is available off of ViewData, and unlike model metadata, is only populated when you’re inside of a template.</p>  <p>The primary property you will be using from TemplateInfo is FormattedModelValue. The value of this field is either the properly formatted model value as a string (based on the format strings on ModelMetadata), or the original raw model value (if there is no format string specified).</p>  <p>There are a couple other things we also use (TemplateDepth property and Visited method), which will be explained when we encounter them.</p>  <h3><strong>Built-In Display Templates</strong></h3>  <p>The system has built-in support for 9 display template names: “Boolean”, “Decimal”, “EmailAddress”, “HiddenInput”, “Html”, “Object”, “String”, “Text”, and “Url”. Two of these (“Text” and “String”) have the same implementation. Some of these have counterparts in the editor templates, and some do not.</p>  <p>The default templates in ASP.NET MVC are done in code, but here I’ve replaced their functionality as .ascx files, to illustrate what they do (and give you a starting point for customizing your own versions of all these templates).</p>  <p><strong>DisplayTemplates/String.ascx</strong></p>  <pre class="brush:html">&lt;%@ Control Language=&quot;C#&quot; Inherits=&quot;System.Web.Mvc.ViewUserControl&quot; %&gt;
&lt;%= Html.Encode(ViewData.TemplateInfo.FormattedModelValue) %&gt;</pre>

<p>There’s nothing really surprising here: we just encode and display the model.</p>

<p><strong>DisplayTemplates/Html.ascx</strong></p>

<pre class="brush:html">&lt;%@ Control Language=&quot;C#&quot; Inherits=&quot;System.Web.Mvc.ViewUserControl&quot; %&gt;
&lt;%= ViewData.TemplateInfo.FormattedModelValue %&gt;</pre>

<p>This is even a little simpler yet, since the “Html” type tells us that the content is HTML and therefore should not be encoded. <em>Be careful when marking your data as “Html” if it comes from end-users, since it opens up the possibility for cross-site scripting (XSS) attacks!</em></p>

<p><strong>DisplayTemplates/EmailAddress.ascx</strong></p>

<pre class="brush:html">&lt;%@ Control Language=&quot;C#&quot; Inherits=&quot;System.Web.Mvc.ViewUserControl&quot; %&gt;
&lt;a href=&quot;mailto:&lt;%= Html.AttributeEncode(Model) %&gt;&quot;&gt;&lt;%= Html.Encode(ViewData.TemplateInfo.FormattedModelValue) %&gt;&lt;/a&gt;</pre>

<p>This template assumes your model is an e-mail address, and uses it automatically create a mailto: link for it. Note how it uses Model for the e-mail address itself, but FormattedModelValue for the display; that lets you place format strings for display purposes, while still preserving the unedited e-mail address. This pattern is fairly common when the data is both mechanically meaningful (as in the e-mail address) but also displayed.</p>

<p><strong>DisplayTemplates/Url.ascx</strong></p>

<pre class="brush:html">&lt;%@ Control Language=&quot;C#&quot; Inherits=&quot;System.Web.Mvc.ViewUserControl&quot; %&gt;
&lt;a href=&quot;&lt;%= Html.AttributeEncode(Model) %&gt;&quot;&gt;&lt;%= Html.Encode(ViewData.TemplateInfo.FormattedModelValue) %&gt;&lt;/a&gt;</pre>

<p>As with EmailAddress above, this will interpret your model as a URL and automatically create a link to it.</p>

<p><strong>DisplayTemplates/HiddenInput.ascx</strong></p>

<pre class="brush:html">&lt;%@ Control Language=&quot;C#&quot; Inherits=&quot;System.Web.Mvc.ViewUserControl&quot; %&gt;
&lt;% if (!ViewData.ModelMetadata.HideSurroundingHtml) { %&gt;
    &lt;%= Html.Encode(ViewData.TemplateInfo.FormattedModelValue) %&gt;
&lt;% } %&gt;</pre>

<p>This template is intended to be used with the [HiddenInput] attribute (described in <a href="http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-2-modelmetadata.html">Part 2</a> of this series). It will generate a display value only if the user explicitly asked for one, by consulting HideSurroundingHtml.</p>

<p><strong>DisplayTemplates/Decimal.ascx</strong></p>

<pre class="brush:html">&lt;%@ Control Language=&quot;C#&quot; Inherits=&quot;System.Web.Mvc.ViewUserControl&quot; %&gt;
&lt;script runat=&quot;server&quot;&gt;
    private object FormattedValue {
        get {
            if (ViewData.TemplateInfo.FormattedModelValue == ViewData.ModelMetadata.Model) {
                return String.Format(System.Globalization.CultureInfo.CurrentCulture,
                                     &quot;{0:0.00}&quot;,
                                     ViewData.ModelMetadata.Model);
            }
            return ViewData.TemplateInfo.FormattedModelValue;
        }
    }
&lt;/script&gt;
&lt;%= Html.Encode(FormattedValue) %&gt;</pre>

<p>This template displays decimal values with 2 digits of precision by default, since most users will use decimal values to represent currency. Note that it only does this if you haven’t applied a format string (which is the purpose of the check in the if statement).</p>

<p><strong>DisplayTemplates/Boolean.ascx</strong></p>

<pre class="brush:html">&lt;%@ Control Language=&quot;C#&quot; Inherits=&quot;System.Web.Mvc.ViewUserControl&quot; %&gt;
&lt;script runat=&quot;server&quot;&gt;
    private bool? ModelValue {
        get {
            bool? value = null;
            if (ViewData.Model != null) {
                value = Convert.ToBoolean(ViewData.Model, System.Globalization.CultureInfo.InvariantCulture);
            }
            return value;
        }
    }
&lt;/script&gt;
&lt;% if (ViewData.ModelMetadata.IsNullableValueType) { %&gt;
    &lt;select class=&quot;list-box tri-state&quot; disabled=&quot;disabled&quot;&gt;
        &lt;option value=&quot;&quot; &lt;%= ModelValue.HasValue ? &quot;&quot; : &quot;selected='selected'&quot; %&gt;&gt;Not Set&lt;/option&gt;
        &lt;option value=&quot;true&quot; &lt;%= ModelValue.HasValue &amp;&amp; ModelValue.Value ? &quot;selected='selected'&quot; : &quot;&quot; %&gt;&gt;True&lt;/option&gt;
        &lt;option value=&quot;false&quot; &lt;%= ModelValue.HasValue &amp;&amp; !ModelValue.Value ? &quot;selected='selected'&quot; : &quot;&quot; %&gt;&gt;False&lt;/option&gt;
    &lt;/select&gt;
&lt;% } else { %&gt;
    &lt;input class=&quot;check-box&quot; disabled=&quot;disabled&quot; type=&quot;checkbox&quot; &lt;%= ModelValue.Value ? &quot;checked='checked'&quot; : &quot;&quot; %&gt; /&gt;
&lt;% } %&gt;</pre>

<p>The Boolean template is an interesting one, because it needs to generate UI that is different for non-nullable booleans vs. nullable booleans. It determines whether or not the model is supposed to be nullable based on IsNullableValueType from ModelMetadata.</p>

<p>The display UI for a non-nullable boolean is a disabled checkbox which is checked or not, depending on the value of the model. The display UI for nullable boolean is a disabled drop-down list with three potential values: “Not Set”, “True”, and &quot;False”.</p>

<p><strong>DisplayTemplates/Object.ascx</strong></p>

<p>It’s worth explaining the logic for this before we look at the code, because the complex object template does a lot of work on your behalf.</p>

<p>The Object template’s primary responsibility is displaying all the properties of a complex object, along with labels for each property. However, it’s also responsible for showing the value of the model’s NullDisplayText if it’s null, and it’s also responsible for ensuring that you only show only level of properties (also known as a “shallow dive” of an object). In the next blog post, we’ll talk about ways to customize this template, including performing “deep dive” operations.</p>

<pre class="brush:html">&lt;%@ Control Language=&quot;C#&quot; Inherits=&quot;System.Web.Mvc.ViewUserControl&quot; %&gt;
&lt;% if (Model == null) { %&gt;
    &lt;%= ViewData.ModelMetadata.NullDisplayText %&gt;
&lt;% }
   else if (ViewData.TemplateInfo.TemplateDepth &gt; 1) { %&gt;
    &lt;%= ViewData.ModelMetadata.SimpleDisplayText %&gt;
&lt;% }
   else { %&gt;
    &lt;% foreach (var prop in ViewData.ModelMetadata.Properties.Where(pm =&gt; pm.ShowForDisplay
                         &amp;&amp; !ViewData.TemplateInfo.Visited(pm))) { %&gt;
        &lt;% if (prop.HideSurroundingHtml) { %&gt;
            &lt;%= Html.Display(prop.PropertyName) %&gt;
        &lt;% }
           else { %&gt;
            &lt;% if (!String.IsNullOrEmpty(prop.GetDisplayName())) { %&gt;
                &lt;div class=&quot;display-label&quot;&gt;&lt;%= prop.GetDisplayName() %&gt;&lt;/div&gt;
            &lt;% } %&gt;
            &lt;div class=&quot;display-field&quot;&gt;&lt;%= Html.Display(prop.PropertyName) %&gt;&lt;/div&gt;
        &lt;% } %&gt;
    &lt;% } %&gt;
&lt;% } %&gt;</pre>

<p>Let’s take a look at the source here, line by line, to understand which bit is doing what.</p>

<pre class="brush:html">&lt;% if (Model == null) { %&gt;
    &lt;%= ViewData.ModelMetadata.NullDisplayText %&gt;
&lt;% }</pre>

<p>This says we only want to print the model’s NullDisplayText if the model is null.</p>

<pre class="brush:html">   else if (ViewData.TemplateInfo.TemplateDepth &gt; 1) { %&gt;
    &lt;%= ViewData.ModelMetadata.SimpleDisplayText %&gt;
&lt;% }</pre>

<p>This limits us to a single level of complex object (&quot;shallow dive&quot;). The TemplateInfo class tracks the depth of templates that you've shown automatically, and the TemplateDepth for the top level template will be 1.</p>

<pre class="brush:html">   else { %&gt;
    &lt;% foreach (var prop in ViewData.ModelMetadata.Properties.Where(pm =&gt; pm.ShowForDisplay
                         &amp;&amp; !ViewData.TemplateInfo.Visited(pm)))</pre>

<p>This is the main loop when we're showing the objects properties. We filter the property list to remove anything where the user has said &quot;do not display this&quot;. The other filter asks TemplateInfo if we've already rendered this object before; this helps us prevent infinite recursion when doing &quot;deep dive&quot; templates that might come from objects with circular references (like a parent/child relationship where both objects have pointers to one another).</p>

<pre class="brush:html">        &lt;% if (prop.HideSurroundingHtml) { %&gt;
            &lt;%= Html.Display(prop.PropertyName) %&gt;
        &lt;% }</pre>

<p>If the user has asked to hide the surrounding HTML, then all we want to do is display the property by itself. We don't want any of the &quot;extra&quot; stuff around it, like labels.</p>

<pre class="brush:html">            &lt;% if (!String.IsNullOrEmpty(prop.GetDisplayName())) { %&gt;
                &lt;div class=&quot;display-label&quot;&gt;&lt;%= prop.GetDisplayName() %&gt;&lt;/div&gt;
            &lt;% } %&gt;
            &lt;div class=&quot;display-field&quot;&gt;&lt;%= Html.Display(prop.PropertyName) %&gt;&lt;/div&gt;</pre>

<p>This will show the display name of the property, surrounded by a div tag, if the display name is not null or empty. Since the display name is not empty by default (it will be the name of the property), that means the user must request for the display name to be hidden by explicitly setting it empty (using [DisplayName] if you're using the default DataAnnotations metadata provider).</p>

<h3><strong>Built-In Editor Templates</strong></h3>

<p>The editor templates will be slightly more complicated than the display templates, since they include the ability to edit the values. They are built upon the existing HTML helpers. There are 7 built-in editor templates: “Boolean”, “Decimal”, “HiddenInput”, “MultilineText”, “Object”, “Password”, and “String”.</p>

<p>One thing you’re going to see that’s unusual here is that we will often by passing empty string as the name to the HTML helpers. Normally this isn’t legal, but in the case of templates, we keep a “context” which tracks where we are in the name of things. This is helpful with complex objects inside of complex objects, because we want our names to indicate where we are in the hierarchy of things (f.e., “Contact.HomeAddress.City” vs. “Contact.WorkAddress.City”).</p>

<p>When you pass a name to the HTML helpers, you’re saying things like “give me a textbox to edit the property of this object named ‘City’.” But what happens when your template isn’t for the address (complex object), but instead for the city (a simple string)? Passing an empty string to the HTML helper says “give me a textbox to edit myself.”</p>

<p><strong>EditorTemplates/String.ascx</strong></p>

<pre class="brush:html">&lt;%@ Control Language=&quot;C#&quot; Inherits=&quot;System.Web.Mvc.ViewUserControl&quot; %&gt;
&lt;%= Html.TextBox(&quot;&quot;, ViewData.TemplateInfo.FormattedModelValue,
                 new { @class = &quot;text-box single-line&quot; }) %&gt;</pre>

<p>Again we start with String, because it’s the simplest template to understand. This tells the system we want a text box (to edit myself), and we want it populated initially with the value of the formatted model value. In addition, we want to attach two CSS classes to the text box, “text-box” and “single-line”. With many of the CSS classes that we use here, you will find that we have provided default styles in MVC 2 that make them look slightly better out of the box.</p>

<p><strong>EditorTemplates/Password.ascx</strong></p>

<pre class="brush:html">&lt;%@ Control Language=&quot;C#&quot; Inherits=&quot;System.Web.Mvc.ViewUserControl&quot; %&gt;
&lt;%= Html.Password(&quot;&quot;, ViewData.TemplateInfo.FormattedModelValue,
                  new { @class = &quot;text-box single-line password&quot; }) %&gt;</pre>

<p>The Password template is similar to String, except that it calls Html.Password and it adds a third CSS class (&quot;password&quot;) to the rendered control.</p>

<p><strong>EditorTemplates/MultilineText.ascx</strong></p>

<pre class="brush:html">&lt;%@ Control Language=&quot;C#&quot; Inherits=&quot;System.Web.Mvc.ViewUserControl&quot; %&gt;
&lt;%= Html.TextArea(&quot;&quot;, ViewData.TemplateInfo.FormattedModelValue.ToString(),
                  0, 0, new { @class = &quot;text-box multi-line&quot; }) %&gt;</pre>

<p>Again, no big surprises here. We call TextArea, and we pass row and column size as 0 (since we style the text area with CSS), and use the CSS class &quot;multi-line&quot; instead of &quot;single-line&quot;.</p>

<p><strong>EditorTemplates/HiddenInput.ascx</strong></p>

<pre class="brush:html">&lt;%@ Control Language=&quot;C#&quot; Inherits=&quot;System.Web.Mvc.ViewUserControl&quot; %&gt;
&lt;script runat=&quot;server&quot;&gt;
    private object ModelValue {
        get {
            if (Model is System.Data.Linq.Binary) {
                return Convert.ToBase64String(((System.Data.Linq.Binary)Model).ToArray());
            }
            if (Model is byte[]) {
                return Convert.ToBase64String((byte[])Model);
            }
            return Model;
        }
    }
&lt;/script&gt;
&lt;% if (!ViewData.ModelMetadata.HideSurroundingHtml) { %&gt;
    &lt;%= Html.Encode(ViewData.TemplateInfo.FormattedModelValue) %&gt;
&lt;% } %&gt;
&lt;%= Html.Hidden(&quot;&quot;, ModelValue) %&gt;</pre>

<p>This is a lot more complex than the display version, because it has to do a lot more. The ModelValue property determines if the model is a LINQ to SQL Binary object or a byte array, and converts the value into a Base64 encoded value if so; otherwise, the raw model value is placed into the hidden input.</p>

<p>In addition to rendering the hidden input, it also needs to know if it should generate a display of the value.</p>

<p><strong>EditorTemplates/Decimal.ascx</strong></p>

<pre class="brush:html">&lt;%@ Control Language=&quot;C#&quot; Inherits=&quot;System.Web.Mvc.ViewUserControl&quot; %&gt;
&lt;script runat=&quot;server&quot;&gt;
    private object ModelValue {
        get {
            if (ViewData.TemplateInfo.FormattedModelValue == ViewData.ModelMetadata.Model) {
                return String.Format(System.Globalization.CultureInfo.CurrentCulture,
                                     &quot;{0:0.00}&quot;, ViewData.ModelMetadata.Model);
            }
            return ViewData.TemplateInfo.FormattedModelValue;
        }
    }
&lt;/script&gt;
&lt;%= Html.TextBox(&quot;&quot;, ModelValue, new { @class = &quot;text-box single-line&quot; }) %&gt;</pre>

<p>The Decimal editor template is nearly identical to the display template version, except that it ends up generating a text box for editing the value.</p>

<p><strong>EditorTemplates/Boolean.ascx</strong></p>

<pre class="brush:html">&lt;%@ Control Language=&quot;C#&quot; Inherits=&quot;System.Web.Mvc.ViewUserControl&quot; %&gt;
&lt;script runat=&quot;server&quot;&gt;
    private List&lt;SelectListItem&gt; TriStateValues {
        get {
            return new List&lt;SelectListItem&gt; {
                new SelectListItem { Text = &quot;Not Set&quot;,
                                     Value = String.Empty,
                                     Selected = !Value.HasValue },
                new SelectListItem { Text = &quot;True&quot;,
                                     Value = &quot;true&quot;,
                                     Selected = Value.HasValue &amp;&amp; Value.Value },
                new SelectListItem { Text = &quot;False&quot;,
                                     Value = &quot;false&quot;,
                                     Selected = Value.HasValue &amp;&amp; !Value.Value },
            };
        }
    }
    private bool? Value {
        get {
            bool? value = null;
            if (ViewData.Model != null) {
                value = Convert.ToBoolean(ViewData.Model,
                                          System.Globalization.CultureInfo.InvariantCulture);
            }
            return value;
        }
    }
&lt;/script&gt;
&lt;% if (ViewData.ModelMetadata.IsNullableValueType) { %&gt;
    &lt;%= Html.DropDownList(&quot;&quot;, TriStateValues, new { @class = &quot;list-box tri-state&quot; })%&gt;
&lt;% } else { %&gt;
    &lt;%= Html.CheckBox(&quot;&quot;, Value ?? false, new { @class = &quot;check-box&quot; })%&gt;
&lt;% } %&gt;</pre>

<p>The Boolean editor template is similar to the display template, except that it uses the built-in HTML helpers for DropDownList and CheckBox.</p>

<p><strong>EditorTemplates/Object.ascx</strong></p>

<pre class="brush:html">&lt;%@ Control Language=&quot;C#&quot; Inherits=&quot;System.Web.Mvc.ViewUserControl&quot; %&gt;
&lt;% if (ViewData.TemplateInfo.TemplateDepth &gt; 1) { %&gt;
    &lt;%= ViewData.ModelMetadata.SimpleDisplayText%&gt;
&lt;% }
   else { %&gt;    
    &lt;% foreach (var prop in ViewData.ModelMetadata.Properties.Where(pm =&gt; pm.ShowForEdit
                         &amp;&amp; !ViewData.TemplateInfo.Visited(pm))) { %&gt;
        &lt;% if (prop.HideSurroundingHtml) { %&gt;
            &lt;%= Html.Editor(prop.PropertyName) %&gt;
        &lt;% }
           else { %&gt;
            &lt;% if (!String.IsNullOrEmpty(Html.Label(prop.PropertyName).ToHtmlString())) { %&gt;
                &lt;div class=&quot;editor-label&quot;&gt;&lt;%= Html.Label(prop.PropertyName) %&gt;&lt;/div&gt;
            &lt;% } %&gt;
            &lt;div class=&quot;editor-field&quot;&gt;
                &lt;%= Html.Editor(prop.PropertyName) %&gt;
                &lt;%= Html.ValidationMessage(prop.PropertyName, &quot;*&quot;) %&gt;
            &lt;/div&gt;
        &lt;% } %&gt;
    &lt;% } %&gt;
&lt;% } %&gt;</pre>

<p>The Editor template for Object is nearly identical to the Display template, except that now we’ve added a call to ValidationMessage so that our default complex object editor will show error message asterisks.</p>

<h3><strong>Wrapping Up</strong></h3>

<p>Hopefully this post has helped you understand what the built-in templates are and exactly what each one of them does. You should be able to take these snippets of user controls and adapt them to create your own customized templates now. In the next blog post, I’ll discuss some of the quick (and not-so-quick) customizations you can do to alter the way your templates work.</p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/BradWilson?a=jWQP-JRcgWs:R32T9RV2ADA:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/BradWilson?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/BradWilson?a=jWQP-JRcgWs:R32T9RV2ADA:dnMXMwOfBR0"><img src="http://feeds.feedburner.com/~ff/BradWilson?d=dnMXMwOfBR0" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/BradWilson?a=jWQP-JRcgWs:R32T9RV2ADA:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/BradWilson?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/BradWilson?a=jWQP-JRcgWs:R32T9RV2ADA:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/BradWilson?i=jWQP-JRcgWs:R32T9RV2ADA:V_sGLiPBpWU" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/BradWilson/~4/jWQP-JRcgWs" height="1" width="1"/><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?a=CFTyLbOSfIw:jWQP-JRcgWs:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?a=CFTyLbOSfIw:jWQP-JRcgWs:dnMXMwOfBR0"><img src="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?d=dnMXMwOfBR0" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?a=CFTyLbOSfIw:jWQP-JRcgWs:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?a=CFTyLbOSfIw:jWQP-JRcgWs:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?i=CFTyLbOSfIw:jWQP-JRcgWs:V_sGLiPBpWU" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/BradWilson-ThenetGuy/~4/CFTyLbOSfIw" height="1" width="1"/>]]></content:encoded>


<dc:subject>ASP.NET</dc:subject>
<dc:subject>ASP.NET MVC</dc:subject>
<dc:subject>Technical</dc:subject>

<dc:creator>Brad Wilson</dc:creator>
<dc:date>2009-10-28T17:03:27-07:00</dc:date>
<feedburner:origLink>http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-3-default-templates.html</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/BradWilson/~3/jWQP-JRcgWs/aspnet-mvc-2-templates-part-3-default-templates.html</feedburner:origLink></item>
<item rdf:about="http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-2-modelmetadata.html">
<title>ASP.NET MVC 2 Templates, Part 2: ModelMetadata</title>
<link>http://feedproxy.google.com/~r/BradWilson-ThenetGuy/~3/Ud6vCjKtOTo/aspnet-mvc-2-templates-part-2-modelmetadata.html</link>
<description>Series Index Part 1: Introduction Part 2: ModelMetadata Part 3: Default Templates Part 4: Custom Object Templates Part 5: Master Page Templates Understanding Your Model One of the classes we introduced with ASP.NET MVC 2 is ModelMetadata. This class is...</description>
<content:encoded><![CDATA[<h3><strong>Series Index</strong></h3>  <ul>   <li><a href="http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-1-introduction.html">Part 1: Introduction</a> </li>    <li><em>Part 2: ModelMetadata</em> </li>    <li><a href="http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-3-default-templates.html">Part 3: Default Templates</a> </li>    <li><a href="http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-4-custom-object-templates.html">Part 4: Custom Object Templates</a></li>    <li><a href="http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-5-master-page-templates.html">Part 5: Master Page Templates</a>&#160;</li> </ul>  <h3><strong>Understanding Your Model</strong></h3>  <p>One of the classes we introduced with ASP.NET MVC 2 is ModelMetadata. This class is designed to tell you interesting things about the objects you want to display or edit. While we commonly use them when writing templates, this metadata is actually always available, even when you’re not in a template.</p>  <h3><strong>What is a Model?</strong></h3>  <p>When it comes to ModelMetadata, the definition of “model” is probably a bit blurrier than you’re used to.</p>  <p>Let’s say for instance that you have the model from part 1 of this blog series:</p>  <pre class="brush:csharp">public class Contact {
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int Age { get; set; }
}</pre>

<p>You created a strongly-typed view for this model, and if inside the view you access ViewData.ModelMetadata, then the model at this point is the Contact object.</p>

<p>However, through this metadata object, you can also get metadata about all of its properties. This returns a collection of ModelMetadata objects, one for each of the properties. If we were to do this with our Contact object, we’d end up with 3 new metadata objects, one each for FirstName, LastName, and Age. When you’re looking at the model metadata for FirstName, the model type is String (and the container type is Contact). In this way, you can even recursively dive through several layers of complex objects via properties.</p>

<h3></h3>

<h3><strong>How Do I Get One?</strong></h3>

<p><em>Use the one for the current model.</em></p>

<blockquote>
  <p>The most common way to get one is to access the ModelMetadata property on ViewData as shown above. This metadata object describes the ViewData’s Model. When you’re rendering a template for an object, this is the most common way to get metadata.</p>
</blockquote>

<p><em>Get one for properties on metadata you already have.</em></p>

<blockquote>
  <p>If you have a metadata object in hand, you can call the Properties property, which returns a list of ModelMetadata objects for each of the properties of that model.</p>
</blockquote>

<p><em>Get one from an expression.</em></p>

<blockquote>
  <p>The ModelMetadata class has two static methods on it: FromStringExpression and FromLambdaExpression. These are the methods that are used when you want t turn a string expression (like “PropertyName”) or a code-based expression (like “m =&gt; m.PropertyName”) into the appropriate ModelMetadata. Most of the existing HTML helpers have been re-written in terms of these two methods, so that they exhibit consistent parsing of expressions (and can use the ModelMetadata to make better decisions about how to display objects).</p>
</blockquote>

<h3><strong>What’s Inside Of One?</strong></h3>

<p>Before we talk about how ModelMetadata is populated, let’s quickly review what kind of information is available inside of a ModelMetadata object.</p>

<p><em>Properties about the model and its container</em></p>

<ul>
  <li><strong>Model</strong> and <strong>ModelType</strong> 

    <br />Retrieves the value and type of the model itself. Although the model value itself may be null, we may still know the type of the model (for example, we can derive that information from the lambda expression). </li>

  <li><strong>ContainerType</strong> and <strong>PropertyName</strong> 

    <br />Retrieves the type of the container object and the name of the property that this value came from. Not all models come from properties, so these may be null. </li>

  <li><strong>Properties</strong> 

    <br />Retrieves a collection of ModelMetadata objects which describe the properties of the existing model. </li>
</ul>

<p><em>Metadata about the model</em></p>

<ul>
  <li><strong>ConvertEmptyStringToNull 
      <br /></strong>A flag which indicates whether empty strings that are posted back in forms should be converted into NULLs. <em>Default: true</em> </li>

  <li><strong>DataTypeName 
      <br /></strong>A string which can used to give meta information about the data type (for example, to let you know that this string is actually an e-mail address). Some well-known data type names include “EmailAddress”, “Html”, “Password”, and “Url”. <em>Default: null</em> </li>

  <li><strong>Description</strong> 

    <br />A long-form textual description of this model. <em>Default: null</em> </li>

  <li><strong>DisplayFormatString</strong> 

    <br />A format string that will be used when displaying this model value in a template. <em>Default: null</em> </li>

  <li><strong>DisplayName</strong> 

    <br />The display name of this model value. Used in templates and Html.Label/LabelFor to generate the label text. <em>Default: null</em> </li>

  <li><strong>EditFormatString 
      <br /></strong>A format string that will be used when editing this model value in a template. <em>Default: null</em> </li>

  <li><strong>HideSurroundingHtml 
      <br /></strong>A flag which indicates that this field should not have any of its surrounding HTML (for example, a label). Often used when a template will be generating a hidden input. <em>Default: null</em> </li>

  <li><strong>IsComplexType</strong> 

    <br />A flag which indicates whether the system considers this to be a complex type (and therefore will default to the complex object template rather than the string template). <em>Not user-settable</em> </li>

  <li><strong>IsNullableValueType</strong> 

    <br />A flag which indicates whether the model is a nullable value type (namely, Nullable&lt;T&gt;). <em>Not user-settable</em> </li>

  <li><strong>IsReadOnly</strong> 

    <br />A flag which indicates if this value is read-only (for example, because the property does not have a setter). <em>Default: false</em> </li>

  <li><strong>IsRequired</strong> 

    <br />A flag which indicates if this value is required. <em>Default: true for non-nullable value types; false for all others.</em> </li>

  <li><strong>NullDisplayText</strong> 

    <br />The text which should be used when attempting to display a null model. <em>Default: null</em> </li>

  <li><strong>ShortDisplayName</strong> 

    <br />The short display name of this mode value. Intended to be used in the title of tabular list views. If this field is null, then DisplayName should be used. <em>Default: null</em> </li>

  <li><strong>ShowForDisplay</strong> 

    <br />A flag which indicates if this model should be shown in display mode. <em>Default: true</em> </li>

  <li><strong>ShowForEdit</strong> 

    <br />A flag which indicates if this model should be shown in edit mode. <em>Default: true</em> </li>

  <li><strong>SimpleDisplayText</strong> 

    <br />Text which should be shown for this model when summarizing what would otherwise be a complex object display. <em>Default: see below</em> </li>

  <li><strong>TemplateHint</strong> 

    <br />A string which indicates a hint as to what template should be used for this model. <em>Default: null</em> </li>

  <li><strong>Watermark</strong> 

    <br />Text that might be displayed as a watermark when editing this model in a text box. <em>Default: null</em> </li>
</ul>

<p><em>Helper methods</em></p>

<ul>
  <li><strong>GetDisplayName()</strong> 

    <br />This method can be used to get a display name for the model. If DisplayName is not null, it returns that; then it checks if PropertyName is not null, and if so it returns that; failing all those, it returns ModelType.Name. </li>

  <li><strong>GetValidators()</strong> 

    <br />This method can be used to retrieve the validators that are applicable for this model. These can be used to either run server-side validation on this model, or to generate the client-side validation rules. </li>
</ul>

<p><em>The default value for SimpleDisplayText follows these rules:</em></p>

<ul>
  <li>If the Model is null, return NullDisplayText </li>

  <li>If the type has overridden the value of Model.ToString(), then return that </li>

  <li>If the model has no properties, return String.Empty </li>

  <li>If the model’s first property is null, then return that property’s NullDisplayText value </li>

  <li>Otherwise, return the model’s first property’s ToString() value </li>
</ul>

<h3><strong>Where Does ModelMetadata Come From?</strong></h3>

<p>We’ve added a pluggable metadata provider system in ASP.NET MVC 2. By default, the ModelMetadata objects are constructed with data taken from attributes, primarily from the System.ComponentModel and System.ComponentModel.DataAnnotations namespaces.</p>

<p>When using the default DataAnnotations model metadata provider, the following attributes will influence model metadata:</p>

<ul>
  <li><strong>[HiddenInput]</strong> <em>(from System.Web.Mvc)</em> 

    <br />Applying this attribute will generate a hidden input when editing this model. By default, it will also hide all the surrounding HTML, unless you set the DisplayValue flag to be true; in this case, it will generate both a displayed value (with its surrounding HTML) and the hidden input. In addition to setting HideSurroundHtml, it also sets a TemplateHint of “HiddenInput” (which be overridden with [UIHint]) </li>

  <li><strong>[UIHint]</strong> <em>(from System.ComponentModel.DataAnnotations)</em> 

    <br />This will set the TemplateHint property with the name of the UI hint. We first look for a PresentationLayer type of “MVC”, and if there isn’t one, look for an empty or null PresentationLayer. </li>

  <li><strong>[DataType]</strong> <em>(from System.ComponentModel.DataAnnotations)</em> 

    <br />This will set the DataTypeName property. </li>

  <li><strong>[ReadOnly]</strong> <em>(from System.ComponentModel)</em> 

    <br />This will set the IsReadOnly property. Note that because we use Type descriptors, any property without a public setter will have the [ReadOnly] attribute automatically. </li>

  <li><strong>[DisplayFormat]</strong> <em>(from System.ComponentModel.DataAnnotations)</em> 

    <br />Setting NullDisplayText on this attribute sets NullDisplayText on model metadata. Setting DataFormatString will set DisplayFormatString on model metadata; if ApplyFormatInEditMode is set to true, then it will also set the EditFormatString on model metadata. Setting ConvertEmptyStringToNull on the attribute will set ConvertEmptyStringToNull on model metadata. </li>

  <li><strong>[ScaffoldColumn]</strong> <em>(from System.ComponentModel.DataAnnotations)</em> 

    <br />This will set both the ShowForDisplay and ShowForEdit properties. </li>

  <li><strong>[DisplayName]</strong> <em>(from System.ComponentModel)</em> 

    <br />This will set the DisplayName property. </li>
</ul>

<h3><strong>Wrapping Up</strong></h3>

<p>Now we know a little bit more about the metadata that’s available about your models when writing templates. In the next blog post, we’ll talk about the default templates that are built into ASP.NET MVC 2, and show what they would look like if you wrote them as .ascx files.</p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/BradWilson?a=b07lc3BkZiI:N7AeIbUYjlc:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/BradWilson?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/BradWilson?a=b07lc3BkZiI:N7AeIbUYjlc:dnMXMwOfBR0"><img src="http://feeds.feedburner.com/~ff/BradWilson?d=dnMXMwOfBR0" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/BradWilson?a=b07lc3BkZiI:N7AeIbUYjlc:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/BradWilson?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/BradWilson?a=b07lc3BkZiI:N7AeIbUYjlc:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/BradWilson?i=b07lc3BkZiI:N7AeIbUYjlc:V_sGLiPBpWU" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/BradWilson/~4/b07lc3BkZiI" height="1" width="1"/><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?a=Ud6vCjKtOTo:b07lc3BkZiI:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?a=Ud6vCjKtOTo:b07lc3BkZiI:dnMXMwOfBR0"><img src="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?d=dnMXMwOfBR0" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?a=Ud6vCjKtOTo:b07lc3BkZiI:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?a=Ud6vCjKtOTo:b07lc3BkZiI:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?i=Ud6vCjKtOTo:b07lc3BkZiI:V_sGLiPBpWU" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/BradWilson-ThenetGuy/~4/Ud6vCjKtOTo" height="1" width="1"/>]]></content:encoded>


<dc:subject>ASP.NET</dc:subject>
<dc:subject>ASP.NET MVC</dc:subject>
<dc:subject>Technical</dc:subject>

<dc:creator>Brad Wilson</dc:creator>
<dc:date>2009-10-27T12:10:44-07:00</dc:date>
<feedburner:origLink>http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-2-modelmetadata.html</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/BradWilson/~3/b07lc3BkZiI/aspnet-mvc-2-templates-part-2-modelmetadata.html</feedburner:origLink></item>
<item rdf:about="http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-1-introduction.html">
<title>ASP.NET MVC 2 Templates, Part 1: Introduction</title>
<link>http://feedproxy.google.com/~r/BradWilson-ThenetGuy/~3/V25i2Varxrw/aspnet-mvc-2-templates-part-1-introduction.html</link>
<description>Series Index Part 1: Introduction Part 2: ModelMetadata Part 3: Default Templates Part 4: Custom Object Templates Part 5: Master Page Templates Introduction to Templates One of the major new features in ASP.NET MVC 2 is templates. This is a...</description>
<content:encoded><![CDATA[<h3><strong>Series Index</strong></h3>  <ul>   <li><em>Part 1: Introduction </em></li>    <li><a href="http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-2-modelmetadata.html">Part 2: ModelMetadata</a> </li>    <li><a href="http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-3-default-templates.html">Part 3: Default Templates</a> </li>    <li><a href="http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-4-custom-object-templates.html">Part 4: Custom Object Templates</a></li>    <li><a href="http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-5-master-page-templates.html">Part 5: Master Page Templates</a></li> </ul>  <h3><strong>Introduction to Templates</strong></h3>  <p>One of the major new features in ASP.NET MVC 2 is templates.</p>  <p>This is a feature that’s similar to Dynamic Data for WebForms. Given an object of a given type, the system can automatically display or edit that object, whether it’s a simple data item (like an integer, a decimal, a string, etc.) or a complex data item (like a class).</p>  <h3><strong>Html.Display</strong></h3>  <p>To display an item, there are three Display method HTML helpers (each with a few overloads):</p>  <ul>   <li><strong>String based: </strong>&lt;%= Html.Display(“PropertyName”) %&gt; </li>    <li><strong>Expression based: </strong>&lt;%= Html.DisplayFor(model =&gt; model.PropertyName) %&gt; </li>    <li><strong>Model: </strong>&lt;%= Html.DisplayForModel() %&gt; </li> </ul>  <p>The string-based versions can be used to pull things to be displayed from both ViewData and a model (whose exact type you may not know).</p>  <p>The expression-based versions are primarily used for pulling values from the model (they are parameterized by the current model, as shown in the example above). They can also be used for pulling values from some source other than the model or ViewData (for example, with an expression like “model =&gt; someOtherValue” which ignores the model entirely). This makes them useful in loops.</p>  <p>The model expressions are simple helpers which operate on the current model. The line <strong>DisplayForModel()</strong> is equivalent to <strong>DisplayFor(model =&gt; model)</strong>.</p>  <p>Let’s start off with a model:</p>  <pre class="brush:csharp">public class Contact {
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int Age { get; set; }
}</pre>

<p>and an action:</p>

<pre class="brush:csharp">public ViewResult Details([DefaultValue(0)] int id) {
    return View(contacts[id]);
}</pre>

<p>and a view:</p>

<pre class="brush:html">&lt;%@ Page Language=&quot;C#&quot;
    MasterPageFile=&quot;~/Views/Shared/Site.master&quot;
    Inherits=&quot;System.Web.Mvc.ViewPage&quot; %&gt;

&lt;asp:Content ContentPlaceHolderID=&quot;MainContent&quot; runat=&quot;server&quot;&gt;
    &lt;%= Html.DisplayForModel() %&gt;
&lt;/asp:Content&gt;</pre>

<p>Running the action yields this result:</p>

<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Example web page for DisplayForModel" border="0" alt="Example web page for DisplayForModel" src="http://bradwilson.typepad.com/.a/6a00e54fbd8c4988340120a679aa0e970c-pi" width="295" height="201" /> </p>

<h3><strong>Html.Editor</strong></h3>

<p>As with Html.Display, there are three versions of Html.Editor, which are used to edit objects:</p>

<ul>
  <li><strong>String based: </strong>&lt;%= Html.Editor(“PropertyName”) %&gt; </li>

  <li><strong>Expression based: </strong>&lt;%= Html.EditorFor(model =&gt; model.PropertyName) %&gt; </li>

  <li><strong>Model: </strong>&lt;%= Html.EditorForModel() %&gt; </li>
</ul>

<p>If I change my view from <strong>DisplayForModel</strong> to <strong>EditorForModel</strong>, this is what I’ll see:</p>

<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Example web page for EditorForModel" border="0" alt="Example web page for EditorForModel" src="http://bradwilson.typepad.com/.a/6a00e54fbd8c4988340120a679aa13970c-pi" width="464" height="224" /> </p>

<p>Now we can see that, for strings and integers, the system will provide text box editors automatically for us.</p>

<h3><strong>What’s Really Happening?</strong></h3>

<p>The template system in MVC 2 contains several built-in templates.</p>

<p>The first one we’re seeing in action here is the complex object template. In order to “display” or “edit” a complex object, the system actually uses reflection to find all the properties on that object, and then automatically generates labels and displays/editors for each of those properties.</p>

<p>If we were to write the core logic for this, it might look something like this:</p>

<pre class="brush:html">&lt;% foreach (var prop in ViewData.ModelMetadata.Properties) { %&gt;
    &lt;div class=&quot;display-label&quot;&gt;&lt;%= prop.GetDisplayName() %&gt;&lt;/div&gt;
    &lt;div class=&quot;display-field&quot;&gt;&lt;%= Html.Display(prop.PropertyName) %&gt;&lt;/div&gt;
&lt;% } %&gt;</pre>

<p><em>Note that this is nowhere near a complete implementation; I’ll talk about some of what’s missing in a later blog post.</em></p>

<p>That is the core of the complex object display template: loop over all the properties of the current model, and for each of those properties, show its label and then call <strong>Html.Display()</strong> to display the actual property value.</p>

<p>What happens when we want to display a string? This is roughly the view code for that:</p>

<pre class="brush:html">&lt;%= Html.Encode(Model) %&gt;</pre>

<p><em>Again, this is not the actual code, but we will see what the real code is in a later blog post.</em></p>

<h3><strong>Overriding Templates</strong></h3>

<p>There is a lot of value in having a bunch of templates built-in, but the bigger value is in being able to override the template at any point in the rendering process.</p>

<p>Here, I’m going to override the display template for strings by creating a partial view named String inside of <strong>~/Views/<em>ControllerName</em>/DisplayTemplates</strong>:</p>

<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Screenshot of Views showing DisplayTemplates folder and String.ascx" border="0" alt="Screenshot of Views showing DisplayTemplates folder and String.ascx" src="http://bradwilson.typepad.com/.a/6a00e54fbd8c4988340120a6223fa0970b-pi" width="206" height="146" /> </p>

<p>And inside this file, I write:</p>

<pre class="brush:html">&lt;%@ Control Language=&quot;C#&quot; Inherits=&quot;System.Web.Mvc.ViewUserControl&quot; %&gt;
&lt;%= Html.Encode(Model) %&gt; <em>Hello there!</em></pre>

<p>Now I refresh the page and see:</p>

<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Updated DisplayForModel view using our custom template" border="0" alt="Updated DisplayForModel view using our custom template" src="http://bradwilson.typepad.com/.a/6a00e54fbd8c4988340120a6223fa7970b-pi" width="465" height="200" /> </p>

<p>You can see that we’ve picked up the new template automatically, and it’s being used for all of our strings. It’s also being used for the integer Age, but we’ll cover why that is in a later blog post.</p>

<p>If we want to write a template for editors, then you place it in a folder named <strong>EditorTemplates</strong>.</p>

<h3><strong>Wrapping Up</strong></h3>

<p>We have a lot to learn about this new Templates feature in ASP.NET MVC 2. This post has introduced us to the template concept and shown us how we can override the built-in templates. In the next blog post, we’ll talk about what the ModelMetadata class is and how it affects templates, as well as the DataAnnotations attributes that feed into ModelMetadata by default in ASP.NET MVC 2.</p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/BradWilson?a=ABtBIh3wpgQ:7ggBzW1U03c:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/BradWilson?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/BradWilson?a=ABtBIh3wpgQ:7ggBzW1U03c:dnMXMwOfBR0"><img src="http://feeds.feedburner.com/~ff/BradWilson?d=dnMXMwOfBR0" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/BradWilson?a=ABtBIh3wpgQ:7ggBzW1U03c:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/BradWilson?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/BradWilson?a=ABtBIh3wpgQ:7ggBzW1U03c:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/BradWilson?i=ABtBIh3wpgQ:7ggBzW1U03c:V_sGLiPBpWU" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/BradWilson/~4/ABtBIh3wpgQ" height="1" width="1"/><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?a=V25i2Varxrw:ABtBIh3wpgQ:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?a=V25i2Varxrw:ABtBIh3wpgQ:dnMXMwOfBR0"><img src="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?d=dnMXMwOfBR0" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?a=V25i2Varxrw:ABtBIh3wpgQ:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?a=V25i2Varxrw:ABtBIh3wpgQ:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?i=V25i2Varxrw:ABtBIh3wpgQ:V_sGLiPBpWU" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/BradWilson-ThenetGuy/~4/V25i2Varxrw" height="1" width="1"/>]]></content:encoded>


<dc:subject>ASP.NET</dc:subject>
<dc:subject>ASP.NET MVC</dc:subject>
<dc:subject>Technical</dc:subject>

<dc:creator>Brad Wilson</dc:creator>
<dc:date>2009-10-26T17:46:05-07:00</dc:date>
<feedburner:origLink>http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-1-introduction.html</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/BradWilson/~3/ABtBIh3wpgQ/aspnet-mvc-2-templates-part-1-introduction.html</feedburner:origLink></item>
<item rdf:about="http://bradwilson.typepad.com/blog/2009/10/enterprise-library-validation-example-for-aspnet-mvc-2.html">
<title>Enterprise Library Validation example for ASP.NET MVC 2</title>
<link>http://feedproxy.google.com/~r/BradWilson-ThenetGuy/~3/N1qP9n09p8E/enterprise-library-validation-example-for-aspnet-mvc-2.html</link>
<description>This blog post is about a preview release of ASP.NET MVC 2. Details may change by the time the final release becomes available, so the code presented here may not necessarily work on future releases with slight modification. In ASP.NET...</description>
<content:encoded><![CDATA[<p><em>This blog post is about a preview release of ASP.NET MVC 2. Details may change by the time the final release becomes available, so the code presented here may not necessarily work on future releases with slight modification.</em></p>

<p>In ASP.NET MVC 2 Preview 1, we added support for server-side validation via the DataAnnotation attributes.</p> <p>In <a href="http://go.microsoft.com/fwlink/?LinkID=154414">ASP.NET MVC 2 Preview 2</a>, we enhanced the validation support to support client-side validation, as well as make validation extensible. We still ship with DataAnnotations support in the box, but now you can plug in a third party validation library and get validation support in your MVC applications.</p>

<p>In this blog post, I’m going to show the code for a validation provider for <a href="http://entlib.codeplex.com/">Enterprise Library</a>’s Validation Application Block that works with MVC 2 Preview 2. <em>This code is written against </em><a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=1643758B-2986-47F7-B529-3E41584B6CE5"><em>EntLib 4.1</em></a><em>, the current release version as of the writing of this blog post. You will need to take references to Microsoft.Practices.EnterpriseLibrary.Common.dll and Microsoft.Practices.EnterpriseLibrary.Validation.dll to get the code in this sample to compile.</em></p>

<h3><strong>The extensibility classes</strong></h3>

<p>We have provided an abstract base class for all validator provider authors: <strong>ModelValidatorProvider</strong>. To write a validation provider for MVC 2, you derive a new class from ModelValidationProvider and implement its single method:</p>

<pre class="brush:csharp">public abstract class ModelValidatorProvider {
  public abstract IEnumerable&lt;ModelValidator&gt; GetValidators(ModelMetadata metadata, ControllerContext context);
}</pre>
 
<p>The usage is relatively straight forward: given a controller context (which describes the current request) and a ModelMetadata (which describes the object to be validated), you should return 0 or more validators to be run against the model.</p>
 
<p>A validator is a class which derives from the abstract base class <strong>ModelValidator</strong>. This class accepts the instances of ModelMetadata and ControllerContext as its constructor arguments, and exposes them via protected properties. Authors of validators have an abstract method they must implement (to do server-side validation) and a virtual method they may override (to provide client-side validation hints, which will be covered in another blog post):</p>
 
<pre class="brush:csharp">public virtual IEnumerable&lt;ModelClientValidationRule&gt; GetClientValidationRules() {
  return Enumerable.Empty&lt;ModelClientValidationRule&gt;();
}
 
public abstract IEnumerable&lt;ModelValidationResult&gt; Validate(object container);</pre>
 
<p>When a validator runs on the server side, it is provided the container, and returns 0 or more <strong>ModelValidationResult</strong> objects that describe validation failures.</p>
 
<p>The container that’s passed here is the parent object for the object you’re validating. So, for example, if you’re validating the FirstName property on a Contact class, the ModelMetadata that you were given in the constructor describes the FirstName property and has the value for the property in the “Model” property, and the container that’s passed here will be the instance of the Contact record.</p>
 
<p>The ModelValidationResult class contains two values: the error message and the member name that the message applies to. If the validation message applies directly to the thing you’re validating (i.e., “FirstName” in this case), then you will leave the member name blank or null; if the message applies to some sub-property of the thing you’re validating (for example, you’re doing a multi-property validation against the model itself), then member name should be set to tell MVC which field to show the error for.</p>
 
<h3><strong>EntLibValidatorProvider and EntLibValidatorWrapper</strong></h3>
 
<p>Our implementation for EntLibValidatorProvider is relatively simple:</p>
 
<pre class="brush:csharp">using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using Microsoft.Practices.EnterpriseLibrary.Validation;
 
public class EntLibValidatorProvider : ModelValidatorProvider {
  public override IEnumerable&lt;ModelValidator&gt; GetValidators(ModelMetadata metadata, ControllerContext context) {
    Validator validator = ValidationFactory.CreateValidator(metadata.ModelType);
 
    if (validator != null) {
      yield return new EntLibValidatorWrapper(metadata, context, validator);
    }
  }
}</pre>
 
<p>EntLib’s ValidationFactory can create an EntLib Validator object for us for the given class we want to validate. If it does, then we’ll return a single instance of a new class called EntLibValidatorWrapper, which implements ModelValidator.</p>
 
<p>EntLib’s Validator object contains a Validate method, which we will call to validate the object. It returns a collection of EntLib ValidationResult objects, which we will convert into MVC’s ModelValidationResult. EntLib&#39;s ValidationResult allows nested validation results, so we&#39;ll write the converter function to be recursive to flatten the list out for MVC.</p>
 
<p>The code is again relatively straight forward:</p>
 
<pre class="brush:csharp">using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using Microsoft.Practices.EnterpriseLibrary.Validation;
 
public class EntLibValidatorWrapper : ModelValidator {
  private Validator _validator;
 
  public EntLibValidatorWrapper(ModelMetadata metadata, ControllerContext context, Validator validator)
    : base(metadata, context) {
    _validator = validator;
  }
 
  public override IEnumerable&lt;ModelValidationResult&gt; Validate(object container) {
    return ConvertResults(_validator.Validate(Metadata.Model));
  }
 
  private IEnumerable&lt;ModelValidationResult&gt; ConvertResults(IEnumerable&lt;ValidationResult&gt; validationResults) {
    if (validationResults != null) {
      foreach (ValidationResult validationResult in validationResults) {
        if (validationResult.NestedValidationResults != null) {
          foreach (ModelValidationResult result in ConvertResults(validationResult.NestedValidationResults)) {
            yield return result;
          }
        }
 
        yield return new ModelValidationResult {
          Message = validationResult.Message,
          MemberName = validationResult.Key
        };
      }
    }
  }
}</pre>
 
<p>Now all that’s left is to register this with <strong>ModelValidatorProviders.Current</strong> and we’ve enabled server-side Enterprise Library validation support. We can decorate our models with EntLib’s validation attributes, and all model binding – implicit via action parameters, or explicit via calls to UpdateModel/TryUpdateModel on a controller – will now run EntLib’s validation automatically.</p>
 
<h3><strong>Why no client-side validation support?</strong></h3>
 
<p>The current design of EntLib’s Validation Application Block uses the <a href="http://en.wikipedia.org/wiki/Composite_pattern">Composite pattern</a>; that is, when we ask for validation for an object, it returns back a single validator object that contains a list of all the validation work to be done. While this is very convenient from a normal usage scenario, the unfortunate side-effect is that we can’t “peek inside” to see what the individual validations are that it’s doing, and therefore can’t generate the appropriate client-side validation hints.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/BradWilson?a=wwxV96T1tNQ:uadpgVovcCA:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/BradWilson?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/BradWilson?a=wwxV96T1tNQ:uadpgVovcCA:dnMXMwOfBR0"><img src="http://feeds.feedburner.com/~ff/BradWilson?d=dnMXMwOfBR0" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/BradWilson?a=wwxV96T1tNQ:uadpgVovcCA:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/BradWilson?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/BradWilson?a=wwxV96T1tNQ:uadpgVovcCA:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/BradWilson?i=wwxV96T1tNQ:uadpgVovcCA:V_sGLiPBpWU" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/BradWilson/~4/wwxV96T1tNQ" height="1" width="1"/><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?a=N1qP9n09p8E:wwxV96T1tNQ:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?a=N1qP9n09p8E:wwxV96T1tNQ:dnMXMwOfBR0"><img src="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?d=dnMXMwOfBR0" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?a=N1qP9n09p8E:wwxV96T1tNQ:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?a=N1qP9n09p8E:wwxV96T1tNQ:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?i=N1qP9n09p8E:wwxV96T1tNQ:V_sGLiPBpWU" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/BradWilson-ThenetGuy/~4/N1qP9n09p8E" height="1" width="1"/>]]></content:encoded>


<dc:subject>ASP.NET</dc:subject>
<dc:subject>ASP.NET MVC</dc:subject>
<dc:subject>Technical</dc:subject>

<dc:creator>Brad Wilson</dc:creator>
<dc:date>2009-10-02T11:31:35-07:00</dc:date>
<feedburner:origLink>http://bradwilson.typepad.com/blog/2009/10/enterprise-library-validation-example-for-aspnet-mvc-2.html</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/BradWilson/~3/wwxV96T1tNQ/enterprise-library-validation-example-for-aspnet-mvc-2.html</feedburner:origLink></item>
<item rdf:about="http://bradwilson.typepad.com/blog/2009/09/xunitnet-15-shipped.html">
<title>xUnit.net 1.5 Shipped</title>
<link>http://feedproxy.google.com/~r/BradWilson-ThenetGuy/~3/-_Op43r1xRU/xunitnet-15-shipped.html</link>
<description>Jim and I released xUnit.net 1.5 a couple weeks ago. This was the first full RTM release in about 9 months, an unfortunate side-effect of our busy schedules. :) The major new feature of 1.5 is the new GUI runner,...</description>
<content:encoded><![CDATA[<p><a href="http://jamesnewkirk.typepad.com">Jim</a> and I released <a href="http://xunit.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=31606">xUnit.net 1.5</a> a couple weeks ago.</p>

<p>This was the first full RTM release in about 9 months, an unfortunate side-effect of our busy schedules. :) The major new feature of 1.5 is the new GUI runner, which has evolved over several CTP and beta builds.</p>

<p>Here is a screenshot of the new GUI runner in 1.5:</p>

<p><a href="http://www.flickr.com/photos/dotnetguy/3945901278/" title="xUnit.net 1.5 GUI by Brad Wilson, on Flickr"><img alt="xUnit.net 1.5 GUI" border="0" height="371" src="http://farm3.static.flickr.com/2445/3945901278_85746df69a.jpg" width="500" /></a></p>

<p>If you&#39;re used to using the GUI runners in other testing tools, you&#39;ll notice that our GUI runner is significantly different. Rather than the traditional &quot;tree&quot; view, we&#39;ve opted for a flat, integrated list of tests (the large box in the upper right of the window). Whatever is visible in this list will be run if you click &quot;Run All&quot;; you can also select specific tests, which turns the button into &quot;Run Selected&quot;.</p><p>These test methods can be filtered in several ways, using the Refinements section on the left:</p><ul>
<li>The search box will search and filter methods whose method name, namespace name, or display name match the provided text</li>
<li>The assemblies list allows you to filter down to just the tests in one or more of your selected assemblies</li>
<li>The traits list shows all the [Trait] attribute name/value combinations in your tests.</li>
<li>The count buttons at the top of the method list also work as filters, so you can quickly just see the tests that have passed, failed, or were skipped.</li>
</ul>
<p>Assemblies are not locked, so you can leave the GUI runner open while working on your test code, and when test assemblies are recompiled, the GUI will automatically reload the DLL. Tests are run on a background thread so that the UI remains responsive while running tests.</p><p>There are lots of other small new features, plus a bunch of bug fixes, which we cover in the release notes (shown below):</p><span id="ctl00_ctl00_MasterContent_Content_ReleasePanelOrderingContainer_ReleaseDescriptionLiteral"><p class="wikidoc "><h3><strong>xUnit.net release 1.5</strong></h3>
Build #1479<br />Change set #<a class="externalLink" href="http://xunit.codeplex.com/SourceControl/changeset/view/42400">42400<span class="externalLinkIcon"></span></a><br /><br /><strong>Important notes for Resharper users:</strong><br /><br /><em>Resharper support has been moved to the <a class="externalLink" href="http://xunitcontrib.codeplex.com/">xUnit.net Contrib<span class="externalLinkIcon"></span></a> project.</em><br /><br /><strong>Important note for TestDriven.net users:</strong><br /><br /><em>If you are having issues running xUnit.net tests in TestDriven.net, especially on 64-bit Windows, we strongly recommend you <a class="externalLink" href="http://www.testdriven.net/">upgrade to TD.NET version 2.20<span class="externalLinkIcon"></span></a> or later. It is also important to uninstall and reinstall TD.NET support using xunit.installer.exe.</em><br /><br /><strong>This release adds the following new features:</strong>
<ul>
<li>Better support for 64-bit machines, including forced 32-bit runners</li>
<li>Introduced a new GUI runner, which allows:
<ul>
<li>Multiple assemblies</li>
<li>Filters on text, assembly, traits, and last run state</li>
<li>Project (.xunit) files</li>
<li>Multithreaded UI so that tests aren&#39;t slowed down by UI updates</li>
<li>Assemblies are not locked and are automatically reloaded so that
you can continue to work on your tests in Visual Studio while leaving
the GUI runner running</li>
<li>Automatically remembers UI window placement and recent assemblies/projects</li>
</ul>
</li>
<li>Additional MSBuild task which consumes project (.xunit) files</li>
<li>Support for MVC 1.0 and MVC 2 Preview 1, including both C# and VB.NET</li>
<li>A new test runner object model for runner authors (supporting multiple assemblies)</li>
<li>IEnumerable/IEnumerable&lt;T&gt; support for Assert.Equal</li>
<li>Better support for Assert.Throws for expressions which return values</li>
<li>Support for installation-free running with TestDriven.net (2.23 or later)</li>
</ul>
<strong>This release fixes several issues, including:</strong>
<ul>
<li>Added an output property named ExitCode to the MSBuild runner (0=success, -1=fail)</li>
<li>Expected/actual messages are improved when values are the same but types don&#39;t match</li>
<li>Fixed an issue where assemblies without config files run from MSBuild were using MSBuild.exe.config as their config file.</li>
<li>Fixed several broken samples.</li>
<li>Fixed an issue where long-running tests would be aborted in the console runner.</li>
<li>Fixed an issue with CDATA handling in test results.</li>
</ul>
<em>For a complete list of fixed issues, see the <a href="http://xunit.codeplex.com/WorkItem/AdvancedList.aspx">Issue Tracker</a>.</em><br /><br /><strong>This release includes:</strong>
<ul>
<li>Core library (<strong>xunit.dll</strong>)</li>
<li>Support for <a class="externalLink" href="http://www.asp.net/mvc/">ASP.NET MVC 1.0 and 2.0 Preview 1<span class="externalLinkIcon"></span></a></li>
<li>Support for CruiseControl.net (see the <a href="http://xunit.codeplex.com/Wiki/View.aspx?title=HowToUseCcNet">wiki</a> for more information)</li>
<li>Support for TeamCity (see the <a href="http://xunit.codeplex.com/Wiki/View.aspx?title=HowToUseTeamCity">wiki</a> for more information)</li>
<li>Version-resilient runner support (<strong>xunit.runner.utility.dll</strong>)</li>
<li>Installer utility for runners and ASP.NET MVC (<strong>xunit.installer.exe</strong>)</li>
<li>Runners:
<ul>
<li>Console runner (<strong>xunit.console.exe</strong> and <strong>xunit.console.x86.exe</strong>)</li>
<li>GUI runner (<strong>xunit.gui.exe</strong> and <strong>xunit.gui.x86.exe</strong>)</li>
<li>MSBuild runner (<strong>xunit.runner.msbuild.dll</strong>)</li>
<li>TestDriven.net 2.x runner (<strong>xunit.runner.tdnet.dll</strong>) <em>see note above</em></li>
</ul>
</li>
<li>Extensions for .NET 2.0+ (<strong>xunit.extensions.dll</strong>):
<ul>
<li>Data theories using <span class="codeInline">[Theory]</span> with support for data from inline values, properties, Excel spreadsheets, SQL Server, and OLE DB data sources</li>
<li><span class="codeInline">[AssumeIdentity]</span> extension</li>
<li><span class="codeInline">[AutoRollback]</span> extension</li>
<li><span class="codeInline">[FreezeClock]</span> extension</li>
<li><span class="codeInline">[Trace]</span> extension</li>
<li>TestClass and Assertions base class for assertion extensibility</li>
</ul>
</li>
</ul>
</p></span><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/BradWilson?a=SNM_fROJjc8:aAkwdPjPUVk:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/BradWilson?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/BradWilson?a=SNM_fROJjc8:aAkwdPjPUVk:dnMXMwOfBR0"><img src="http://feeds.feedburner.com/~ff/BradWilson?d=dnMXMwOfBR0" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/BradWilson?a=SNM_fROJjc8:aAkwdPjPUVk:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/BradWilson?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/BradWilson?a=SNM_fROJjc8:aAkwdPjPUVk:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/BradWilson?i=SNM_fROJjc8:aAkwdPjPUVk:V_sGLiPBpWU" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/BradWilson/~4/SNM_fROJjc8" height="1" width="1"/><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?a=-_Op43r1xRU:SNM_fROJjc8:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?a=-_Op43r1xRU:SNM_fROJjc8:dnMXMwOfBR0"><img src="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?d=dnMXMwOfBR0" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?a=-_Op43r1xRU:SNM_fROJjc8:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?a=-_Op43r1xRU:SNM_fROJjc8:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?i=-_Op43r1xRU:SNM_fROJjc8:V_sGLiPBpWU" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/BradWilson-ThenetGuy/~4/-_Op43r1xRU" height="1" width="1"/>]]></content:encoded>


<dc:subject>Agile</dc:subject>
<dc:subject>ASP.NET MVC</dc:subject>
<dc:subject>Technical</dc:subject>
<dc:subject>xUnit.net</dc:subject>

<dc:creator>Brad Wilson</dc:creator>
<dc:date>2009-09-22T14:15:33-07:00</dc:date>
<feedburner:origLink>http://bradwilson.typepad.com/blog/2009/09/xunitnet-15-shipped.html</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/BradWilson/~3/SNM_fROJjc8/xunitnet-15-shipped.html</feedburner:origLink></item>
<item rdf:about="http://bradwilson.typepad.com/blog/2009/09/movie-server-handbrake-and-interlacing.html">
<title>Movie Server, Handbrake, and Interlacing</title>
<link>http://feedproxy.google.com/~r/BradWilson-ThenetGuy/~3/n99yxbgQvUE/movie-server-handbrake-and-interlacing.html</link>
<description>I've been using my new Home Server as a massive network storage device whose primary purpose is to stream audio and video to my Apple TV box. The video conversion tool I've been using is Handbrake, mostly because it has...</description>
<content:encoded><![CDATA[<p dir="ltr" style="MARGIN-RIGHT: 0px">I&#39;ve been using my new Home Server as a massive network storage device whose primary purpose is to stream audio and video to my Apple TV box.</p>
<p>The video conversion tool I&#39;ve been using is<span class="Apple-converted-space">&#0160;</span><a href="http://www.handbrake.fr/" style="COLOR: blue !important; CURSOR: text !important; text-decoration: underline !important">Handbrake</a>, mostly because it has an excellent and powerful command line utility, as well as a GUI that you can use to inspect your DVDs and get the exact right command line. It&#39;s also cross-platform, so I could use the same tools and knowledge on both my Windows and OS X machines.</p>
<p>My goal was to be able to take video from a variety of sources, and ensure that I had great quality for playback on the Apple TV, but also support taking the video with me on the iPhone and Zune. As an added bonus, the video will play directly from as well as stream to the Xbox 360.</p>
<p>One of the mistakes I made was failing to realize that once I had video files, I was going to need to ensure that they were deinterlaced.</p>
<p>Interlacing is the process that older CRT TVs used where they would display half the picture at a time (every other line). A lot of video stored on DVDs is stored in this interlaced format. When you play it back on a DVD player, either they and/or your HDTV is designed to recognize this and deinterlace the picture when appropriate. Unfortunately, if you play back a video, this logic doesn&#39;t kick in, and the picture is distractingly jerky.</p>
<p>During playback, you&#39;ll see three normal frames, like so:</p>
<p><a href="http://www.flickr.com/photos/dotnetguy/3908421130/" title="Image Without Interlace by Brad Wilson, on Flickr"><img alt="Image Without Interlace" height="175" src="http://farm3.static.flickr.com/2458/3908421130_3bee75d442_o.png" style="BORDER-BOTTOM: medium none; BORDER-LEFT: medium none; BORDER-TOP: medium none; BORDER-RIGHT: medium none" width="325" /></a></p>
<p>Followed by two interlaced frames, like so:</p>
<p><a href="http://www.flickr.com/photos/dotnetguy/3908421194/" title="Image With Interlace by Brad Wilson, on Flickr"><img alt="Image With Interlace" height="175" src="http://farm4.static.flickr.com/3443/3908421194_4e021c9183_o.png" style="BORDER-BOTTOM: medium none; BORDER-LEFT: medium none; BORDER-TOP: medium none; BORDER-RIGHT: medium none" width="325" /></a></p>
<p>It&#39;s incredibly visually distracting. So now I&#39;m going to have to go back and re-encode the video with de-interlacing enabled. I thought it might be useful to share this knowledge and show people what switches I&#39;m using to drive my encoding, in case they want to do the same thing for themselves.</p>
<p>I use the following command line switches for handbrakecli.exe:</p>
<blockquote dir="ltr"><pre>-i &quot;InputSource&quot;</pre>
<blockquote dir="ltr">
<p>This is the input filename or input source (you can point at the VIDEO_DS folder of a DVD to use the DVD as your source). If you&#39;re using a DVD, you should use&#0160;</p></blockquote><pre>-o &quot;OutputFilename.m4v&quot;</pre>
<blockquote dir="ltr">
<p>This is the output filename. Handbrake makes MPEG-4 videos.</p></blockquote><pre>-t title#<br />-l</pre>
<blockquote dir="ltr">
<p>If your input source is a DVD, you can use &quot;-t #&quot; to specify the title number on the DVD to encode, or use &quot;-l&quot; which says &quot;auto-select the longest title&quot;. If the source is not a DVD (i.e., it&#39;s a single video file), then this parameter is not necessary.</p></blockquote><pre>-e x264</pre>
<blockquote dir="ltr">
<p>This tells Handbrake to use the H.264 encoding, using the &quot;x264&quot; encoder. This is the slowest encoder that Handbrake has, but it produces the best quality video with the smallest file size.</p></blockquote><pre>-q 0.59</pre>
<blockquote dir="ltr">
<p>This tells Handbrake what quality level you want. This is the right quality level for the bit-rates supported by all my devices.</p></blockquote><pre>-E faac,ac3 -B 160,auto -R 48,48 -6 dpl2,auto</pre>
<blockquote dir="ltr">
<p>This instructs Handbrake to create two audio tracks for the video file. The first is a 2-channel down-mix, which is used by the iPhone/iPod and Zune. The second is to also include the original AC3 (Dolby Digital) audio track, which will be used for 5.1 surround audio by the Apple TV.</p></blockquote><pre>-a audio#,audio#</pre>
<blockquote dir="ltr">
<p>When a DVD has multiple audio tracks, you can use the -a parameter to specify which one you want to use. It&#39;s duplicated here twice, because you could choose a different audio track for the AAC and AC3 audio tracks; in practice, you will use the same one. If you don&#39;t specify -a, Handbrake chooses the first audio track, which is usually the right choice.</p></blockquote><pre>-X 720 -P<br /></pre>
<blockquote dir="ltr">
<p>This instructs Handbrake to make an appropriately sized video, automatically figuring out if the video is widescreen or not.</p></blockquote><pre>-m</pre>
<blockquote dir="ltr">
<p>This tells Handbrake to make chapter markers in the video for each of the chapters in the video. Usually only useful if you&#39;re encoding a DVD.</p></blockquote><pre>-d slower</pre>
<blockquote dir="ltr">
<p>This is the all-important flag that says to de-interlace with the best quality available.</p></blockquote><pre>-x level=30:cabac=0:ref=3:mixed-refs=1:analyse=all:me=umh:no-fast-pskip=1</pre>
<blockquote>
<p>These are specialized instructions to the x264 encoder. Leave them as they are. :)</p></blockquote></blockquote><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/BradWilson?a=VAstyFplQ7w:9wSdeG9K34Y:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/BradWilson?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/BradWilson?a=VAstyFplQ7w:9wSdeG9K34Y:dnMXMwOfBR0"><img src="http://feeds.feedburner.com/~ff/BradWilson?d=dnMXMwOfBR0" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/BradWilson?a=VAstyFplQ7w:9wSdeG9K34Y:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/BradWilson?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/BradWilson?a=VAstyFplQ7w:9wSdeG9K34Y:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/BradWilson?i=VAstyFplQ7w:9wSdeG9K34Y:V_sGLiPBpWU" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/BradWilson/~4/VAstyFplQ7w" height="1" width="1"/><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?a=n99yxbgQvUE:VAstyFplQ7w:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?a=n99yxbgQvUE:VAstyFplQ7w:dnMXMwOfBR0"><img src="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?d=dnMXMwOfBR0" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?a=n99yxbgQvUE:VAstyFplQ7w:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?a=n99yxbgQvUE:VAstyFplQ7w:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?i=n99yxbgQvUE:VAstyFplQ7w:V_sGLiPBpWU" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/BradWilson-ThenetGuy/~4/n99yxbgQvUE" height="1" width="1"/>]]></content:encoded>


<dc:subject>Movies</dc:subject>
<dc:subject>Television</dc:subject>

<dc:creator>Brad Wilson</dc:creator>
<dc:date>2009-09-10T18:24:57-07:00</dc:date>
<feedburner:origLink>http://bradwilson.typepad.com/blog/2009/09/movie-server-handbrake-and-interlacing.html</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/BradWilson/~3/VAstyFplQ7w/movie-server-handbrake-and-interlacing.html</feedburner:origLink></item>
<item rdf:about="http://bradwilson.typepad.com/blog/2009/08/pauseps1.html">
<title>pause.ps1</title>
<link>http://feedproxy.google.com/~r/BradWilson-ThenetGuy/~3/q_CkJq_2jNw/pauseps1.html</link>
<description>I needed a "pause" command for some of my PowerShell scripts, so this is what I ended up with. Enjoy. param( [string]$message = "Press any key to continue..." ) Write-Host -NoNewLine $Message $Host.UI.RawUI.FlushInputBuffer() do { $key = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown").Character } while...</description>
<content:encoded><![CDATA[<p>I needed a "pause" command for some of my PowerShell scripts, so this is what I ended up with. Enjoy.</p>

<pre class="brush:powershell; gutter:false">param(
  [string]$message = "Press any key to continue..."
)

Write-Host -NoNewLine $Message

$Host.UI.RawUI.FlushInputBuffer()
do { $key = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown").Character } while ([int]$key -eq 0)

Write-Host ""</pre><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/BradWilson?a=aQNV-A3yUBw:PruAfLaGLdI:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/BradWilson?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/BradWilson?a=aQNV-A3yUBw:PruAfLaGLdI:dnMXMwOfBR0"><img src="http://feeds.feedburner.com/~ff/BradWilson?d=dnMXMwOfBR0" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/BradWilson?a=aQNV-A3yUBw:PruAfLaGLdI:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/BradWilson?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/BradWilson?a=aQNV-A3yUBw:PruAfLaGLdI:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/BradWilson?i=aQNV-A3yUBw:PruAfLaGLdI:V_sGLiPBpWU" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/BradWilson/~4/aQNV-A3yUBw" height="1" width="1"/><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?a=q_CkJq_2jNw:aQNV-A3yUBw:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?a=q_CkJq_2jNw:aQNV-A3yUBw:dnMXMwOfBR0"><img src="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?d=dnMXMwOfBR0" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?a=q_CkJq_2jNw:aQNV-A3yUBw:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?a=q_CkJq_2jNw:aQNV-A3yUBw:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?i=q_CkJq_2jNw:aQNV-A3yUBw:V_sGLiPBpWU" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/BradWilson-ThenetGuy/~4/q_CkJq_2jNw" height="1" width="1"/>]]></content:encoded>


<dc:subject>PowerShell</dc:subject>
<dc:subject>Technical</dc:subject>

<dc:creator>Brad Wilson</dc:creator>
<dc:date>2009-08-22T15:43:04-07:00</dc:date>
<feedburner:origLink>http://bradwilson.typepad.com/blog/2009/08/pauseps1.html</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/BradWilson/~3/aQNV-A3yUBw/pauseps1.html</feedburner:origLink></item>
<item rdf:about="http://bradwilson.typepad.com/blog/2009/08/xunitnet-15-beta-released.html">
<title>xUnit.net 1.5 Beta Released</title>
<link>http://feedproxy.google.com/~r/BradWilson-ThenetGuy/~3/u85QJPxiF3c/xunitnet-15-beta-released.html</link>
<description>Jim and I just shipped xUnit.net 1.5 Beta. We're pretty much done with the features for 1.5 at this point. Other than a non-functional recent item list for projects in the GUI, we believe we are feature complete. We will...</description>
<content:encoded><![CDATA[<p><a href="http://jamesnewkirk.typepad.com/">Jim</a> and I just shipped <a href="http://xunit.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=30943">xUnit.net 1.5 Beta</a>.</p>

<p>We're pretty much done with the features for 1.5 at this point. Other than a non-functional recent item list for projects in the GUI, we believe we are feature complete. We will probably be restructuring some of the GUI runner code so that it can have a long and maintainable life. :)</p>

<p>The big new feature for 1.5 Beta is the introduction of xUnit.net Test Project files (.xunit files). These files contain information about multiple assemblies and their run parameters, and can be consumed from the GUI and MSBuild runners (as well as created in the GUI). To accommodate this, the GUI got a small makeover in the menus, and now behaves like a single document application (where the document is your project file). We also support launching .xunit files from Windows Explorer (run the installer utility, xunit.installer.exe, to enable this support).</p>

<p>The other big feature is that we've included builds of the console and GUI runner which always run in 32-bit mode, even on 64-bit OSes. The default versions will run in whatever is native. We also included environment information (32- vs. 64-bit and the .NET version) in several places, including the native XML output files.</p>

<p>Finally, we added preliminary support for&nbsp;<a href="http://www.asp.net/mvc">ASP.NET MVC</a> 2 Preview 1. This support may need to evolve with later releases of MVC.</p>

<p>As always, we look forward to usage reports, especially with the new GUI. Your help lets us know that we're ready to ship!</p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/BradWilson?a=EOtAfRDQCSo:JZEvvdugfmA:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/BradWilson?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/BradWilson?a=EOtAfRDQCSo:JZEvvdugfmA:dnMXMwOfBR0"><img src="http://feeds.feedburner.com/~ff/BradWilson?d=dnMXMwOfBR0" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/BradWilson?a=EOtAfRDQCSo:JZEvvdugfmA:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/BradWilson?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/BradWilson?a=EOtAfRDQCSo:JZEvvdugfmA:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/BradWilson?i=EOtAfRDQCSo:JZEvvdugfmA:V_sGLiPBpWU" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/BradWilson/~4/EOtAfRDQCSo" height="1" width="1"/><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?a=u85QJPxiF3c:EOtAfRDQCSo:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?a=u85QJPxiF3c:EOtAfRDQCSo:dnMXMwOfBR0"><img src="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?d=dnMXMwOfBR0" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?a=u85QJPxiF3c:EOtAfRDQCSo:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?a=u85QJPxiF3c:EOtAfRDQCSo:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/BradWilson-ThenetGuy?i=u85QJPxiF3c:EOtAfRDQCSo:V_sGLiPBpWU" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/BradWilson-ThenetGuy/~4/u85QJPxiF3c" height="1" width="1"/>]]></content:encoded>


<dc:subject>Agile</dc:subject>
<dc:subject>ASP.NET MVC</dc:subject>
<dc:subject>Technical</dc:subject>
<dc:subject>xUnit.net</dc:subject>

<dc:creator>Brad Wilson</dc:creator>
<dc:date>2009-08-08T17:56:02-07:00</dc:date>
<feedburner:origLink>http://bradwilson.typepad.com/blog/2009/08/xunitnet-15-beta-released.html</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/BradWilson/~3/EOtAfRDQCSo/xunitnet-15-beta-released.html</feedburner:origLink></item>


</rdf:RDF><!-- ph=1 --><!-- nhm:dynamic-ssi -->
