Of Image Exif, PropertyItem and reflection

As documented here on MSDN the PropertyItem object does not have a public constructor.

What to do then when you want to add a property to an image, using Image.SetPropertyItem(..) method?

This post suggests you create some bank of all property items you want, hold it memory and clone from it.

A commenter on that blog suggested using reflection: Get the non-public parameter-less constructor and invoke it. Notable downside for this approach is reliance on internal implementation of the object. True. I'll risk it though.

In my implementation, I added a helper method which simply generates the PropertyItem using System.Activator like so:

public static PropertyItem CreatePropertyItem(int id, int length, short exifType, byte[] buffer)
{
    var instance = (PropertyItem)Activator.CreateInstance(typeof(PropertyItem), true);
    instance.Id = id;
    instance.Len = length;
    instance.Type = exifType;
    instance.Value = buffer;
 
    return instance;
}

Pretty clean and simple. Under the covers, Activator will use some reflection to create the instance, but would also utilize some caching and speed written by not-me. I like not-me code because it means I don't have to write it.

Since one of my my upcoming talks at http://socalcodecamp.com is on the subject of reflection, this all falls neatly into place.



  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Json serialization – RPC style in MVC

In a previous posting, I discussed replacing the stock MVC serializer used for the JsonResult exposed when you use the controller method Json(..) instead of View.

This was all find and dandy. But how – you may wonder – can I call actions that contain complex parameters? Do I need a special binder? Should I write my own?

The answer is mostly "no". As Phil Hack blogged, the ASP.NET MVC framework already contains value providers that take care of that for you. All you need to do is ensure that your Javascript calls your action using some very specific header and mime types.

Here is a function that may help you

   1: <script type="text/javascript">
   2:        var postToAction = function (sender) {
   3:            var json = $('textarea#' + sender.data).val();
   4:            $("textarea#myResponse").val('working...');
   5:             $.ajax({
   6:                 url: document.location.href,
   7:                 type: 'POST',
   8:                 dataType: 'json',
   9:                 data: json,
  10:                 contentType: 'application/json; charset=utf-8',
  11:                 success: function (data) {
  12:                     var replyText = JSON.stringify(data);
  13:                     $("textarea#myResponse").val(replyText);
  14:                 }
  15:             });
  16:         };
  17:     </script>

The special sauce here is the dataType and contentType together with the POST method. The rest is pretty much how jQuery wants to be called.

On line 6 you will note that I'm POSTing to the same URL as the browser is on – you may want to fiddle with that.

We  call this function by hooking up a button, something like:

   1: $("button#myButtonId").click('myTextAreaWithJsonContent', postToAction);

In your own implementation you will no doubt compose some object in JavaScript, or create a Json object. In the code above, I'm simply using Json formatted string: Line 3 gets the value from a text area element. If you compose a complex object and want to send it, you will need to convert it into a Json string. jQuery 1.5.1 – which I happen to use – already contains this facility, JSON.stringify(x) would do the trick. You can see it here used  on line 12, for the inbound response which I simply stringify and hydrate a response text area. But this is only demo code – you will wire up the success (and failure function- right?) to your own logic.

But back to the core issue: Yes, MVC supports submitting Json and hydrating my controller action, but how do I persuade it to use my custom chosen super duper serializer rather than the stock one?

The answer is: Create a custom ValueProviderFactory and instantiate your favorite serializer in there. A bit of inspection on the MVC source code on CodePlex.com reveals the stock implementation.

Here's a modified version, which isolates the serialization in a clear way:

   1: public class MyJsonValueProviderFactory : ValueProviderFactory
   2: {
   3:     public override IValueProvider GetValueProvider(ControllerContext controllerContext)
   4:     {
   5:         if (controllerContext == null)
   6:         {
   7:             throw new ArgumentNullException("controllerContext");
   8:         }
   9:  
  10:         if (!controllerContext.HttpContext.Request.ContentType.StartsWith(
  11:                 "application/json", StringComparison.OrdinalIgnoreCase))
  12:         {
  13:             return null;
  14:         }
  15:  
  16:  
  17:         object value = Deserialize(controllerContext.RequestContext.HttpContext.Request.InputStream);
  18:  
  19:         if (value == null)
  20:         {
  21:             return null;
  22:         }
  23:  
  24:         var bag = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
  25:  
  26:         PopulateBag(bag, string.Empty, value);
  27:  
  28:         return new DictionaryValueProvider<object>(bag, CultureInfo.CurrentCulture);
  29:     }
  30:  
  31:     private static object Deserialize(Stream stream)
  32:     {
  33:         string str = new StreamReader(stream).ReadToEnd();
  34:  
  35:         if (string.IsNullOrEmpty(str))
  36:         {
  37:             return null;
  38:         }
  39:  
  40:         var serializer = new JavaScriptSerializer(new MySpecialTypeResolver());
  41:  
  42:         return serializer.DeserializeObject(str);
  43:     }
  44:  
  45:     private static void PopulateBag(Dictionary<string, object> bag, string prefix, object source)
  46:     {
  47:         var dictionary = source as IDictionary<string, object>;
  48:         if (dictionary != null)
  49:         {
  50:             foreach (var entry in dictionary)
  51:             {
  52:                 PopulateBag(bag, CreatePropertyPrefix(prefix, entry.Key), entry.Value);
  53:             }
  54:         }
  55:         else
  56:         {
  57:             var list = source as IList;
  58:             if (list != null)
  59:             {
  60:                 for (int i = 0; i < list.Count; i++)
  61:                 {
  62:                     PopulateBag(bag, CreateArrayItemPrefix(prefix, i), list[i]);
  63:                 }
  64:             }
  65:             else
  66:             {
  67:                 bag[prefix] = source;
  68:             }
  69:         }
  70:     }
  71:  
  72:     private static string CreatePropertyPrefix(string prefix, string propertyName)
  73:     {
  74:         if (!string.IsNullOrEmpty(prefix))
  75:         {
  76:             return (prefix + "." + propertyName);
  77:         }
  78:         return propertyName;
  79:     }
  80:  
  81:     private static string CreateArrayItemPrefix(string prefix, int index)
  82:     {
  83:         return (prefix + "[" + index.ToString(CultureInfo.InvariantCulture) + "]");
  84:     }
  85: }

It all really boils down to the same ceremony as the default implementation, except on line 40 and 42 we now get to use our own special serializer. Woot!

To use this instead of the built in one, you will modify your global.asax.cs Application_Start() to include something like

   1: var existing = ValueProviderFactories.Factories.FirstOrDefault(f => f is JsonValueProviderFactory);
   2: if (existing != null)
   3: {
   4:     ValueProviderFactories.Factories.Remove(existing);
   5: }
   6: ValueProviderFactories.Factories.Add(new MyJsonValueProviderFactory());

where the built in one gets removed and my custom one gets added. Pretty straightforward.

With this technique and the one described in my previous post, you are ready to use the full power of MVC as an API supporting a nice strongly typed parameter for the back end developer and supporting fully customizable JSON in and out of methods. No real need for other frameworks or technologies for the serving jQuery needs.

Depending on your methods, you may even get away with one set of actions serving both form posts and jQuery invocation.

Happy coding!



  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

JSON serialization problems and solution in MVC3

For various reasons you may find that the default JsonResult returned by invoking the controller method such as

return Json([data);

Is unsuitable for the consumer. The main issue most often encountered is that this method uses the JsonResult which in turn uses the JavaScriptSerializer with no access to the JavaScriptTypeResolver.

This means that you can provide that serializer a parameter specifying you own custom type resolver.

Other issues, such as maximum recursion depth and maximum length and type resolvers can be simply configured in web.config. See  Configuring JSON Serialization section on MSDN.

Back to the core problem though.

To override the JsonResult, we would need to do 2 things:

1) Create our own custom JsonResult implementation

2) Tell the controller to use ours rather than the stock one.

A new JsonResult is needed because the base one hard codes the construction of the JavaScriptSerializer.

