Learn How to Use IDcitionary<,>.TryGetValue!

I'm going nuts every time I see the code similar to the following snippet.

/* Given:
 * IDictionary<TKey, TValue> dictionary;
 * TKey key;
 */
if (dictionary.ContainsKey(key) 
{
    var value = dictionary[key];
    // do something with retrieved value
}

You should really use TryGetValue instead:

/* Given:
 * IDictionary<TKey, TValue> dictionary;
 * TKey key;
 */
TValue value;
if (dictionary.TryGetValue(key, out value) 
{
    // do something with retrieved value
}

And here is a couple of reasons why:

  • It is more performant as the location of the value calculated only once. And in fact implementation of ContainsKey, Item and TryGetValue is exactly the same.
  • In the first example the dictionary could be changed between ContainsKey and Item method calls, and the retrieving of the item could fail in multi-threaded environment.

I was so crazy about this, so couple of month ago I wrote a plugin for ReSharper which can analyze and optimize such subsequent calls.

Solving DropDown list in ASP.NET MVC with MvcExtensions

This is an translation of my article from 2nd April of 2012.

From the first version of ASP.NET MVC couple of years ago I found that there is no common solution how to display drop down lists properly. Probably every of you asked yourself: “How to pass the selection list to a drop down list?” And so I was asking the same question to myself, I could not even sleep;)

Introduction

For example we have an form to create a film, and we need to select film's genre from a drop down list. I'm not going to show any "newbuy" solutions as, for instance, getting the genres in the view file.

"Head on" solution

The programmers bumping that problem try to solve it by brute force: they create additional property "Genres" of type SelectList at the model class, and they fill it at the controller's action. Like this:

The model

public class Movie {
    public int GenreId { get; set; }
    public SelectList Genres { get; set; }    
    //...
} 

The controller

public class MoviesController {
    [HttpGet] public ActionResult Create() {
        var model = new Movie() { Genres = GetAllGenresFromDatabase(); }
        return View(model); 
    }

    [HttpPost] public ActionResult Create(Movie form) {
        // do something with movie.
    }

    [HttpGet] public ActionResult Edit(int id) {
        var model = GetMovieFromDatabase();
        model.Genres = GetAllGenresFromDatabase(); 
        return View(model); 
    }

    [HttpPost] public ActionResult Edit(EditMovie form) {
        // do something with movie.
    }
    //...
}

This works so far, but the solution has some major problems

  1. Model has redundant fields
  2. Need to create a model for a creation form (when there is no entity in DB yet)
  3. Code duplication for select list options retrieval logic. This problem grows if you need to select form the same list in many places.
  4. Not possible to use Html.EditorForModel() to display all you form at once with auto-generated markup, as we do not have access to neighbour fields when ASP.NET renders the model

Solution using ViewBag / ViewData

The solution is similar to the previous one with one simple change: selection list is passing through ViewBag / ViewData

The model

public class Movie {
    [UIHint("Genres")]
    public int GenreId { get; set; }
    //...
}

The controller

public class MoviesController {
    [HttpGet] public ActionResult Create() {
        ViewBag.Genres = GetAllGenresFromDatabase();
        return View(); 
    }

    [HttpPost] public ActionResult Create(Movie form) {
        // do something with movie.
    }

    [HttpGet] public ActionResult Edit(int id) {
        var model = GetMovieFromDatabase();
        ViewBag.Genres = GetAllGenresFromDatabase(); 
        return View(model); 
    }

    [HttpPost] public ActionResult Edit(EditMovie form) {
        // do something with movie.
    }
    //...
}

Pros over the previous solution

  1. The model does not have redundant fields
  2. Not needed to create a model for a creation form (when there is no entity in DB yet)
  3. Possible to use Html.EditorForModel() with own Editor Template for every drop-down list field

Cons

  1. Using of the dynamics or magic-strings*, which complicates refactoring and code modification
  2. Code duplication for select list options retrieval logic
  3. Custom editor template per field

Improved solution with ViewBag / ViewData

To improve the solution and reduce code duplication of retrieving of selection options logic we move the code from the controller action to an action filter

The model

The same as in the previous example

ActionFilter

public class PopulateGenresAttribute: ActionFilterAttribute {
    public override void OnActionExecuted(ActionExecutedContext filterContext) {
        filterContext.Controller.ViewData["Genres"] = GetAllGenresFromDatabase();
    }
    //...
}

The controller

public class MoviesController {
    [HttpGet, PopulateGenres] public ActionResult Create() {
        return View(); 
    }

    [HttpPost] public ActionResult Create(Movie form) {
        // do something with movie.
    }

    [HttpGet, PopulateGenres] public ActionResult Edit(int id) {
        var model = GetMovieFromDatabase();
        return View(model); 
    }

    [HttpPost] public ActionResult Edit(EditMovie form) {
        // do something with movie.
    }
    //...
}

Pros over the previous solution

  1. No code duplication for select list options retrieval logic

Cons

  1. Using of the dynamics or magic-strings*, which complicates refactoring and code modification
  2. Custom editor template per field
  3. Application specific logic in the filter, which smells

Imporved solution with ViewBag / ViewData + MvcExtnsions

MvcExtensions have beautiful methdos to work with drop down lists: AsDropDownList / AsListBox (the first one for drop down list and the second one for multi-select lists). These are extension methods for model metadata builder. These methods set the template and allow to pass the ViewData's field name which stores the selection list to the View. So we are solving the need of having an template per field.

The model

public class Movie {
    public int GenreId { get; set; }
} 

The metadata

public class MovieMetadata : ModelMetadataConfiguration {
    public MovieMetadata {
        Configure(movie => movie.GenreId).AsDropDownList("Genres"/*шаблон*/);
    }
}

The controller

The same as in the previous example

Pros over the previous solution

  1. Using of two generic templates (DropDownList / ListBox) for all lists, or specific one if needed

Cons

  1. Using of the dynamics or magic-strings*, which complicates refactoring and code modification

The solution with ChildAction

This is a good idea to put logic of the selection list to a separate action. This will lead to better separation of concern and give you some benifits like caching. But yf you'll try to use just a child action, then it'll not work at all: you will not have client-side validation from the box, you will not be able to use nested forms, etc., because the field names will be broken. To make it work properly you need to set view data's model metadata to the same as in parent action.

The model

public class Movie {
    [UIHint("Genres")]
    public int GenreId { get; set; }
} 

The controllers

public class MoviesController {
    [HttpGet] public ActionResult Create() {
        return View(); 
    }

    [HttpPost] public ActionResult Create(Movie form) {
        // do something with movie.
    }

    [HttpGet] public ActionResult Edit(int id) {
        var model = GetMovieFromDatabase();
        return View(model); 
    }

    [HttpPost] public ActionResult Edit(EditMovie form) {
        // do something with movie.
    }
}
public class GenresController {
    public ActionResult List() {
        var selectedGenreId = this.ControllerContext.ParentActionViewContext.ViewData.Model as int?;

        var genres = GetGenresFormDatabase();

        var model = new SelectList(genres, "Id", "DisplayName", selectedGenreId);

        this.ViewData.Model = model;
        this.ViewData.ModelMetadata = this.ControllerContext.ParentActionViewContext.ViewData.ModelMetadata;

        return View("DropDown");
    }
}

Pros over the previous solution

  1. No using of dynamics and magic-strings
  2. No code duplication of select list options retrieval logic
  3. No application specific logic in ActionFilter

Cons

  1. Duplication of the boilerplate code
  2. Custom template per select list
  3. The Post-Redirect-Get scenario is not supported

Solution using ChildAction + MvcExtensions

I decided to imporve the previouse solution and apply the ActionFilter experience, and now, from the version 2.5.0-rc8000 MvcExtension do support child-action based drop down lists out of the box. I've added extension methods, which allows to use RenderAction to render the model fields. Also SelectListActionAttribute attibute were added, which serves the action providing selection list data. Also this solution supports Post-Redirect-Get scenario.

The model

public class Movie {
    public int GenreId { get; set; }
}

The metadata

public class MovieMetadata : ModelMetadataConfiguration {
    public MovieMetadata {
        Configure(movie => movie.GenreId).RenderAction("List", "Genres");
    }
}

The controllers

public class MoviesController {
    [HttpGet] public ActionResult Create() {
        return View(); 
    }

    [HttpPost] public ActionResult Create(Movie form) {
        // do something with movie.
    }

    [HttpGet] public ActionResult Edit(int id) {
        var model = GetMovieFromDatabase();
        return View(model); 
    }

    [HttpPost] public ActionResult Edit(EditMovie form) {
        // do something with movie.
    }
}
public class GenresController {
    [ChildActionOnly, SelectListAction] public ActionResult List(int selected) {
        var model = GetGenresFormDatabase(selected);
        return View("DropDown", model);
    }
}

Pros over the previous solution

  1. No boilerplate code duplication
  2. Use an generic template
  3. MultiSelect "out of the box"
  4. Post-Redirect-Get is supported

Ending

For me, as a developer of MvcExtensions the methdos using the library is preferrable.

The sample of code with ViewBag / ViewData + MvcExtensions is here: http://github.com/MvcExtensions/Core/tree/master/samples

The sample of code with ChildAction + MvcExtensions is here: http://github.com/hazzik/DropDowns


*magic-strings can be easily solved by using of constans, and so because of that, I prefere using string over dynamic properties.

PS: The MvcExtensions abilities to extend ASP.NET MVC are limitless

Render Action Attribute

The purpose of this attribute is to be able to render action as an editor or display template for your form fields. First of all we will need the data structure which will hold options for the our editor template.

RenderActionOptions.cs

public class RenderActionOptions 
{
    public static string MetadataKey = "RenderActionOptions";

    public string Action { get; set; }
    public string Controller { get; set; }
    public string Area { get; set; }
}

Then we can use custom attribute, which implements IMetadataAware interface, to fill the options and pass them to a metadata.

RenderActionAttribute.cs

public class RenderActionAttribute : Attribute, IMetadataAware
{
    public RenderActionAttribute([AspMvcAction] string action)
    {
        Action = action;
    }

    public RenderActionAttribute([AspMvcAction] string action, [AspMvcController] string controller)
    {
        Action = action;
        Controller = controller;
    }

    public RenderActionAttribute([AspMvcAction] string action, [AspMvcController] string controller, [AspMvcController] string area)
    {
        Action = action;
        Controller = controller;
        Area = area;
    }

    public string Action { get; set; }
    public string Controller { get; set; }
    public string Area { get; set; }

    public void OnMetadataCreated(ModelMetadata metadata)
    {
        metadata.AdditionalValues[RenderActionOptions.MetadataKey] = new RenderActionOptions
        {
            Action = Action,
            Controller = Controller,
            Area = Area
        };
        metadata.TemplateHint = "RenderAction";
    }
}

And finally at our EditorTemplate we will retrieve the options from the metadata and use Html.RenderAction helper method to render our action. Please note, that Html.RenderAction nor Html.Action do not accept "area" as an argument, so we need to add the "area" key to our routes dictionary. Also, we pass data to the Html.RenderAction method to be able supply some additional information/metadata to the rendered action.

Shared/EditorTemplates/RenderAction.cshtml

@{
    var data = new RouteValueDictionary(ViewData);
    object o;
    ViewData.ModelMetadata.AdditionalValues.TryGetValue(RenderActionOptions.MetadataKey, out o);
    var options = o as RenderActionOptions;
    if (!string.IsNullOrEmpty(options.Area))
    {
        data["area"] = options.Area;
    }
    if (!string.IsNullOrEmpty(options.Controller))
    {
        Html.RenderAction(options.Action, options.Controller, data);
    }
    else
    {
        Html.RenderAction(options.Action, data);
    }
}

Example of Usage

MyModel.cs

public class MyModel 
{
    [Display(Name = "City"), RenderAction("ListCities", "Cities")]
    public int CityId { get; set; }
}

MyForm.cshtml

@model MyModel
// ...
@Html.EditorFor(m => m.CityId, new { htmlAttributes = new { @class = "my-editor" } } )
// ...

The blog has been moved to alexzaytsev.me

Subj

Computable properties for any LINQ provider

In this blog post I want to present a little library which I wrote a while ago. This library can decompile methods to their λ-representation.

Why

Sometimes you need to use computable properties in LINQ queries, for example you have Employee class with computable property FullName

class Employee
{
    public string FullName
    {
        get { return FirstName + " " + LastName; }
    }

    public string LastName { get; set; }

    public string FirstName { get; set; }
}

And now your manager comes to you and says that we need to have ability to search by employee’s full name. And you without any thinking write following query:

var employees = (from employee in db.Employees
                 where (employee.FirstName + " " + employee.LastName) == "Test User"
                 select employee).ToList();

Yes, with such simple property as FullName it can work, but what will you do if field would be not simple as this one? For example there is one field from one of my previous projects, and it should be queryable!

class WayPoint 
{
    // all other is skipped due to clarity reasons
    public virtual bool IsValid
    {
        get 
        {
            return (Account == null) ||
               (Role == null || Account.Role == Role) &amp;&amp;
               (StructuralUnit == null || Account.State.StructuralUnit == StructuralUnit);
        }
    }
}

This is much harder…

What do we have to solve such puzzles?

<formula> element in NHibernate

If you are using NHibernate then you can map this field as formula, but this way is full of big scare bears, and such code is hard to maintain, and the <formula> element supports only small subset of SQL, and if you are developing software which have to work with different RDBMS you have to be very-very careful.

It works only in NHibernate

Microsoft.Linq.Translations

With this great and powerful library we would rewrite our class like this

class Employee 
{
    private static readonly CompiledExpression fullNameExpression
        = DefaultTranslationOf.Property(e => e.FullName).Is(e => e.FirstName + " " + e.LastName);

    public string FullName 
    {
        get { return fullNameExpression.Evaluate(this); }
    }

    public string LastName { get; set; }

    public string FirstName { get; set; }
}
var employees = (from employee in db.Employees
                 where employee.FullName == "Test User"
                 select employee).WithTranslations().ToList()

All right, and the query looks good but the field declaration is terrible! And Evaluate compiles the λ-expression in runtime, which is no less terrible than the computable field decalaration.

And now meet my small library - DelegateDecompiler

DelegateDecompiler

The property should be marked with [Computed] attribute and it is all you need, and add .Decompile() method invocation to the query.

class Employee 
{
    [Computed]
    public string FullName 
    {
        get { return FirstName + " " + LastName; }
    }

    public string LastName { get; set; }

    public string FirstName { get; set; }
}
var employees = (from employee in db.Employees
                 where employee.FullName == "Test User"
                 select employee).Decompile().ToList()

In my opinion it is gracefully (If you don’t blow your own horn, no one will do it for you). But bear in mind that the source of your computable property should be supported using LINQ provider.

How does it work?

.Decompile() method finds all the properties and methods marked with [Computed] attribute and expand them to their source expressions. In other words the query above will become as following query:

var employees = (from employee in db.Employees
                 where (employee.FirstName + " " + employee.LastName) == "Test User"
                 select employee).ToList();

The library uses Mono.Reflection (GitHub, NuGet) as decompiler. The Mono.Reflection library is written by Jean-Baptiste Evain the creator of Mono.Cecil.

PS: This is an alpha version, use at your own risk.

Links