home comments edit

Had a bit of a home improvement weekend.

We have these water fountains for the cats - one upstairs, one downstairs. We noticed that the one upstairs was getting filled a lot more often over the course of a week than it had been and figured it was just that the cats were more thirsty or something. No, turns out the fountain was leaking.

The short version is that the carpet was a bit wet and everything was generally OK except for the baseboards near the fountain, which had expanded (yay, pressboard!) and were basically water damaged so we had to replace them.

If you have to replace your baseboards in your house, just assume that Home Depot and Lowes will not have the exact type you have installed. They just won’t. I don’t care if you bought it there last week, that trim is now out of style and you’ll get something really close to what you had, but it won’t be exact. This will cause you to have to replace a bigger section than you really wanted to because they have to match. If you are unlucky, this means the entire room. (We were lucky and only had to replace a small corner by the door.)

Over the course of last week I got the new baseboard painted and got all the tools ready for the weekend job. Saturday my dad came over and showed me how to use the complex miter saw that I inherited a while ago but have basically ignored since I got it. Learning! Anyway, with his help we got the new section up and it looks like new. Actually, slightly better than new because the replacement I bought was the same pattern but a bit thicker and better quality than the baseboards originally in the room.

Of course, neither of us are professionals at this so replacing like four feet of baseboards took something like three hours. No cursing or drinking was involved/required, though. It went smoothly.

After that, my dad and I took a break and played the last few levels of Gears of War 2 on co-op, which was fun, while Jenn and my mom went shopping.

That was Saturday.

Lego Imperial Shuttle

Sunday, other than the little chores that need to get done because you’re lazy about them all week, I finally got the opportunity to sit down with my new Lego set that I got thanks to the tax return. It’s a big 2503-piece behemoth Star Wars ship. (My favorite ship, in fact, from the Star Wars universe, which is why I bought it.) Phillips Double Chocolate Porter, my recently-acquired Reboot DVDs, and Legos. That’s a recipe for a nice afternoon, right there.

The Lego set has four separate instruction manuals. I only really got through the first 2/3 of the first manual in a couple of hours, so it looks like this will be a long project, which is fine. I like building Legos. It’s like putting together a super cool 3D puzzle. I’m recording it with our video camera so I can make a time-lapse video of the construction.

Slightly related: At the same time I bought the new baseboards, I also bought the crown moulding for the bathroom that we painted back in 2004. At the time we totally intended to put up crown moulding and then somehow it never happened. We didn’t have a saw, we didn’t have time, we didn’t have inclination. Well, now that I have the saw, I know how to use it, and I’m already in that DIY mode, I figure it’s time. I’ve got the boards, they’re painted, they just need to be cut and put up.

dotnet, coderush, aspnet comments edit

I’m a huge CodeRush and Refactor user and DevExpress fan, but my day job is developing web sites so I thought I’d give the DevExpress MVC Extensions a run to see how they work.

The DevExpress MVC Extensions are sort of like web controls - like HtmlHelper methods combined with some client-side script - that allow you to easily provide rich client-side widgetry in your MVC applications. I’m always interested in easy ways to provide a nice experience, so this sounds pretty good to me.

The first thing I noticed, even before I got a chance to use the extensions, was the seamless install process. I had already installed CodeRush/Refactor using the separate DevExpress IDE Tools installer, but when I ran the full DX Universal installer it totally picked up that I had some components installed and went to a “Modify” operation rather than not seeing the previously installed tools and telling me to re-install. I had actually built up in my head that I was going to have trouble with this, but it was totally cool. It’s the little things, right?

After installing, I decided to start up a new project to test things out in. There is an article on DevExpress that explains how to integrate with your existing site, but I really wanted to start a clean project to mess around in. The article explaining how to integrate with an existing project is, admittedly, a little intimidating. Much is just one-time setup, adding assembly references and so forth, but it’s not a short list of steps. Luckily, for new projects, DevExpress adds some project templates that allow you to start up with everything pre-wired.