So here we go. Some CTRL+C, CTRL+V later from the open source MVC on Codeplex gives us

   1: public class TypedJsonResult : JsonResult
   2: {
   3:     public override void ExecuteResult(ControllerContext context)
   4:     {
   5:         if (context == null)
   6:         {
   7:             throw new ArgumentNullException("context");
   8:         }
   9:  
  10:         if ((JsonRequestBehavior == JsonRequestBehavior.DenyGet)
  11:             && string.Equals(context.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase))
  12:         {
  13:             throw new InvalidOperationException("JsonRequest GetNotAllowed");
  14:         }
  15:  
  16:         var response = context.HttpContext.Response;
  17:  
  18:         response.ContentType = !string.IsNullOrEmpty(ContentType) ? ContentType : "application/json";
  19:  
  20:         if (ContentEncoding != null)
  21:         {
  22:             response.ContentEncoding = ContentEncoding;
  23:         }
  24:  
  25:         if (Data != null)
  26:         {
  27:             var serializer = new JavaScriptSerializer(new BiasedTypeResolver());
  28:             response.Write(serializer.Serialize(Data));
  29:         }
  30:     }
  31: }

You will note on line 27 that we're still using the JavaScriptSerializer, but this time we're controlling its construction and decided to give it our own type resolver. More on that type resolver in a bit.

Next, we want to our controller(s) an easy way to choose our TypedJsonResult rather than the stock one. Luckily, the controller boils down the call Json(data) and several other signatures to a call to a virtual signature which we may simply override, like so:

   1: protected override  JsonResult Json(object data, string contentType, Encoding contentEncoding, JsonRequestBehavior behavior)
   2: {
   3:     return new TypedJsonResult { Data = data, ContentType = contentType, ContentEncoding = contentEncoding, JsonRequestBehavior = behavior };
   4: }

That's it! On line 3 you will notice we return our custom TypedJsonResult, whereas the stock implementation would have returned the JsonResult.

If this new behavior is desired everywhere, then you would probably want to place this override in a base controller of your own, and have all your controllers inherit it.

Other powers this bestows on you is of course using some other serializer altogether, such as Json.NET or whatever you fancy.

Now back to my own type resolver. You could, after all, use the SimpleTypeResolver built into the framework, which works quite well. However, it introduces fairly long type names – frowned upon by my clients consuming this Json on other platforms, and also doesn't enable me to map my own type names to a type of my choice. Enter the BiasedTypeResolver.

   1: private static readonly Dictionary<string, Type> _KnownTypes;
   2:  
   3: static BiasedTypeResolver()
   4: {
   5:     _KnownTypes = new Dictionary<string, Type> ();
   6:     var appDomain = AppDomain.CurrentDomain;
   7:     foreach (var assembly in appDomain.GetAssemblies().Where(a => a.GetName().Name.EndsWith(".ValueObjects")))
   8:     {
   9:         foreach (var type in assembly.GetTypes().Where(t => !t.IsInterface && !t.IsAbstract))
  10:         {
  11:             _KnownTypes[type.Name] = type;
  12:         }
  13:     }
  14: }
  15:  
  16: public override Type ResolveType(string id)
  17: {
  18:     var result = Type.GetType(id);
  19:     if (result != null || _KnownTypes.TryGetValue(id, out result))
  20:     {
  21:         return result;
  22:     }
  23:     throw new ArgumentException("Unable to resolve [" + id + "]", "id");
  24: }
  25:  
  26: public override string ResolveTypeId(Type type)
  27: {
  28:     if (type == null)
  29:     {
  30:         throw new ArgumentNullException("type");
  31:     }
  32:  
  33:     return type.Name;
  34: }

This resolver spelunks specific assemblies only (those named [whatever].ValueObjects which are my naming convention for POCO public objects) and catalogs them into a dictionary by short type name.

It doesn't know how to resolve 2 types of the same name if they only differ by namespace, but then again I'd ask "how come you would define 2 classes of the same exact name in your solution?" You can define type names to whatever suites your needs.

The resolver's responsibility is twofold: Given a string , return the System.Type that corresponds to it. Given a type, return a name for it. The former is used during deserialization, the latter when serializing.

Now you may not need or like this particular type resolver implementation. But now that you can inject your own, possibilities are limitless. These can range to configuration based type resolution, versioning decisions base on some revision upgrades etc.

Note also that upon deserialization, the type resolver is only called when a type discriminator exists in the JSON stream. That is, a complex type that doesn't contain "__type":"foo" will be serialized by the JavaScriptSerializer by matching the target member name rather than the resolver. This is nice because the JSON can contain strategically placed type discriminators for polymorphic reasons on some members, but be left terse and bare otherwise.

Hopefully, this helps you, or me-of-the-future when the gray cells got filled with the next great thing..

Happy Coding!



  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

The last MVVM you'll ever need?

As my MVC projects mature and grow, the need to have some omnipresent, ambient model properties quickly emerge. The application no longer has only one dynamic pieced of data on the page: A sidebar with a shopping cart, some news flash on the side – pretty common stuff. The rub is that a controller is invoked in context of a single intended request. The rest of the data, even though it could be just as dynamic, is expected to appear on it's own.

There are many solutions to this scenario. MVVM prescribes creating elaborate objects which expose your new data as a property on some uber-object with more properties exposing the "side show" ambient data. The reason I don't love this approach is because it forces fairly acute awareness of the view, and soon enough you have many MVVM objects laying around, and views have to start doing null-checks in order to ensure you really supplied all the values before binding to them. Ick.

Just as unattractive is the ViewData dictionary. It's not strongly typed, and in both this and the MVVM approach someone has to populate these properties – n'est pas? Where does that live?

With MVC2, we get the formerly-futures  feature Html.RenderAction(). The feature allows you plant a line in a view, of the format:

<% Html.RenderAction("SessionInterest", "Session"); %>

While this syntax looks very clean, I can't help being bothered by it. MVC was touting a very strong separation of concerns, the Model taking on the role of the business logic, the controller handling route and performing minimal view-choosing operations and the views strictly focused on rendering out angled-bracket tags. The RenderAction() syntax has the view calling some controller and invoking it inline with it's runtime rendering. This – to my taste – embeds too much  knowledge of controllers into the view's code – which was allegedly forbidden.  The one way flow "Controller Receive Data –> Controller invoke Model –> Controller select view –> Controller Hand data to view" now gets a "View calls controller and gets it's own data" which is not so one-way anymore. Ick.

I toyed with some other solutions a bit, including some base controllers, special view classes etc. My current favorite though is making use of the ExpandoObject and dynamic features with C# 4.0.

If you follow Phil Haack or read a bit from David Heyden you can see the general picture emerging. The game changer is that using the new dynamic syntax, one can sprout properties on an object and make use of them in the view. Well that beats having a bunch of uni-purpose MVVM's any day! Rather than statically exposed properties, we'll just use the capability of adding members at runtime. Armed with new ideas and syntax, I went to work:

First, I created a factory method to enrich the focuse object:

public static class ModelExtension
{
    public static dynamic Decorate(this Controller controller, object mainValue)
    {
        dynamic result = new ExpandoObject();
        result.Value = mainValue;
        result.SessionInterest = CodeCampBL.SessoinInterest();
        result.TagUsage = CodeCampBL.TagUsage();
        return result;
    }
}

This gives me a nice fluent way to have the controller add the rest of the ambient "side show" items (SessionInterest, TagUsage in this demo) and expose them all as the Model:

public ActionResult Index()
{
    var data = SyndicationBL.Refresh(TWEET_SOURCE_URL);
    dynamic result = this.Decorate(data);
    return View(result);
}

So now what remains is that my view knows to expect a dynamic object (rather than statically typed) so that the ASP.NET page compiler won't barf:

<%@ Page Language="C#" Title="Ambient Demo"
 MasterPageFile="~/Views/Shared/Ambient.Master" 
 Inherits="System.Web.Mvc.ViewPage<dynamic>" %>

Notice the generic ViewPage<dynamic>. It doesn't work otherwise.

In the page itself, Model.Value property contains the main data returned from the controller. The nice thing about this, is that the master page (Ambient.Master) also inherits from the generic ViewMasterPage<dynamic>. So rather than the page worrying about all this ambient stuff, the side bars and panels for ambient data all reside in a master page, and can be rendered using the RenderPartial() syntax:

<% Html.RenderPartial("TagCloud", Model.SessionInterest as Dictionary<string, int>); %>

Note here that a cast is necessary. This is because although dynamic is magic, it can't figure out what type this property is, and wants you to give it a type so its binder can figure out the right property to bind to at runtime. I use as, you can cast if you like.

So there we go – no violation of MVC, no explosion of MVVM models and voila – right?

