Wednesday 4 April 2012

SetResultTransformer into an anonymous type

The other day I was looking for a way to shortcut the SetResultTransformer and cast a list to an anonymous type rather than having to hand craft DTO classes with public properties (getters/setters). I stumbled on a GitHub Gist by Buthrakaur (Filip Kinský) that did just this.

Why would we want to do this?
  • We may want to return a few columns from an entity
  • We want to return Json from an MVC view which just gets thrown away
  • We want to cut down the amount of code that just handles redundant DTO's because we want to pass data around

The solution to this is really easy (thanks Filip), first we create an anonymous type inline and then project straight into this using an extension method .ListAs(dto)
//first create our anonymous type DTO
var dto = new { 
    Id = 0L, 
    Source = string.Empty, 
    Destination = string.Empty, 
    Is301 = false
};

//notice the ListAs(dto) extension method
var model = Session.QueryOver<CmsRedirect>()
  .SelectList(s => s
    .Select(x => x.Id).WithAlias(() => dto.Id)
    .Select(x => x.Source).WithAlias(() => dto.Source)
    .Select(x => x.Destination).WithAlias(() => dto.Destination)
    .Select(x => x.Do301).WithAlias(() => dto.Is301)
  )
  .Take(take).Skip(page * pageSize)
  .ListAs(dto);

return Json(new { Total = total, List = model }, 
    JsonRequestBehavior.AllowGet);
The source to the GIST can be found here.
public static class NHibernateExtensions {
  public static IList<TRes> ListAs<TRes>(
      this IQueryOver qry, TRes resultByExample) {

    var ctor = typeof(TRes).GetConstructors().First();

    return qry.UnderlyingCriteria
      .SetResultTransformer(
        Transformers.AliasToBeanConstructor(
         (ConstructorInfo) ctor)
        ).List<TRes>();
  }
}
And the Json that gets returned is:-
{
  "Total":3,
  "List":[
    {"Id":101000,"Source":"clients.aspx",
       "Destination":"portfolio","Is301":true},
    {"Id":101101,"Source":"consultancy.aspx",
       "Destination":"consultancy","Is301":true},
    {"Id":101102,"Source":"contact.aspx",
       "Destination":"contact","Is301":true},
  ]
}
This is perfect for plugging straight into my Kendo UI Grid.

A big thank you to Filip for taking some of the repetiveness out of my day.

No comments:

Post a Comment