[New Project dialog with DevExpress project templates. Click to
enlarge.

The project template generates something very similar to the standard MVC3 project, with a few placeholder items like the HomeController and Index views.

Default project structure for DevExpress MVC3
project.

You’ll also see several references to the DevExpress assemblies.

DevExpress assembly references in the MVC3
project.

If you look at the Home/Index view, there’s really nothing interesting there. What’s interesting is in the Site.Master, where you’ll see the stylesheet and script references that were added for the MVC extensions.

[Site.Master code generated by DevExpress template. Click to
enlarge.

When you fire up the site, the initial view (Home/Index) really doesn’t have anything on it - it’s a blank slate.

Initial view of DevExpress MVC3
project.

This, though, is where the fun begins.

First, let’s look at how the references in the Site.Master translate to rendered code:

[Initial script references. Click to
enlarge.

As you can see, there’s some script and CSS combining going on, so you only have one file transfer for script and one for CSS when you add the extensions. The default set of script/CSS provided a ~350KB script (a gzipped version of 1.5MB script) and a ~27KB CSS file (a gzipped version of a 278KB CSS file). Note that the script/CSS is only zipped, not minified, so I think there’s an opportunity for DevExpress to reduce the overhead further.

Now that we have a basic project skeleton in order, I figured I would do something slightly more robust than a standard “Hello World” to test these out. A simple contact list sounds like a reasonably simple, yet more than “Hello World,” solution, so that’s what I went for.

I’m going to yada yada over some of the details of putting the scaffolding in place because that part’s not interesting. Basically I added a one-table database with a Person object that has first and last name (strings), birthdate (DateTime), and a biography (HTML). (Here’s the metadata buddy class.)

using System;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;

namespace DevExpressMvcApplication1.Models
{
  [MetadataType(typeof(PersonMetadata))]
  public partial class Person
  {
    public class PersonMetadata
    {
      [Required]
      [StringLength(50)]
      [DisplayName("First Name")]
      public object FirstName { get; set; }

      [Required]
      [StringLength(50)]
      [DisplayName("Last Name")]
      public object LastName { get; set; }

      [Required]
      [DataType(DataType.Date)]
      public object Birthdate { get; set; }

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

…as well as the controller actions and views for simple list/create/details/edit/delete operations.

First, the list view. For that, I exercised the GridView extension.

The GridView extension is an AJAX grid that appears to be an MVC-friendly wrapper around the extraordinarily robust ASPxGridView control. Adding a GridView via the extension has basically four steps:

  1. Add a partial view that contains the grid proper.
  2. In the main view, render the partial view with your grid.
  3. Add a controller action that returns just the grid partial view.
  4. In the grid definition, indicate which action renders your grid partial view so sort operations, etc., can do the appropriate callback.

I threw a couple of test people into my database and ran it. Here’s what I came out with:

Default GridView with no
enhancements.

That’s not too shabby for like two minutes’ worth of work. Clicking the little arrow or a different header changes the sort order/column as expected. Each click calls the controller action that returns the partial view, so it’s working a little like an UpdatePanel control in ASP.NET - rather than getting the data as JSON and client-side binding, the whole view is returned and replaces the grid.

That default grid is with a pretty minimal configuration:

<%
Html.DevExpress().GridView(
  settings =>
  {
    settings.Name = "indexList";
    settings.CallbackRouteValues = new { Controller = "Person", Action = "IndexListView" };
    settings.Width = 450;
    settings.Columns.Add("LastName").SortOrder = DevExpress.Data.ColumnSortOrder.Ascending;
    settings.Columns.Add("FirstName");
  })
  .Bind(Model)
  .Render();
%>

That Html.DevExpress() bit is common for the MVC Extensions - that’s how you access the DevExpress functionality. After that, you can see a pretty simple settings structure that shows the client ID of the tablet that will be generated, the callback info for the partial view rendering action, and info on which columns are displayed.

Something I thought interesting was that the sort order is managed entirely by the grid. When the partial view action gets called, you just hand the view the raw data and the grid deals with sorting it. I’m not sure how I feel about that. On the one hand, it’s nice to not have to worry about it and fiddle with it in my controller action; on the other hand, it’s sort of abstracted away, so if I want to do something different if a specific column is sorted or whatever, I’m into a more web forms style programming model where I’m handling events like DataBound.

Another thing I noticed was in looking at the column headers. The ALT text on the sort direction arrows was inserted for me, which is nice, but I couldn’t figure out how I’d localize that text.

<td style="width:100%;">Last Name</td><td style="padding-left:5px;"><img class="dxGridView_gvHeaderSortUp" src="/DXR.axd?r=1_3-uURn2" alt="(Ascending)" style="border-width:0px;" /></td>

I admittedly didn’t put a load of time into researching it, and with a settings object that has ~60 properties, I’m sure it’s possible… but I could spend all day on this thing and there is more stuff to look at, so I didn’t dwell on it. It did occur to me that with so many settings, there’s probably a heck of a learning curve figuring out what all of them do and when you’d use each one. Not a bad thing, just something to be aware of.

OK, so we have a grid. Let’s put some links to get to the “delete” and “details” views on people. I’ll make the last name column clickable so you can get to the details view from there. Doing this is simple if you know how, but it took me a while to figure it out. Again, we get a small taste of web forms style programming by setting column template contents using DataBinder.Eval and so forth. Not bad, just slightly different than that bare-metal-HTML feel you might be used to in MVC view creation. Same thing with adding a little delete link column - reasonably simple. Here’s the code we end up with…

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<IEnumerable<Person>>" %>
<%
  Html.DevExpress().GridView(
    settings =>
    {
      settings.Name = "indexList";
      settings.CallbackRouteValues = new { Controller = "Person", Action = "IndexListView" };
      var deleteColumn = settings.Columns.Add("", "");
      deleteColumn.HeaderStyle.HorizontalAlign = HorizontalAlign.Center;
      deleteColumn.CellStyle.HorizontalAlign = HorizontalAlign.Center;
      deleteColumn.SetDataItemTemplateContent(c =>
        {%>
        <a href="<%: Url.Action("Delete", new { Id = DataBinder.Eval(c.DataItem, "Id") }) %>">
          <img src="<%: Url.Content("~/Content/Delete.png") %>" alt="Delete" style="border: none;" />
        </a>
        <%});
      var lastNameColumn = settings.Columns.Add("LastName");
      lastNameColumn.SortOrder = DevExpress.Data.ColumnSortOrder.Ascending;
      lastNameColumn.SetDataItemTemplateContent(c =>
        {%>
        <%= Html.ActionLink(
            DataBinder.Eval(c.DataItem, "LastName").ToString(),
            "Details",
            new { Id = DataBinder.Eval(c.DataItem, "Id") })
        %>
        <%});
      settings.Columns.Add("FirstName");
    })
    .Bind(Model)
    .Render();
%>

…and here’s the resulting grid:

GridView with delete and details
links.

Nice. Now, you probably have two questions about this:

  1. Could I have accomplished this just using an HTML table and some foreach looping? Sure, but what I get by using the extension is the sorting, AJAX loading, and additional flexibility that the logic inside the GridView brings. It comes with a bit of a price in that you do dip your toe back in the web forms waters, so whether it’s appropriate for you will be a balance between your desire to remain pure and your desire for packaged super-functionality.
  2. Could I have added inline editing and deleting? Yes, I could have done everything right in the grid, adding editing templates and delete confirmations and all that right there. That might even have been a nicer user experience. On the other hand, it would have effectively sidestepped my experimentation with the rest of the controls, which is sort of the point here, so I’m doing things the long way.

Anyway, GridView is pretty slick and far beyond what I’d normally term “robust.” A little web-forms-ish, but if you’re trying to package up this kind of logic in some sort of reusable format, I’m not sure how else you’d do it. It also has a non-trivial learning curve, but wow, does it have features layered on features. Enough so it’s really difficult to even give it a fair evaluation because you’d spend weeks delving into it. Check out some of the demos on the DevExpress site to see the features I didn’t get into. What’s more robust than robust? Now you have the answer: the DevExpress MVC extensions GridView.

Now that we have the delete and edit links in place, let’s wire things up. There’s not a lot of interesting anything going on with the delete view, so I’m not going to go there. The good stuff is in the details and edit views, so let’s dig into those.

I’m a big fan of the DataAnnotations support in MVC and the whole Html.DisplayFor() method of displaying and editing models, so I figured I’d create a display and edit template for our Person model.

Easy enough to add a quick partial view in the DisplayTemplates folder for handling my Person model, but even with the option to scaffold some default details HTML in there to display the various fields, we can clean it up a bit. Let’s try the Rounded Panel extension to add just a little flair for fun. A quick bit of code in DisplayTemplates/Person.ascx…

<%
  Html.DevExpress().RoundPanel(
    settings =>
    {
      settings.Name = "personDetails";
      settings.HeaderText = String.Format("{0} {1}", this.Model.FirstName, this.Model.LastName);
      settings.ShowHeader = true;
      settings.View = DevExpress.Web.ASPxRoundPanel.View.Standard;
      settings.Width = 315;
      settings.SetContent(() =>
      {%>
        <div class="display-label">Birthdate</div>
        <div class="display-field"><%: String.Format("{0:d}", Model.Birthdate) %></div>
        <div class="display-label">Biography</div>
        <div class="display-field"><%= Model.Biography %></div>
      <%});
    })
    .Render();
%>

…and we have a nice little view:

Details view with a
RoundPanel.

It was at this point I decided I wanted to do some styling. For example, I wanted to make the person’s name in the header be bold and maybe a little larger. Simply throwing a CSS class on the header didn’t seem to fix it, though, since the HTML that the rounded panel generates is… a bit more complex than you might think.

Styling the MVC extensions is somewhat unintuitive and is a more involved process than you realize. The way you’re supposed to do what I want to do is to use the theme deployer tool to manually deploy the CSS used to style these controls (which is normally stored as embedded resources in an assembly) and then manually tweak the deployed files. I put out a call for help on this in the forums which confirmed this. It feels like overkill when I just want to style a single element. It also implies that these controls will probably not work easily with other styling tools like jQuery ThemeRoller (though, admittedly, I didn’t try). Note that in the forum response, they did mention they’re working on an easier way to do this.

OK, so, moving on. We have our details view, it’s in a nice RoundPanel, let’s create an editor view. I threw a link on the details page so we can get to the edit view, then added a simple editor template and view. It all starts out looking like this:

Default edit view. Not very
pretty.

Well, that’s not very pretty, so let’s add a little model metadata to clean up the display information and throw a RoundPanel around it to make it at least a bit consistent with the details view.

Edit view with a RoundPanel. Better, but still not
done.

Better, but not done. To make date editing nicer, I figured I’d try out the Date Edit MVC Extension. This is a nice date picker control that has a very good user experience. You can type the date in, pick it from a calendar, allow for character masking… it’s really pretty sweet. Definitely check out the demo on the DevExpress site on this one because there’s no way I can exercise it all right here.

Anyway, easiest way to get dates all editing the same way is to add an editor template for dates to my project, so that’s what I’ll do. I created a Shared/EditorTemplates folder and a DateTime.ascx control that has the following code in it:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<System.DateTime?>" %>
<%
  Html.DevExpress().DateEdit(
    settings =>
    {
      settings.Name = this.ViewData.ModelMetadata.PropertyName;
      settings.Properties.NullText = "MM/dd/yyyy";
      settings.Properties.EditFormat = EditFormat.Date;
      if (this.Model.HasValue)
      {
        settings.Date = this.Model.Value;
      }
    }
  )
  .Render();
%>

That ends up rendering the date picker like this, so you can click the dropdown arrow and get the calendar:

DevExpress date picker.
SHINY.

Niiiiice.

Adding date editing with the Date Edit extension was super simple. Really, the only challenging bit about it was setting the “Name” property since you have to do that manually rather than letting the framework infer it for you. This is an easy way of getting a nice, robust date picking/editing user experience into your site.

Good, so we have date editing covered for the birthdate field, let’s deal with editing the biography field. For this one, I want to have a nice, rich HTML editor so the biography can be formatted and not just text. (Yes, in real life this would open us up to XSS attacks, but we’re demoing here, so we’re not really focusing on security.)

The MVC extensions come witha super-rich HTML editor, so I figured I’d use that. Same drill as with the date editor - a new EditorTemplate for HTML data.

Except… looking at the HTML editor, it’s not quite as drop-in-and-go as all that. It’s closer to the GridView in setup, with a need for various callback actions and so forth. The key here is to start with the documentation rather than the demo code since the documentation provides a much simpler starting point that allows you to skip the extra bells and whistles and add them on later.

First thing I did was to add an Html.ascx in my Shared/EditorTemplates folder that will serve as the template for editing HTML fields. Inside that editor template, I added the call to Html.RenderPartial as outlined in the documentation.

Note: In setting this up, I encountered early on that due to the need to render a partial view from a partial view, when the HTML editor posts to the server to get an updated view you lose your model metadata. That means you have to propagate things like the model property name manually, and it’s sort of painful. You’ll see where I add in some ViewData settings and such to accommodate this.

So, the HTML editor template looks like this:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<System.String>" %>
<%
  this.ViewData["PropertyName"] = this.ViewData.ModelMetadata.PropertyName;
  Html.RenderPartial("HtmlEditorPartial");
%>

That’s not a very exciting view, but what it does is gets our editor template in place. Then I added a new partial view in the Shared folder called HtmlEditorPartial.ascx. That partial view is where I render the actual HTML editor.

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<System.String>" %>
<%
  var propertyName = this.ViewData["PropertyName"].ToString();
  Html.DevExpress().HtmlEditor(
    settings =>
    {
      settings.Name = propertyName;
      settings.CallbackRouteValues = new { Controller = "HtmlEditor", Action = "HtmlEditorPart", PropertyName = propertyName };
      if (this.Model != null)
      {
        settings.Html = this.Model;
      }
    })
    .Render();
%>
<input type="hidden" name="<%= this.ViewData["PropertyName"].ToString() %>" />

Again, note how I’m getting the model metadata property name from a ViewData value I set manually. You have to do this due to the indirect partial-rendering-partial callback that goes on, and you have to keep that available.

I’ll explain that extra hidden field later. It has to do with a challenge I found around model binding. Anyway…

The last thing I did was add a controller that will handle the callbacks from the HTML editor. I called it HtmlEditorController and there’s only one action on it - HtmlEditorPart, which renders the editor’s partial view.

using System;
using System.Web.Mvc;

namespace DevExpressMvcApplication1.Controllers
{
  public class HtmlEditorController : Controller
  {
    public ActionResult HtmlEditorPart(string propertyName)
    {
      this.ViewData["PropertyName"] = propertyName;
      return PartialView("HtmlEditorPartial");
    }
  }
}

It was at this point I got stuck.

Even though I was setting the Name property on the HTML editor correctly (to, in this case, “Biography”), when I’d get the postback I’d have a ton of fields that all start with “Biography” (like “Biography_CurDialog,” “Biography_TD_T0CI,” “Biography$TD$T1$ITCNT0$ctl00,” and so on) but no actual field called “Biography” would come back in the POST. If you’re trying to get this to work with model binding, that’s sort of a showstopper. I posted a question to the forums and got pointed to an example that shows how to get the HTML back out of the editor - you need to use a special HtmlEditorExtension.GetHtml() method. That sort of throws a wrench in the works as far as model binding is concerned because it means I would have to manually extract the value in some sort of a controller action. Given the way EditorTemplates work, partial views and whatnot, that’s not so easy. (A later response pointed me to a class called DevExpressEditorsBinder that is used for binding data coming from other editor controls, but apparently it’s not yet updated to work with the HTML editor.)

I tried adding a custom model binder for HTML data types, but the problem you run into is that the HTML editor still doesn’t post a value with the right name so when model binding runs, it doesn’t see a field matching the name of the property (“Biography”) and doesn’t even run the binder. The way I ended up working around this is to add a hidden input field with an empty value to the HTML editor partial view and give that input field the name of the HTML editor. (That’s why you see it in the partial view earlier.) Since the HTML editor doesn’t generate any input field with that name, there’s no overlap, and it makes it so something with the appropriate property name gets posted back and model binding will run. Then I added a custom model binder that verifies the data type of the field being parsed and if it’s HTML, it uses that GetHtml method I mentioned earlier.

using System;
using System.Web.Mvc;
using DevExpress.Web.Mvc;

namespace DevExpressMvcApplication1
{
  public class HtmlModelBinder : IModelBinder
  {
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
      if (bindingContext.ModelMetadata.DataTypeName == "Html")
      {
        return HtmlEditorExtension.GetHtml(bindingContext.ModelName);
      }
      else
      {
        return ModelBinders.Binders.DefaultBinder.BindModel(controllerContext, bindingContext);
      }
    }
  }
}

You have to register that model binder at application startup for the System.String datatype so it’ll fire.

ModelBinders.Binders.Add(typeof(string), new HtmlModelBinder());

Now any string property marked with [DataType(DataType.Html)] will go through the appropriate model binder and have the HTML properly pulled out of the HTML editor control.

That was a little painful and not straightforward. I think the HTML editor is pretty cool, but I feel like I jumped through a few hoops on that one. Maybe this isn’t the primary use case for it or something.

The last thing I wanted to try was adding model validation in. This article’s running a bit on the long side already so I’ll cut right to it:

  • I wasn’t able to get the jQuery validation working. I fought with it for about an hour, but simply setting the web.config parameters and/or setting Html.EnableClientValidation() didn’t do it. The form always seemed to post, regardless of the validity of the fields, though the server would properly see model validation was incorrect. I ended up adding the original MicrosoftMvcValidation.js style validation back in and disabling the jQuery validation and that worked.
  • Thedemo showing validation using the MVC extensionssays it’s using standard DataAnnotations model validation but when you look at the demo code, it’s doing some really crazy custom stuff. (It appears the demos for the custom DevExpress validation and the DataAnnotations validation are the same.) I did not want to spend a ton of time on this but I have a feeling there was something I wasn’t wiring up properly, or that maybe there’s some flag or setting I wasn’t wiring up right.
  • Validation with the date picker was effortless. It validates just like a text box, no problems. I didn’t have to wire anything special up.
  • I didn’t try validation with the HTML editor. After working through the model binding issue, I didn’t want to get into the validation thing. It may have been easy, but somehow I’m thinking I’d have gotten into writing custom client-side adapters or trying to mix the DevExpress validation in with the DataAnnotations validation, which doesn’t sound like a five minute task.

So, given all that, the results of my spike with the DevExpress MVC Extensions:

  • They look really nice. Out of the box, the styles are really nice so it makes it simple to add some quick hotness to your site.
  • Custom styling isn’t fall-down easy. The controls can get a little complex so you do need to look at using the DevExpress themes that ship with the extensions, possibly with customizations. You probably won’t be able to get by just throwing a couple of quick overrides in a separate CSS file, and it may be a challenge to figure out what to change to achieve the results you want.
  • Simple use cases are a breeze. It was easy to sub the date picker in as my date editor and just as easy to get validation working in it.
  • Damn, I love that date picker. I just wanted to throw that in there again. I’d almost buy the package just for that really nice date picker.
  • The complex controls are very full-featured but can be complex to work with. The GridView and HTML editor have a ton of fantastic features, but they’re not really fall-down simple to work with. While there are a lot of demos, figuring out what each line in the demo does and whether or not it’s something you’re interested in doing in your own code is a challenge. The documentation is reasonable from an API standpoint but there could probably stand to be a bit more “how to” style docs. Not just demos, but more explanation of the various features, what they do, and how you use them. Model binding, as you saw, was also a challenge in the more complex controls (HTML editor), though hopefully that will get easier as new versions are released.
  • There’s still a touch of web forms in places. For example, the GridView exposing data binding events, working with DataBinder.Eval, and so forth, felt pretty web forms to me. I’m not sure what I’d like to see instead, but you’ve probably read in places that “data binding in MVC is a foreach loop” - it might be nice to see something closer to that level of simplicity.
  • Callback partial views can throw a wrench in the works. The GridView and HTML editor, being AJAX-y controls, need partial views that they can call back to and update their content. You saw how this made using the HTML editor a bit of a challenge in an EditorTemplate. I can see that it may get a little less than straightforward in other areas, too.
  • DevExpress support is awesome. I’ve had a great experience working with the DevExpress folks - community, tech support, devs - throughout my relationship with them using CodeRush and Refactor, and using the MVC Extensions is no different. You get quick answers in the forums, they’re receptive to input (they even filed an enhancement request based on my forum post!)… honestly, there are a small handful of companies that are a joy to work with like this. That counts for a lot.

Anyway, that was a bit longer than I thought it was going to turn out… but hopefully that helps you on your way to cooler web sites.

personal, process comments edit

If you’re writing a programming article or an email to your team, many times you’ll probably try to provide an example code snippet to illustrate the point you’re trying to make. The problem is, regardless of the example, you will most likely fall into one of these losing traps:

The Prose Example

This example is where you try to describe the code in a paragraph like this one, in natural language.

When registering a component for dependency injection, be aware of the lifetime you choose for the component. Choosing the wrong lifetime may mean the component lives longer than you intend. For example, if you have a component that keeps state information based on the current incoming request, you don’t want to keep it around as a singleton.

The trap here is that many people stop reading about five words in and don’t pay attention to what you’re trying to say. TL;DR. Even if the example you’re trying to explain requires some additional detail, attention spans wane and… you’re not even reading this anymore, are you?

The FooBar Example

This example is intentionally obscured from a naming perspective so that people ignore the names and focus on what the code is actually doing. The names “foo” and “bar” are commonly used as placeholders. For example, if you wanted to demonstrate automatically implemented properties in C#, you might show a class like this:

public class Foo
{
  public string Bar { get; set; }
}

It’s shorter and more direct than prose, which will keep those ADD engineers at bay… but the trap with this one is that you’ll get people who can’t work through the concepts because of the ambiguous naming, or they can’t figure out where the concept applies because the example was not concrete enough to make sense.

To address this, you get into…

The Imprecise Concrete Example

This is when you want to show a quick example of something but you don’t want people to get hung up on the names for things. The implementation really isn’t important, it’s just an example. Like if you wanted to demonstrate numeric parsing…

public class Address
{
  public int PostalCode { get; private set; }

  public void ParseAndSetPostalCode(string input)
  {
    this.PostalCode = Int32.Parse(input);
  }
}

The good part is that it’s more concrete, so the folks who couldn’t figure out the Foobar example can see where a concept might be used. On the other hand, with imprecise examples you inevitably get trapped by people complaining about the design of the code. “Are you sure you wouldn’t want to check for null first? What if the input isn’t a numeric string?”

You see this a lot with some of the quick demos given at presentations - the code isn’t 100% complete and tested (because it’s a demo) but people do the Monday-morning-quarterback thing and wonder why that wasn’t included.

So, that leads you to…

The Precise Concrete Example

This type of example is when you provide some code where all the details are there. It addresses the shortcomings in the imprecise example, but comes with it’s own issues. Like if you were demonstrating how one might use ACLs in the filesystem…

using System;
using System.IO;
using System.Security.AccessControl;

namespace SomeNamespace
{
  public static class FileInfoExtensions
  {
    public static void AllowFullControl(this FileInfo file, string username)
    {
      if (file == null)
      {
        throw new ArgumentNullException("file");
      }
      if (username == null)
      {
        throw new ArgumentNullException("username");
      }
      if (username.Length == 0)
      {
        throw new ArgumentException("Username may not be empty.", "username");
      }
      if (!file.Exists)
      {
        throw new FileNotFoundException(String.Format("Unable to find file {0}", file.FullName), file.FullName);
      }
      var acl = file.GetAccessControl();
      var rule = new FileSystemAccessRule(username, FileSystemRights.FullControl, AccessControlType.Allow);
      acl.AddAccessRule(rule);
      file.SetAccessControl(acl);
    }
  }
}

There are actually three problems with this one.

First, the whole concept you were trying to illustrate is now lost in details. People have stopped looking at the conceptual/high-level thing you were providing an example of and now they’re focused on your error checking and code format. Along with this, these examples are usually sort of long, so you run into the prose example problem again

Second, and related to that first issue, these examples totally open the door tonitpickers (a la Raymond Chen). “Your string formatting wasn’t culture sensitive and you didn’t localize the exception message!”

Finally, you get peoplecopy/pasting the code as though it’s production-ready without bothering to see if it does everything they need it to do, sometimes without even testing the code.

HOW DO YOU ESCAPE THE TRAPS?

The root of the problem is that people learn in different ways. Some people need that prose example or the Foobar example so they can focus on the concept rather than the details; others need more precise examples so they can see how things actually work in a more “real-world” environment.

There is a two-part solution to this, and it requires cooperation on everyone’s part.

For the people providing examples: Provide multiple examples of the same concept but using different styles. Describe in prose what you’re going to demonstrate and then give a precise concrete example. Or give an imprecise concrete example and clarify it in prose with maybe another example in the Foobar format. The idea here is that between two or more examples, at least one will make sense to folks, or they’ll be able to put concepts from the different examples together to make a complete picture.

The drawback to having multiple examples is that it is longer, so you’ll want to put the shortest bits first to draw the attention in and convey the most info you can up front. This is similar to the pyramid structure used when people write news stories.

For the people reading examples: Don’t get stuck in the details. There is an unspoken contract between folks reading an example and folks presenting examples. When a person is trying to convey some information to you in a succinct fashion, they have to trim things down for time or readability. As the recipient of that information, you need to understand and agree to that. If you get stuck on naming or nitpicking, stop for a second and realize you’re missing the point. If the example is talking about file permissions and there’s a missing null check, don’t worry about it unless you think it actually fundamentally affects your understanding of the example. Feel free to ask questions, but before you do, ask yourself if the question is constructive or would help you understand better… or if you’re just trying to be right about something.

WHAT OTHER TRAPS ARE THERE?

Did I miss an example trap? Ideas on how to provide better examples? Leave a comment!

dotnet, web, vs comments edit

When you install IIS Express it also installs a self-signed certificate that it will use for SSL. This is not normally a problem, however, if you already have a self-signed certificate, it may result in a confusing issue where you have two certificates with the same distinguished name, like so:

Duplicate certificates with
CN=localhost

And why would that be a problem? Say you are working with WCF services that need to identify themselves with certificates. You have your dev machine set up to use the self-signed certificate, like so:

<serviceCredentials>
  <serviceCertificate
    x509FindType="FindBySubjectDistinguishedName"
    findValue="CN=localhost"
    storeLocation="LocalMachine"
    storeName="My" />
</serviceCredentials>

Now when you go visit your service, the channel is always faulted. Why? If you turn up the WCF end-to-end logging, you’ll see the following exception:

System.ServiceModel.ServiceActivationException: The service ‘/YourServiceHere.svc’ cannot be activated due to an exception during compilation. The exception message is: Found multiple X.509 certificates using the following search criteria: StoreName ‘My’, StoreLocation ‘LocalMachine’, FindType ‘FindBySubjectDistinguishedName’, FindValue ‘CN=localhost’. Provide a more specific find value.

Basically - Ambiguous match. Be more precise.

There is an article explaining how to use a custom SSL certificate with IIS Express that involves removing the SSL endpoint and re-creating it with the appropriate cert. Your other option, and the one I’m going with, is to identify the certificate for WCF by certificate thumbprint rather than distinguished name.

<serviceCredentials>
  <serviceCertificate
    x509FindType="FindByThumbprint"
    findValue="1234567890123456789012345678901234567890"
    storeLocation="LocalMachine"
    storeName="My" />
</serviceCredentials>

Far less human readable, to be sure, but more precise and totally unambiguous. Of course, if you’re on a development team, it means everyone needs to have the same dev certificates installed. Tradeoffs, tradeoffs.

This one took me a while to figure out and caused “Hulk Smash!” style rage during the search. Hopefully I can save you the same.