Well, I could not let this go without a tweak or two more. The first thing to improve, is that some views may not need all the properties. In that case, it would be a waste of resources to populate every property. The solution to this is simple: rather than exposing properties, I change d the factory method to expose lambdas - Func<T> really. So only if and when a view accesses a member of the dynamic object does it load the data.

public static class ModelExtension
{
// take two.. lazy loading!
    public static dynamic LazyDecorate(this Controller c, object mainValue)
    {
        dynamic result = new ExpandoObject();
        result.Value = mainValue;
        result.SessionInterest = new Func<Dictionary<string, int>>(() => CodeCampBL.SessoinInterest());
        result.TagUsage = new Func<Dictionary<string, int>>(() => CodeCampBL.TagUsage());
        return result;
    }
}

Now that lazy loading is in place, there's really no reason not to hook up all and any possible ambient property. Go nuts! Add them all in – they won't get invoked unless used.

This now requires changing the signature of usage on the ambient properties methods –adding some parenthesis to the master view:

<% Html.RenderPartial("TagCloud", Model.SessionInterest() as Dictionary<string, int>); %>

And, of course, the controller needs to call LazyDecorate() rather than the old Decorate().

The final touch is to introduce a convenience method to the my Controller class , so that the tedium of calling Decorate() everywhere goes away. This is done quite simply by adding a bunch of methods, matching View(object), View(string,object) signatures of the Controller class:

public ActionResult Index()
{
    var data = SyndicationBL.Refresh(TWEET_SOURCE_URL);
    return AmbientView(data);
}

//these methods can reside in a base controller for the solution:
public ViewResult AmbientView(dynamic data)
{
    dynamic result = ModelExtension.LazyDecorate(this, data);
    return View(result);
}

public ViewResult AmbientView(string viewName, dynamic data)
{
    dynamic result = ModelExtension.LazyDecorate(this, data);
    return View(viewName, result);
}

The call to AmbientView now replaces any call the View() that requires the ambient data. DRY sattisfied, lazy loading and no need to replace core pieces of the MVC pipeline. I call this a good MVC day.

Enjoy!



  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

DotNetNuke + PayPal

A DotNetNuke i'm supporting has had a paypal "buy now" button and other variations with custom fields for a while now. About 2 weeks ago (somewhere in March 2010) they all stopped working.

The problem manifested such that once you clicked the "buy now" button, Paypal site would throw a scary error page to the effect of:

"Internal Server Error

The server encountered an internal error or misconfiguration and was unable to complete your request.
Please contact the server administrator, webmaster@paypal.com and inform them of the time the error occurred, and anything you might have done that may have caused the error.
More information about this error may be available in the server error log"

Once I verified no cheeky content editor changed the page, I went digging for answers.

The main source incompatibility of PayPal's simple HTML forms is that DNN includes a form on every page, and nested forms are not really supported. As blogged here and lamented here, the solution I came up with is simply to modify the form enctype to 'application/x-www-form-urlencoded' as illustrated below:

   1: <input type="image" border="0" 
   2:     src="https://www.paypal.com/en_US/i/btn/btn_buynowCC_LG.gif" 
   3:     name="submit" 
   4:     alt="PayPal - The safer, easier way to pay online!" 
   5:     onClick="this.form.action='https://www.paypal.com/cgi-bin/webscr'; this.form.enctype='application/x-www-form-urlencoded';this.form.submit();" />

One would think that PayPal would want the masses submitting HTML in all manners of "enctype", but I guess every company has it's quirks.

At least my favorite non-profit can now continue and accept payments.

Sigh.



  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

MVC Automatic Menu

An ex-colleague of mine used to call his SQL script generator "Super-Scriptmatic 2000". It impressed our then boss little, but was fun to say and use. We called every batch job and script "something 2000" from that day on. I'm tempted to call this one Menu-Matic 2000, except it's waaaay past 2000. Oh well.

The problem: I'm developing a bunch of stuff in MVC. There's no PM to generate mounds of requirements and there's no Ux Architect to create wireframe. During development, things change. Specifically, actions get renamed, moved from controller x to y etc. Well, as the site grows, it becomes a major pain to keep a static menu up to date, because the links change. The HtmlHelper doesn't live up to it's name and provides little help. How do I keep this growing list of pesky little forgotten actions reigned in?

The general plan is:

  1. Decorate every action you want as a menu item with a custom attribute
  2. Reflect out all menu items into a structure at load time
  3. Render the menu using as CSS  friendly <ul><li> HTML.

The MvcMenuItemAttribute decorates an action, designating it to be included as a menu item:

[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
    public class MvcMenuItemAttribute : Attribute
    {
 
        public string MenuText { get; set; }
 
        public int Order { get; set; }
 
        public string ParentLink { get; set; }
 
        internal string Controller { get; set; }
 
        internal string Action { get; set; }
 
 
        #region ctor
 
        public MvcMenuItemAttribute(string menuText) : this(menuText, 0) { }
        public MvcMenuItemAttribute(string menuText, int order)
        {
            MenuText = menuText;
            Order = order;
        }
 
 
 
        internal string Link { get { return string.Format("/{0}/{1}", Controller, this.Action); } }
 
        internal MvcMenuItemAttribute ParentItem { get; set; }
        #endregion
    }

The MenuText allows overriding the text displayed on the menu. The Order allows the items to be ordered. The ParentLink allows you to make this item a child of another menu item. An example action could then be decorated thusly: [MvcMenuItem("Tracks", Order = 20, ParentLink = "/Session/Index")] . All pretty straightforward methinks.

The challenge with menu hierarchy becomes fairly apparent when you try to render a menu and highlight the "current" item or render a breadcrumb control. Both encounter an  ambiguity if you allow a data source to have more than one menu item with the same URL link. The issue is that there is no great way to tell which link a person click. Using referring URL will fail if a user bookmarked the page. Using some extra query string to disambiguate duplicate URLs essentially changes the links, and also ads a chance of collision with other query parameters. Besides, that smells. The stock ASP.Net sitemap provider simply disallows duplicate URLS. I decided not to, and simply pick the first one encountered as the "current". Although it doesn't solve the issue completely – one might say they wanted the second of the 2 links to be "current"- it allows one to include a link twice (home->deals and products->deals etc), and the logic of deciding "current" is easy enough to explain to the customer.

Now that we got that out of the way, let's build the menu data structure:

public static List<MvcMenuItemAttribute> ListMenuItems(Assembly assembly)
{
    var result = new List<MvcMenuItemAttribute>();
    foreach (var type in assembly.GetTypes())
    {
        if (!type.IsSubclassOf(typeof(Controller)))
        {
            continue;
        }
        foreach (var method in type.GetMethods())
        {
            var items = method.GetCustomAttributes(typeof(MvcMenuItemAttribute), false) as MvcMenuItemAttribute[];

            if (items == null)
            {
                continue;
            }
            foreach (var item in items)
            {
                if (String.IsNullOrEmpty(item.Controller))
                {
                    item.Controller = type.Name.Substring(0, type.Name.Length - "Controller".Length);
                }
                if (String.IsNullOrEmpty(item.Action))
                {
                    item.Action = method.Name;
                }
                result.Add(item);
            }
        }
    }

    return result.OrderBy(i => i.Order).ToList();
}

Using reflection, the ListMenuItems method takes an assembly (you will hand it your MVC web assembly) and generates a list of menu items. It digs up all the types, and for each one that is an MVC Controller, digs up the methods. Methods decorated with the MvcMenuItemAttribute get plucked and added to the output list. Again, pretty simple. To make the structure hierarchical, a LINQ expression matches up all the items to their parent:

public static void RegisterMenuItems(List<MvcMenuItemAttribute> items)
{
    _MenuItems = items;
    _MenuItems.ForEach(i => i.ParentItem =
                            items.FirstOrDefault(p =>
                                                 String.Equals(p.Link, i.ParentLink, StringComparison.InvariantCultureIgnoreCase)));
}

The _MenuItems is simply an internal list to keep things around for later rendering. Finally, to package the menu building for easy consumption:

public static void RegisterMenuItems(Type mvcApplicationType)
{
    RegisterMenuItems(ListMenuItems(Assembly.GetAssembly(mvcApplicationType)));
}

To bring this puppy home, a call in Global.asax.cs Application_Start() registers the menu. Notice the ugliness of reflection is tucked away from the innocent developer. All they have to do is call the RegisterMenuItems() and pass in the type of the application. When you use the new project template, global.asax declares a class public class MvcApplication : HttpApplication and that is why the Register call passes in that type.

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();
    RegisterRoutes(RouteTable.Routes);
 
    MvcMenu.RegisterMenuItems(typeof(MvcApplication));
}

 

What else is left to do? Oh, right, render!

public static void ShowMenu(this TextWriter output)
{
    var writer = new HtmlTextWriter(output);
 
    renderHierarchy(writer, _MenuItems, null);
}
 
public static void ShowBreadCrumb(this TextWriter output, Uri currentUri)
{
    var writer = new HtmlTextWriter(output);
    string currentLink = "/" + currentUri.GetComponents(UriComponents.Path, UriFormat.Unescaped);
 
    var menuItem = _MenuItems.FirstOrDefault(m => m.Link.Equals(currentLink, StringComparison.CurrentCultureIgnoreCase));
    if (menuItem != null)
    {
        renderBreadCrumb(writer, _MenuItems, menuItem);
    }
}
 
private static void renderBreadCrumb(HtmlTextWriter writer, List<MvcMenuItemAttribute> menuItems, MvcMenuItemAttribute current)
{
    if (current == null)
    {
        return;
    }
    var parent = current.ParentItem;
    renderBreadCrumb(writer, menuItems, parent);
    writer.Write(current.MenuText);
    writer.Write(" / ");
 
}
 
 
static void renderHierarchy(HtmlTextWriter writer, List<MvcMenuItemAttribute> hierarchy, MvcMenuItemAttribute root)
{
    if (!hierarchy.Any(i => i.ParentItem == root)) return;
 
    writer.RenderBeginTag(HtmlTextWriterTag.Ul);
    foreach (var current in hierarchy.Where(element => element.ParentItem == root).OrderBy(i => i.Order))
    {
        if (ItemFilter == null || ItemFilter(current))
        {
 
            writer.RenderBeginTag(HtmlTextWriterTag.Li);
            writer.AddAttribute(HtmlTextWriterAttribute.Href, current.Link);
            writer.AddAttribute(HtmlTextWriterAttribute.Alt, current.MenuText);
            writer.RenderBeginTag(HtmlTextWriterTag.A);
            writer.WriteEncodedText(current.MenuText);
            writer.RenderEndTag(); // link
            renderHierarchy(writer, hierarchy, current);
            writer.RenderEndTag(); // li
        }
    }
    writer.RenderEndTag(); // ul
}

The ShowMenu method renders the menu out to the provided TextWriter. In previous posts I've discussed my partiality to using well debugged, time test HtmlTextWriter to render HTML rather than writing out angled brackets by hand. In addition, writing out using the actual writer on the actual stream rather than generating string and byte intermediaries (yes, StringBuilder being no exception) disturbs me.

To carry out the rendering of an hierarchical menu, the recursive renderHierarchy() is used. You may notice that an ItemFilter is called before rendering each item. I figured that at some point one might want to exclude certain items from the menu based on security role or context or something. That delegate is the hook for such future feature.

To carry out rendering of a breadcrumb recursion is used again, this time simply to unwind the parent hierarchy from the leaf node, then rendering on the return from the recursion rather than as we go along deeper. I guess I was stuck in LISP that day.. recursion is fun though.

 

Now all that is left is some usage! Open your Site.Master or wherever you'd like to place a menu or breadcrumb, and plant one of these calls:

<% MvcMenu.ShowBreadCrumb(this.Writer, Request.Url); %> to show a breadcrumb trail (notice lack of "=" after <% and the semicolon).

<% MvcMenu.ShowMenu(Writer); %> to show the menu.

 

As mentioned before, the HTML output is nested <UL> <LI> tags, which should make it easy to style using abundant CSS to produce anything from static horizontal or vertical to dynamic drop-downs.

 

This has been quite a fun little implementation and I was pleased that the code size remained low. The main crux was figuring out how to pass parent information from the attribute to the hierarchy builder because attributes have restricted parameter types. Once I settled on that implementation, the rest falls into place quite easily.



  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Fluent Binder – Simple Magic can happen in 10 lines of C#

Often enough we have frameworks do heavy lifting for us. That's usually a good thing. But I always found it kind of sedating to let "the man" provide me with too much comfort. Especially when the framework or other SOUP library fails to perform exactly what you want. That usually leads to some grumpiness followed by some code-acrobatics to punch that square peg into a round hole – often negating the elegance and usefulness of the library call altogether.

One task a framework often performs is binding. Binding – as defined here – is taking an object and assigning values to it's properties from a property bag of sorts. For example, a property bag could be a hash-table or list of name-value pairs and an object would be a POCO (Plain old class object). It's common in web and ORM contexts, also in web services to receive a dictionary of values and have to attach them to your domain model. The plain straightforward way would be to pluck key value pairs one by one by name and assign to your object. But that's no fun and error prone. What we would like is to be able to auto-attach values to the target object.

How do we achieve that? Steve Bearman and I actually presented this very briefly as part of a larger talk on advanced C# at SoCal Code Camp last weekend. A bit of reflection, a bit of generics and extensions, and viola:

   1: public static T Populate<T>(this T target, IEnumerable<KeyValuePair<string, object>> values)
   2: {
   3:     Type targetType = target.GetType();
   4:     foreach (var kvp in values)
   5:     {
   6:         PropertyInfo pi = targetType.GetProperty(kvp.Key);
   7:         pi.SetValue(target, kvp.Value, null);
   8:     }
   9:     return target;
  10: }

The extension method Populate() above takes an IEnumerable of KeyValuePair as a parameter. It then iterates a these pairs and for each key finds a property  by that name and assigns the value from the dictionary to the target object. Reflection comes in at lines 6 and 7. A property is found based on the name alone, and assigned to. Usage of this extension can look something like this:

   1: Dictionary<string, object> assignments = new Dictionary<string, object>();
   2: assignments.Add("Name", "Paris Hilton");
   3: assignments.Add("ID", 42);
   4: assignments.Add("HomePhone", "(310)-555-1212");
   5: assignments.Add("WorkPhone", "(310)-777-FILM");
   6: Person paris = new Person();
   7:  
   8: Person result = paris.Populate(assignments);

Simple, granted. Simplistic perhaps. But let's consider that the average programmer doesn't write much code like this. There can be many bells and whistles added here: A property getter might only assign if the prperty is writable, attempt to match without case sensitivity, only match if property is public or adorned with an attribute. The main thinks is that you can write this method into your solution in very few lines and shape it as you wish. You do not have to depend on default MVC binders or ORMs being open source or anything like that to have binding performed. Further utilizing this bit (!) of code you might create a simple object factory that returns a new populated type from any object given a property bag of values. In fact, let's do this right here:

   1: public static class MyFactory<T>
   2: {
   3:     public static T Create(IEnumerable<KeyValuePair<string, object>> values)
   4:     {
   5:         T result;
   6:         ConstructorInfo ctor = typeof(T).GetConstructor(System.Type.EmptyTypes);
   7:         result = (T)ctor.Invoke(null);
   8:         result.Populate(values);
   9:         return result;
  10:     }
  11: }

The generic factory MyFactory has a Create() method which takes a property bag as a parameter and returns a populated instance with the values provided. The usage of the factory eliminates the need for creating a new empty instance before populating it. Well, actually , it does it so you don't have to – code was not eliminated, just consolidated. The usage then becomes:

   1: Dictionary<string, object> values = new Dictionary<string, object>();
   2: values.Add("Name", "Paris Hilton");
   3: values.Add("ID", 42);
   4: values.Add("HomePhone", "(310)-555-1212");
   5: values.Add("WorkPhone", "(310)-777-FILM");
   6:  
   7: Person actual = MyFactory<Person>.Create(values);

So there we have it folks. Another DIY tidbit that would hopefully help you take control of the common binding task away from framework writers and back into your hands - where it belongs.

In production, you would probably want to also take a look at whether there's a Populate() or TryPopulate() -exception or return boolean -  and handle the whole error pathing in an explicit way that fits your own style of coding. Similarly you should consider whether an unassigned property (missing value in the bag) is cause for error and whether extra unmatched values are cause for error. In this example, an extra value will cause an exception and an unassigned property will not.

Happy Binding!



  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Between - Extension method to shorten notation

Sometimes I just write code. And sometimes I clean up my code. Most of the times, I focus on the meat of the methods, hacking away at verbose or lengthy flows, re-factoring out common code, trying to untangle overly complex logic etc.

Recently, I noticed that many of the conditional terms I write span very long lines and are a bit cumbersome to read. The reason for that is that many of the variable names are long, or the properties or both and that often the comparison is on a property of an object or member of a collection etc.

So for instance:

if (summerCatalog.Products[0].ProductCategories[0].ParentCategoryID >= 1 && summerCatalog.Products[0].ProductCategories[0].ParentCategoryID <= 4)
{ 
//...
}


Can become quite long.
Long is not easy to read.
Long is not easy to maintain.
Long is not easy to think through.

What I really wanted to say is if [value] is between [a] and [b].

Of course, one could say "lets just make the variable names shorter". But that flies in the face of self explanatory plain naming. So abbreviating for the sake of short-lineliness (New word! You heard it her first!) is out.

Well, this is just screaming "EXTENSION METHODS" doesn't it?

Here we go then:

/// <summary>
/// Returns whether the value is between the 2 specified boundaries.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value">The value to compare</param>
/// <param name="minValueInclusive">The min value (inclusive).</param>
/// <param name="maxValueInclusive">The max value (inclusive).</param>
/// <returns>True if the value is equal to or between the boundaries; False otherwise.</returns>
public static bool Between<T>(this T value, T minValueInclusive, T maxValueInclusive) where T : IComparable<T>
{
    if (minValueInclusive.CompareTo(maxValueInclusive) > 0)
    {
        throw new ArgumentException("minimum value must not be greater than maximum value");
    }
    return (value.CompareTo(minValueInclusive) >= 0 && value.CompareTo(maxValueInclusive) <= 0);
}

The Between function takes any object which supports IComparable<T> and performs syntactic sugar comparison with the inclusive min and max values.
What's more, it adds a basic sanity check for the comparison. How many times do I do that sanity check in my normal code (!)?

Now the conditional is

if (summerCatalog.Products[0].ProductCategories[0].ParentCategoryID.Between(1, 4)) 
{
///...
}

At least I don't have to refactor this in my brain while reading.

Sure, you might say, but you could have just de-referenced the deep value and then have a shorter conditional, like so:

Category category = summerCatalog.Products[0].ProductCategories[0];
if (category.ParentCategoryID >= 1 && category.ParentCategoryID <= 4)
{
    //...
}
Yes - of course - but it adds a line of code, places the burden of reading the very common idiom ( x >= a && x <= b) on me, and I constantly stumble on the lest-than-or-equal vs. less-than and it doesn't check for my boundaries being inadvertently swapped.

So there you have it. A simple extension cuts down your lines of code, makes long text shorter and saves lives. Which begs the question: is this already part of the language - and should it be?

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Unit Testing and approval tests

It's been years now that unit testing frameworks and tools have grabbed our attention, made their way into our favorite IDE and sparked yet another wave of seemingly endless "my framework is better than yours" wars. And then there are the principal wars of whether TDD is better than Test After Development. And most excitingly the automated testing tools etc. Oh, and let's not forget mocks! So we have all the tools we need – right? Well, kind of, no.

I recently attended a talk by Llewellyn Falco and Woody Zuill the other day, and they used a little library called Approval Tests (http://approvaltests.com/). I immediately fell in love with the concept and the price ($0). Llewellyn is one of the two developers of the product, hosted on http://sourceforge.net/projects/approvaltests/.

What does it do that years of frameworks don't?

For me, a major nuisance is that you have a piece of code, and that piece of code produces a result (object, state – call it what you will). That result is commonly named "actual" in Visual Studio unit tests. The developer must then assert against that result to ensure that the code ran properly. In theory, unit tests are supposed to be small and only test one thing. In reality, functions which return complex objects rarely can be asserted with one assert. You'd typically find yourself asserting several properties or testing some behavior of the actual value. In corporate scenario, the unit tests might morph into some degree of integration tests and objects become more complex, requiring a slew of assert.this and assert.that().

What if you could just run the code, inspect the value returned, and – if it satisfies the requirements – set "that value" to be the comparison for all future runs? Wouldn't that be nice? Good news: Approval Tests does just that. So now, instead of writing so many asserts against your returned value, you just call ApprovalTests.Approve() and the captured state is compared against your current runtime. Neat huh?

But wait, there's more! What if your requirements are regarding a windows form, or a control? how do you write a unit test that asserts against a form? The answer is simple and genius: Capture the form as an image, and compare the image produced by your approved form (after you have carefully compared it to the form given to you by marketing – right?) and compare it to each subsequent run. ApprovalTests simply does a byte by byte comparison of the resultant picture of the form and tells you if it matches what you approved.

Let's break down the steps for installation:

  1. Add a reference to the ApprovalTests.dll assembly.

Yeah,it's that simple.

Ok. Let's break down the steps for adding an approval to your unit test

  1. Write your unit test (arrange, act – no asserts) as usual.
  2. Add a call to Approve()

Yeah, it's that simple.

How do you tell it that the value received is "the right one"? Upon first run, the Approve() call will always fail. Why? Because it has no stored approved value to compare the actual it received against. When it fails, it will print out a message (console or test report – depends on your unit test runner). That message will contain a path for the file that it received, complaining about a lack of approved file. The value captured from that run (and any subsequent run) is stored in a file named something like "{your unit test file path}\{your method}.received.xyz". If you like the result of the run -the image matches what the form should look like, or the text value is what your object should contain etc – then you can rename it to "{your unit test file path}\{your method}.approved.xyz". You should check the approved file into your source control. After all, it's content constitutes the basis of the assertion in your unit test!

Consider the very simple unit test code:

   1: [Test]
   2:         public void DateTime_Constructor_YMDSetDate()
   3:         {
   4:             DateTime actual;
   5:             actual = new DateTime(2038, 4, 1);
   6:             Approvals.Approve(actual.ToString());
   7:         }

The function under test here is the constructor for System.DateTime which takes 3 parameters – month day and year. Upon first run, the test will fail with a message resembling

"TestCase 'MyProject.Tests.DateTimeTest.DateTime_Constructor_YMDSetDate'
failed: ApprovalTests.Core.Exceptions.ApprovalMissingException : Failed Approval: Approval File "C:\….\MyProject\DateTimeTest.DateTime_Constructor_YMDSetDate.approved.txt" Not Found."

That's because this file was never created – it's your first run. Using the standard approver, this file will actually now be created but will be empty. In that same directory you will find a file named {…}.received.txt. This is the capture from this run. You can open the received value file, and inspect the text to ensure that the value returned matches your expected value. If it does, simply rename that file to .approved.text or copy it's content over and run the test again. This time, the Approve() method should succeed. If at any point in the future the method under test returns a different value, the approval will fail. If at any point in the future the specs change, you will need to re-capture a correct behavior and save it.

How do you easily compare the values from the last run and the saved approved value? The approved file is going to be a text file for string approvals, and an image file for WinForm approvals. As it turns out, you can instruct Approval Tests to launch a diff program with the 2 files (received, approved) automatically upon failure, or just open the received file upon failure or silently just fail the unit test. To control that behavior, you use a special attribute

   1: [TestFixture]
   2: [UseReporter(typeof(DiffReporter))]
   3: public class ObjectWriterTest
   4: {

The UserReporterAttribute allows you to specify one of 3 included reporters

  1. DiffReporter – which opens tortoisediff for diffing the received and approved files if the comparison fails.
  2. OpenReceivedFileReporter – which launches the received file using the application registered to it's extension on your system if the comparison fails.
  3. QuietReporter – which does not launch any program but only fails the unit test if the comparison fails.

When your have a CI server and run unit tests as part of your builds, you probably want to use the quiet reporter. For interactive sessions, one of the first 2 will probably be more suitable.

How are value comparisons performed? Under the standard built in methods, a file is written out and compared to byte by byte. If you wish to modify this or any behavior, you can implement your own approver or file writer or reporter by implementing simple interfaces. I ended up adding a general use object writer so that I can approve arbitrary objects. The effort was fairly painless and straightforward.

I did have to read the code to get the concept. If only my time machine worked: I could have read my own blog and saved myself 20 minutes. Yeah, right.

The project has some bells and whistles – plug ins for a few IDE's and there's a version for Java and Ruby. I have not reviewed these versions.

There you have it folks- a shiny new tool under your belt. I can see this saving my hours of mindless typing of Assert.* calls and I can go home early. Yeah, right.



  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

MVC Radio Button List

As predicted, I came around to using some radio  buttons. As you might guess by now, I didn't like the HTML or the implementation in the current MVC release. As you may expect, I wrote my own :-)

The implementation is fairly simple and straightforward. It extends System.Web.MVC.ViewPage, takes a list of objects, allows for selection of one of the radio buttons, supports orientation and supports selection of both the value the radio button submits and the display string for that item independently.

   1: using System;
   2: using System.Collections.Generic;
   3: using System.Linq.Expressions;
   4: using System.Web.Mvc;
   5: using System.Web.UI;
   6:  
   7: public static partial class HtmlHelpers
   8: {
   9:     public static void ShowRadioButtonList<T>(this ViewPage page, IList<T> list, string name, Expression<Func<T, object>> valueProperty, Expression<Func<T, object>> displayProperty, System.Web.UI.WebControls.Orientation orientation)
  10:     {
  11:         page.ShowRadioButtonList(list, name, valueProperty, displayProperty, "3", orientation);
  12:     }
  13:  
  14:  
  15:     public static void ShowRadioButtonList<T>(this ViewPage page, IList<T> list, string name, Expression<Func<T, object>> valueProperty, Expression<Func<T, object>> displayProperty, string selectedValue, System.Web.UI.WebControls.Orientation orientation)
  16:     {
  17:         HtmlTextWriter writer = new HtmlTextWriter(page.Response.Output);
  18:         if (writer != null)
  19:         {
  20:             Func<T, object> valueGetter = valueProperty.Compile();
  21:             Func<T, object> displayStringGetter = displayProperty.Compile();
  22:  
  23:             for (int i = 0; i < list.Count; i++)
  24:             {
  25:                 T row = list[i];
  26:                 string value = valueGetter(row).ToString();
  27:                 writer.AddAttribute(HtmlTextWriterAttribute.Type, "radio");
  28:                 writer.AddAttribute(HtmlTextWriterAttribute.Id, name + "_" + i);
  29:                 writer.AddAttribute(HtmlTextWriterAttribute.Name, name, true);
  30:                 writer.AddAttribute(HtmlTextWriterAttribute.Value, value, true);
  31:                 if (value == selectedValue)
  32:                 {
  33:                     writer.AddAttribute(HtmlTextWriterAttribute.Checked,"checked");
  34:                 }
  35:                 writer.RenderBeginTag(HtmlTextWriterTag.Input);
  36:                 writer.Write(displayStringGetter(row));
  37:                 writer.RenderEndTag();
  38:  
  39:                 if (orientation == System.Web.UI.WebControls.Orientation.Vertical)
  40:                 {
  41:                     writer.RenderBeginTag(HtmlTextWriterTag.Br);
  42:                     writer.RenderEndTag();
  43:                 }
  44:             }
  45:         }
  46:     }
  47: }

 

This implementation uses the type Expression<Func<T,Object>> for the selection of the value and the display string. To invoke the helper, assuming you have a list of Product objects, Product being defined:

   1: public class Product
   2: {
   3:     public int ProductID { get; set; }
   4:     public string Title { get; set; }
   5:     public string Description { get; set; }
   6:     public decimal Price { get; set; }
   7: }

You can now call the helper from your MVC View Page strongly typed with a model List<Product>:

   1: <%@ Page Title="" Language="C#" Inherits="System.Web.Mvc.ViewPage<List<Product>>"
   2:     MasterPageFile="~/Views/Shared/Site.Master" %>
   3:  

invoked simply

   1: <% this.ShowRadioButtonList<Product>(Model, 
   2:                             "productRadioButtonList", 
   3:                             a => a.ProductID, 
   4:                             d => d.Title, "4", 
   5:                             Orientation.Horizontal); %>

This call will create a radio button for each product in the list (Model is a List<Product> because we strongly typed the page as such). The radio button will use the ProductID property for the value of the input, and the Title property as the displayed string. If one of the product Id's happens to be 4, that radio button will be selected in the group. The radio buttons will all be named "productRadioButtonList" but their ID will be appended an ordinal number  "productRadioButtonList_1","productRadioButtonList_2","productRadioButtonList_3" etc.

There you have it: another day, another MVC control, another blog post.



  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

MVC paged list

The need

As certain as the sun rising tomorrow, there will come the point where you will want to display a list or grid with paging. While many solutions exist, and many component developers are coming in with robust solutions, a simple and satisfactory solution can be created fairly easily.

Implementation

Why create a pager from scratch? Several reasons:

1) You want to control the pager completely – display, style and all.

2) You don't like the idea of JavaScript paging, which will load your hundreds of pages to the browser and do client side paging / grid

3) You want to understand and control exactly how a page subset of record is fetched and take control of database or IO thrashing

Of the quickly surveyed solutions out there, I found this one simple and straightforward. Being small, straightforward and simple means also easy to maintain, extend or modify. Based on that solution, I've created my own pager which breaks into 2 class implementations and one usage guidance.

The first class, is the PagedList class. The whole class is rather small and the only crux is doing correct math and ensuring the logic handles zero items returned. This class is responsible for taking a source list of all items (more on that below in the performance considerations) and presenting simple properties for HasNextPage, HasPreviousPage, TotalPages and CurrentPage. The implementation inherits from the generic List<T>, and so exposes and enumerator and the Count property. The constructor copies only the current page's worth of items into the instance though, so Count will return the number of items on the current page (0 to page size) therefore an additional property TotalItems is populated upon construction which exposes the total number of items in the underlying source.

using System;
using System.Collections.Generic;
using System.Linq;

namespace BL.Models
{

    /// <summary>
    /// Adapted from http://blog.wekeroad.com/2007/12/10/aspnet-mvc-pagedlistt/
    /// </summary>
    /// <typeparam name="T">The type of item this list holds</typeparam>
    public class PagedList<T> : List<T>, IPagedList
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="PagedList&lt;T&gt;"/> class.
        /// </summary>
        /// <param name="source">The source list of elements containing all elements to be paged over.</param>
        /// <param name="currentPage">The current page number (1 based).</param>
        /// <param name="pageSize">Size of a page (number of items per page).</param>
        public PagedList(IEnumerable<T> source, int currentPage, int itemsPerPage)
        {
            this.TotalItems = source.Count();
            this.ItemsPerPage = itemsPerPage;
            this.CurrentPage = Math.Min(Math.Max(1, currentPage), TotalPages);
            this.AddRange(source.Skip((this.CurrentPage - 1) * itemsPerPage).Take(itemsPerPage).ToList());
        }


        public int CurrentPage {get ;private set;}

        public int ItemsPerPage { get; private set; }

        public bool HasPreviousPage { get { return (CurrentPage > 1); } }

        public bool HasNextPage { get { return (CurrentPage * ItemsPerPage) < TotalItems; } }

        public int TotalPages { get { return (int)Math.Ceiling((double)TotalItems / ItemsPerPage); } }

        public int TotalItems { get; private set; }
    }
}

PagedList implements the interface IPagedList, since a static class can not be generic, and the control renderer will need access to the PagedList's properties:

   1: using System;
   2:  
   3: namespace BL.Models
   4: {
   5:     public interface IPagedList
   6:     {
   7:         int CurrentPage { get; }
   8:         bool HasNextPage { get; }
   9:         bool HasPreviousPage { get; }
  10:         int ItemsPerPage { get; }
  11:         int TotalItems { get; }
  12:         int TotalPages { get; }
  13:     }
  14: }

The second class is more like a custom web control. Since this is MVC, we are driven to use a helper like implementation. My approach to developing HTML helpers for MVC is to create an extension method on the System.Web.MVC.ViewPage type. This allows the use of the well known and tested HtmlTextWriter to render the actual HTML rather than creating angled brackets in strings on the fly. I find this approach both more true to the form – rendering output to the output stream and not composing a string to be copied later – and safe: using compliant well tested constants and constructs rather than typing in HTML and hoping your syntax and understanding of the tag is correct.

using System.Web.Mvc;
using System.Web.UI;

public static partial class HtmlHelpers
{
    /// <summary>
    /// Shows a pager control - Creates a list of links that jump to each page
    /// </summary>
    /// <param name="page">The ViewPage instance this method executes on.</param>
    /// <param name="pagedList">A PagedList instance containing the data for the paged control</param>
    /// <param name="controllerName">Name of the controller.</param>
    /// <param name="actionName">Name of the action on the controller.</param>
    public static void ShowPagerControl(this ViewPage page, IPagedList pagedList, string controllerName, string actionName)
    {
        HtmlTextWriter writer = new HtmlTextWriter(page.Response.Output);
        if (writer != null)
        {
            for (int pageNum = 1; pageNum <= pagedList.TotalPages; pageNum++)
            {
                if (pageNum != pagedList.CurrentPage)
                {
                    writer.AddAttribute(HtmlTextWriterAttribute.Href, "/" + controllerName + "/" + actionName + "/" + pageNum);
                    writer.AddAttribute(HtmlTextWriterAttribute.Alt, "Page " + pageNum);
                    writer.RenderBeginTag(HtmlTextWriterTag.A);
                }

                writer.AddAttribute(HtmlTextWriterAttribute.Class,
                                    pageNum == pagedList.CurrentPage ?
                                                        "pageLinkCurrent" :
                                                        "pageLink");

                writer.RenderBeginTag(HtmlTextWriterTag.Span);
                writer.Write(pageNum);
                writer.RenderEndTag();

                if (pageNum != pagedList.CurrentPage)
                {
                    writer.RenderEndTag();
                }
                writer.Write("&nbsp;");
            }

            writer.Write("(");
            writer.Write(pagedList.TotalItems);
            writer.Write(" items in all)");
        }
    }
}

 

The implementation creates a list of page numbers, with a link on each except for the current page. The link will be of the format "/{controller name}/{action name}/{page number}".

I have added conditional style attribute to the link so that you can style the current page differently from the other pages easily. Since you have the code, you can extend the resultant HTML as you wish. You might want to have text indication of "no more pages" or some indication if the list is empty etc.

Finally, you would want to make use of this shiny new widget. The steps are as follows

1) In your controller, create an action which takes the page number as it's sole parameter. The action would then create a new instance of the PagedList, passing it the "full list" and the current page number from the parameter.

public ActionResult Page(int id)
        {
            List<Product> products = CatalogService.ListOpenProducts();
            PagedList<Product> data = new PagedList<Product>(products, id, PAGE_SIZE);
 
            return View(data);
        }

2) Change / create a view which takes the PagedList<your row type> as it's model.

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" 
Inherits="System.Web.Mvc.ViewPage<BL.Models.PagedList<Product>>" %>

3) Place a call to the extension method to display the pager anywhere in your view (multiple placement allowed – you can put one on top and one on the bottom etc). Recall that the method ShowPagerControl() extends  ViewPage, so the keyword this should show your intellisence for the method. If you chose a more complex model (MVVM ViewModel containing more data than just the paged list) then you would use Model.{paged list property name}. The use of the view as a bag of random data conjured up by string names should IMHO be universally abandoned and eliminated.

<% this.ShowPagerControl(Model, "Bids", "Page"); %>

 

Considerations

Take != load all + scroll

The PagedList implementation takes an IEnumerable<T> as it's source data. Internally, it uses Linq syntax which would seem to require all items be loaded, and then skip the first N pages and take the next {page size} worth of items. If your underlying list of items is a huge DB call, you will find that troubling. What you might consider then will be to use deferred loading. Extend the Linq IQueryable<T> or ObjectQuery<T> and let the ORM of your choice do the paging in the database. If your ORM is eager loader, you will need to implement custom partial record loading and paging at the data source level. If it can defer loading you will be in better shape.

Conversely, you might want to actually eager-load all records at the first shot. This will provide you with 2 benefits: cachability and coherency. Loading all items into memory incurs one DB call overhead and the IO required for all records. If you load each page at a time, you would incur {page count} * page clicks DB call overheads which might exceed the former if users scroll often back and forth. Once you load the whole list, you can cache it in memory and expire it based on data change events. If you have the base list in memory, access to it incurs no more IO regardless of pager clicks. Another phenomena caching gets around is coherency problems. If you page ad the DB level and an item is inserted or deleted, the end user experiences skips or stutter items. A skip is when a user clicks from page 1 to 2 an item which was to be on page 2 now is in the range of page 1 because an item on page 1 was deleted. Going to page 2 skips this item, and paging back should reveal it but would be surprising to the user (because she just came from page 1 and it wasn't there before) creating the appearnace of a skipped / missed item. A stutter is the reverse situation: user clicks from page 1 to 2, and an item from page 1 appears again on page 2. This happens when an item was added and "pushed" the repeat item into page 2 because of it's sorting order. This appears to the user as a malfunction and may infuriate some enough to call customer service (alas, advising customers to adjust their medication does not actually calm them down). A solution to coherence is to cache the result list for each user, expiring the cache actively when navigating away or running a different query.

Conclusion

The code above and variations of it are fairly easy to create. If your favorite web control vendor has not solved this for you, if you want to take full control of your paging of if you are just naturally curious – it's a great way to add paging to your MVC application.



  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

MVC + ASP.Net template control and user control

Seeing that I can use a DataBoundControl such as DataList, and binding it to a source control is achievable – what next?

Data bound controls contain various templates. The usual suspects are the item template and alternating template (for a repeating object, with possible varied style), the header and the footer templates (for enclosing HTML pre/post wrap or header / footer effects).

Under MVC, all events are out the window. So we're not concerned at all with event hookup. We might want to provide the various "modes" of display (Edit, Create, Delete etc) which align well with CRUD command structure and may map to MVC quite naturally. But for starters, my project's requirements simply required styling of the repeating item to be easily controlled.

So rather than inline HTML in the <ItemTemplate> tag, I wanted to use a user control (ASCX). This allows my to style the item once and re-use it in pop-ups or other areas of the site, not just the data list view.

The question becomes then – how do I pass data "down" to the user control? The answer turned out to be to easy – you don't have to do anything! That's right, the containing DataList gets bound to data. The user control then can pluck fields from the "data row" (each item in the bound list of the parent) by using the syntax Eval("{some property}")

So the steps are:

  1. Create your user control (MiniItem.ascx)
  2. Register the user control in the hosting ASPX page
  3. Include the user control in the item template of your data bound control

The user control is an .ascx file, but change it to just inherit from System.Web.UI.UserControl. This is MVC so code behind is left behind..

<%@ Control Language="C#" Inherits="System.Web.UI.UserControl" %>
<fieldset>
    <legend>Oh Goodie!</legend>
    <p>
        Product ID:
        <%#Eval("ProductID") %>
    </p>
    <p>
        Title:
        <%#Eval("Title") %>
    </p>
    <img src='/Content/ProductImages/<%#Eval("ImagePath") %>' alt='Image Path' />
    <p>
        Description:
        <%#Eval("Description") %>
    </p>
</fieldset>

Your host ASPX file will need to register your control type in order to use it, so up at the top you place:

<%@ Register Src="MiniItem.ascx" TagName="MiniItem" TagPrefix="uc1" %>

Now you can use the user control simply by adding it to the ItemTemplate tag:

<asp:DataList runat="server" ID="dataList" RepeatColumns="4" RepeatDirection="Horizontal">
    <ItemTemplate>
        <uc1:MiniItem ID="MiniItem1" runat="server" />
    </ItemTemplate>
</asp:DataList>

There you have it. You can use the good concepts of ASPX and the controls and visual components you are familiar with. While HTML helpers and fluent interface libraries are popping up, some find it more convenient and easy to use the "old" familiar ASPX controls. There are some good reasons to learn new things and try new framework or software paradigms. However, we can also leverage many of the successful declarative features of ASPX as a templating engine to achieve rapid development and modular UI.



  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

MVC, helpers and classic ASP.NET data bound controls – Better Together

A lot of hype around MVC these days. So, of course, yours truly is working on some project utilizing MVC. While brushing the dust off my raw HTML tag memory and designing the obvious: lists, grids, repeated item displays and the such, I thought "why not use the asp.net controls instead?"

For one, most of the ASP.NET data bound controls have a rich site of event post backs to hook up. MVC says: no dice! You can't rely on the event dispatch loop of asp.net. In fact, this is the whole point of going MVC – to create a simple, well separated delineation between the presentation and the BL. If you have all these states and post back logic pieces all in the code behind you really have a tightly coupled application.

What *is* available though, is the rendering of most controls. So instead of "for each" and "if" statements sprinkled in the "presentation" template, you can actually just use the plain old asp.net controls declaratively. I put "presentation" in quotation marks because the more code (branching is code!) you have in the View, the more brittle it becomes, the more tightly coupled to BL it is and the less testable it is.

The main advantages I find in using the old controls is that:

  1. Familiarity – My developers know them already
  2. Rich – Theming, localization behavior and layout aspects built in and available
  3. Well tested – These controls have been around a while, and are generally well behaved
  4. Modular – The controls isolate the presentation of a particular element and divorce it from the surrounding. In particular, it avoids issues of nesting and other inline logic in the presentation layer.

The main issue to overcome in a DataBoundControl is that with no code behind, how do you specify the data source declaratively? How do you do so with minimum code and maximum flexibility?

One solution is to use a data source object. Yes, they work. In most scenarios you can use them as you did before, but you must note that hooking up events (OnSelecting, OnSelected and the such) would again be challenging to do declaratively.

My approach for my project was to create an extension method for

DataBoundControl has a property "DataSource", to which you assign an object that will be data bound. The most permissive base object System.Object, so we simply create an extension method:

 

using System.Web.UI.WebControls;

public static class DataboundControlExtensions
{
    /// <summary>
    /// Extends <typeparamref name="System.Object"/> to bind it to a <typeparamref name="System.Web.UI.WebControls.DataList"/>
    /// </summary>
    /// <param name="data">The data source object to bind.</param>
    /// <param name="control">The control to bind the data source object to.</param>
    public static void BindTo(this object data, DataList control)
    {
        control.DataSource = data;
        control.DataBind();
    }

    /// <summary>
    /// Extends <typeparamref name="System.Object"/> to bind it to a <typeparamref name="System.Web.UI.WebControls.ListView"/>
    /// </summary>
    /// <param name="data">The data source object to bind.</param>
    /// <param name="control">The control to bind the data source object to.</param>
    public static void BindTo(this object data, ListView control)
    {
        control.DataSource = data;
        control.DataBind();
    }
}

Note that the control is passed in as the target and is strongly typed. As it turns out, you get a runtime error if you attempt to specify the control parameter typed as DataBoundControl – the base class for all data bound controls. In other words, this doesn't work:

public static void BindTo(this object data, DataBoundControl control) // Runtime error!

With the extension included in my project, I can now add the control and  bind it in one code line:

<% Model.BindTo(dataList); %>
<asp:DataList runat="server" ID="dataList" RepeatColumns="2" RepeatDirection="Horizontal">
    <ItemTemplate>
        <fieldset>
            <legend>
                <%# Eval("ID")%></legend>
            <p>
                Title:
                <%#Eval("Title") %>
            </p>
            <a href='<%#Eval("ImagePath") %>'>
                <img src='<%#Eval("ThumbPath") %>'  height="64" width="48" alt="pic"/></a>
            <p>
                Description:
                <%#Eval("Description") %>
            </p>
        </fieldset>
    </ItemTemplate>
</asp:DataList>

This is not as clean as completely declarative binding, but is much cleaner than having loop and branch constructs all over your view.

Most of you would note that the current MVC release includes HTML helpers. The Futures release is promising several more HTML helpers, which would provide with single line calls that would render lists, and other data bound presentation we are accustomed to. The reasons I didn't use the futures HTML helper methods are:

  1. The futures were not in release yet at time
  2. I don't love the mode in which the HTML helpers work
  3. The HTML helpers are not as rich as the asp.net components

The reason I don't love the HTML helpers is simple: they are string valued functions. As string valued functions, they must, internally generate strings and throw away memory. Even when you use StringBuilder, the repetitive appendage of strings creates discarded buffers in the underlying byte array. Asp.Net controls, on the other hand, have access to the underlying output stream via a TextWriter. This means that the appended string snippets do not create intermediary buffers but rather get copied more efficiently to the actual byte stream that would be shipped to the browser.

So if I need to add an HTML helper to MVC what I do is write an extension method that extends System.Web.MVC.ViewPage, like so

using System.Web.Mvc;
using System.Web.UI;

public static class HelloKittyHelper
{
    public static void Meow(this ViewPage page, string text)
    {
        HtmlTextWriter writer = new HtmlTextWriter(page.Response.Output);
        if (writer != null)
        {
            writer.RenderBeginTag(HtmlTextWriterTag.Pre);
            writer.Write(KITTY_ASCII);
            writer.Write(text);
            writer.RenderEndTag();
        }
    }
    /// <summary>
    /// ASCII art of a kitty - source unknown.
    /// </summary>
        private const string KITTY_ASCII = @"
  .-. __ _ .-.
  |  `  / \  |
  /     '.()--\
 |         '._/
_| O   _   O |_
=\    '-'    /=
  '-._____.-'
  /`/\___/\`\
 /\/o     o\/\
(_|         |_)
  |____,____|
  (____|____)
";
}

Then pass it the data from the Model or anything you like from the view:

<%
   1:  this.Meow("purrr.. meow");  
%>

With the ambient objects in the page, I just extend "this", and internally utilize the HtmlTextWriter to write directly to the stream – no intermediary StringBuilder and hopefully less wasted immutable objects. The other advantage is that HtmlTextWriter can do things like begin/end tag tracking, add attributes and encode HTML as necessary. Leveraging existing well tested framework again, reducing costs of testing and education to deliver value early and often.

 

In conclusion, we can use the new MVC concepts and remain true to the separation of view and logic by leveraging existing components and developing minimal custom extensions that help us avoid the pitfalls of "presentation logic".



  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Localize your MVC with ease.

MVC seems all the rage these days. And while there are many good things it brings to the table, it seams it takes us a step back in terms of I18N.

For instance, if you want to use the special aspx attribute meta:resourceKey="foo", you won't always be able to do so.

The following would work fine:

   1: <asp:Label runat="server" ID="_QueryPrompt" Text="Enter Query" meta:resourcekey="_QueryPrompt" />&nbsp;

But we're out of luck with buttons:

   1: <asp:Button runat="server" ID="btn" Text="Run" meta:resourcekey="_SubmitQuery" />

At runtime, you will get an exception explaining you need a FORM with a runat="Server". Ugh.

 

After some spelunking I came across this discussion, which basically suggests creating an extension to the System.Web.Mvc.HtmlHelper class. The discussion is thick with issues, specifically that if a UserControl is used, finding it's path in order to get to it's local resource requires all manners of digging around compilation and application with fairly extensive branching and parsing. Ultimately, the extension is complicated by attempting to combine both a resource retrieval, fallback to global from local resource and formatted template substitution in one. A good helper – if the kinks are worked out.

So I wrote my own syntactic sugar to do the same:

   1: public static string Localize(this System.Web.UI.UserControl control, string resourceKey, params object[] args)
   2: {
   3:     string resource = (HttpContext.GetLocalResourceObject(control.AppRelativeVirtualPath, resourceKey) ?? string.Empty).ToString();
   4:     return mergeTokens(resource, args);
   5: }
   6:  
   7: public static string Localize(this System.Web.UI.Page page, string resourceKey, params object[] args)
   8: {
   9:     string resource = (HttpContext.GetLocalResourceObject(page.AppRelativeVirtualPath, resourceKey) ?? string.Empty).ToString();
  10:     return mergeTokens(resource, args);
  11: }
  12:  
  13: private static string mergeTokens(string resource, object[] args)
  14: {
  15:     if (resource != null && args != null && args.Length > 0)
  16:     {
  17:         return string.Format(resource, args);
  18:     }
  19:     else
  20:     {
  21:         return resource;
  22:     }
  23: }

It is substantially shorter and defers to a base class. System.Web.MVC.ViewUserControl inherits from System.Web.UI.UserControl, so the call is true to it's application. I also extend System.Web.UI.Page.

Lastly, there is the issue of a global resource. Since these resources are compiled and accessed at design time using dot notation (MyGlobalRes.MyKey) I felt that providing an extra function would not significantly shorten code or simplify developer's life. That is, given a resx file in the App_GlobalResources containing the file Zones.resx, containing a key Zone1 one would simply write out

   1: <%= Resources.Zones.Zone1 %>

or – if your resource is a template requiring tokens to be merged:

   1: <%= String.Format(Resources.Zones.Zone1,"foo",11) %>

Happy MVC Internationalization, localization and globalization!



  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Save The Date: time_t 1234567890

On Friday, February 13th 23:31:30 UTC 2009 the time_t structure would contain the the number 1234567890 The time_t is measures seconds past midnight of January 1 1970 (see Unix Epoc, POSIX time etc)

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati