Monthly Archives: October 2011

ValueInjecter and Expression Magic

In a previous post I have talked some about how I use AutoMapper and I’m using it for all my “Entity To View” model mappings; works like a charm! But what it does not do is to map the other way; ie. take whatever comes from the view and apply that to an entity model. There are some discussions online on the ‘correctness’ of doing this, but I found it to be an easy and productive technique.

But since AutoMapper doesn’t handle this I had to write a lot of LHS-RHS code, right? No I didn’t! Somebody else have already solved this problem in a utility called ValueInjecter. Basically it’s capable of injecting values from one object to another, and this of course is exactly what I need! So how do I use it;

var entityObject = db.GetEntity(viewObject.UniqueId);
entityObject.InjectFrom<CustomInjectionRules>(viewObject);
entityObject.State = EntityState.Modified;
db.Store(entityObject);

The magic happens on line number two; the InjectFrom method will transfer data from my viewObject to the entityObject. The method can be used without specifying a type (generics) to assist in the injection, but I need it to allow for data type and naming variations between the two objects. The CustomInjectionRules class handles those two issues and looks a little like this:

public class CustomInjectionRules : ConventionInjection
   {
       protected override bool Match(ConventionInfo c)
       {
           return c.SourceProp.Name.Equals(“ViewProp”) && c.TargetProp.Name.Equals(“EntityProp”);
       }

       protected override object SetValue(ConventionInfo c)
       {
           return Convert.ToInt32(c.SourceProp.Value);
       }

   }

The class inherits from “ConventionInjection” and overrides two methods; one for matching properties with unequal names and the second for converting between whatever “ViewProp” is and int32 (“EntityProp”).

After writing this code I made sure it worked and then came back to look at it; could I improve it? Refactor it somehow? Not much code in there, so my first instinct was; No, this is fine. But then I looked hard at the “Magic Strings” (“ViewProp”/”EntityProp”)… I do not like magic strings! No refactor/compile time support and all that nonsense. So I had to find a better solution! I immediately thought of another blog post I’d done some time ago; MVC 3, EF 4.1 And Some More… The HtmlHelper methods appear to just take a lambda expression as input and then figures out the name of the property! Which of course is exactly what I needed! So I started Googling… I found a few examples, but they weren’t spot on before I found a question on StackOverflow! Spot on! I did some minor adjustments and not my CustomInjectionRules class looks like this:

public class EvaluationRuleTypeInjection : ConventionInjection
{
    protected override bool Match(ConventionInfo c)
    {
        return c.SourceProp.Name.Equals(GetMemberInfo<ViewObject>(r => r.ViewProp))
                && c.TargetProp.Name.Equals(GetMemberInfo<EntityObject>(r => r.EntityProp));       
    }

    protected override object SetValue(ConventionInfo c)
    {
        return Convert.ToInt32(c.SourceProp.Value);
    }

    private string GetMemberInfo<T>(Expression<Func<T, object>> method)
    {
        LambdaExpression lambda = method as LambdaExpression;
        if (lambda == null)
            throw new ArgumentNullException(“method”);

        MemberExpression memberExpr = null;

        if (lambda.Body.NodeType == ExpressionType.Convert)
            memberExpr = ((UnaryExpression)lambda.Body).Operand as MemberExpression;
        else if (lambda.Body.NodeType == ExpressionType.MemberAccess)
            memberExpr = lambda.Body as MemberExpression;

        if (memberExpr == null)
            throw new ArgumentException(“method”);

        return memberExpr.Member.Name;
    }
}

Awesome! I immediatly moved the “GetMemberInfo” method out of this class and into a more appropriate class, but included it here to avoid expanding all the code…

Pretty happy about this change. Also loving how easy it is to get stuff such as ValueInjecter into my prosjects using nuget.

GoodleAdz

Reading Gisle Hannemyrs latest blog post on GoodleAdz I’ve been thinking if there might be something more to this… What if I became a member and had Google Ads on my page? And presumably GoodleAdz has quite a few members; if they’re all looking at my page once a day that will eventually become quite a few pageviews, will it not? I’m not saying this is a good idea, it really isn’t, but interesting thought though…

AutoMapper, aka AutoMagic

 

Update 27.10.2011: It turns out that the implementation below is not really all that good. The map created with the custom resolver will be cached; so all future results from a mapping process will use the initial value (enityTwoId). I reverted to ignoring the property during the mapping and then setting it manually afterwards.

We are currently working on a re-write of an application here at Proactima and in that process I’ve decided to use EF 4.1 Magic Unicorn Edtion as my backend. It supports POCOs, but sometimes I don’t really wanna send the whole object to the view; so I create some view specific classes to use for this purpose. Mapping between the entity class and the view class would be tedious work was it not for the magic of AutoMapper! It handles the RHS-LHS mapping for me! How cool! But sometimes even magic needs a helping hand and AutoMapper accepts it!

These are my entity classes (not the actual classes…):

public class EntityOne
{
    public int EntityOneID { get; set; }
    public string Title { get; set; }
    public virtual ICollection<EntityTwo> EntityTwos { get; set; }
}

public class EntityTwo
{
    public int EntityTwoID { get; set; }
    public string SomeInformation { get; set; }
    public int EntityOneID { get; set; }
    public virtual EntityOne EntityOne { get; set; }
}

And these should be mapped to these classes:

public class EntityOneView
{
    public int EntityOneID { get; set; }
    public string Title { get; set; }
    public virtual EntityTwoView EntityTwo { get; set; }
}

public class EntityTwoView
{
    public int EntityTwoID { get; set; }
    public string SomeInformation { get; set; }  
}

Basically I only bring with me one of the “EntityTwoView” objects, as opposed to a list in the entity class. Naturally in an actual application the classes would be FAR more complex than these, but I needed this to illustrate the point. I find it easier to understand code where there is little or no noise.

Given an “EntityOne” object I now want to map/convert it to an “EntityOneView” object before sending it of the the view (from the controller in ASP.Net MVC). If I didn’t have to list->one issue I could simply write these two lines:

EntityOne one = db.Load<EntityOne>(1);
Mapper.CreateMap<EntityOne, EntityOneView>();
EntityOneView oneView = Mapper.Map<EntityOneView>(one);

But this will fail since AutoMapper have no idea on how to go from a list of EntityTwo’s to a single EntityTwo. So I have to help her (?) out a bit. I can do that by writing a Custom Value Resolver. It would for this code look like this:

public class SingleLineResolver : ValueResolver<EntityOne, EntityTwoView>
{
    private int EntityTwoId { get; set; }
    public SingleLineResolver(int entityTwoId)
    {
        this.EntityTwoId = entityTwoId;
    }

    protected override EntityTwoView ResolveCore(EntityOne source)
    {
        Mapper.CreateMap<EntityTwo, EntityTwoView>();
        var line = source.EntityTwos.First(e=> e.EntityTwoID == this.EntityTwoId);
        return Mapper.Map<EntityTwoView>(line);
    }
}

This code took me awhile to understand and be able to write… Now I might be stupid and you smart, so perhaps I’m the only one struggeling with this one… But to make use of it I had to update the previous code to:

EntityOne one = new EntityOne();
SingleLineResolver resolver = new SingleLineResolver(2);
Mapper.CreateMap<EntityOne, EntityOneView>()
    .ForMember(dest => dest.EntityTwo, opt => opt.ResolveUsing(resolver));
EntityOneView oneView = Mapper.Map<EntityOneView>(one);

Here I am basically saying that when you (AutoMapper) create the mapping between EntityOne and EntityOneView and come to the “EntityTwo” property (on the EntityOneView object) please use my custom value resolver (resolver) to figure out the value of that property. It will then send the “one” object into my custom value resolver class (SingleLineResolver) and the output will be set as the value of the property called “EntityTwo” on the new object of type “EntityOneView”; Puh!

Basically AutoMapper let’s me use two objects (or more!) that are fairly similar and map between them. She (?) will handle complex scenarios like this and much, much more. I hereby dub the project “AutoMagic”.

Please note that the code I present here has been severly altered from the actual production code, so please don’t shoot me if it fails to work as expected!

Howto use configurable rolenames to authorize attribute

For one of my ASP.Net MVC 3 projects I make heavy use of the “[Authorize(Roles=…)]” syntax, but the fact that I have to type in the rolename there always rubbed me the wrong way. I started to experiment to see if I could perhaps use some code to get the rolename from configuration or something. By default I could not, but it was possible to inherit from the Authorize attribute and create my own to make this possible. And so that’s what I did, here is the code:

public class SecureAttribute : AuthorizeAttribute
{
     public SecureAttribute() : this(true)
     {
     }

     public SecureAttribute(bool requireAdmin) : base()
     {
          if (requireAdmin)
          {
               this.Roles = Configuration.AdminRoleName;
          }
     }
}

To use it:

[Secure]
public abstract class SecureController : Controller

Basically all I do is add two constructors to enable me to set the “Roles” property to whatever I have configured it to be. Now, this code is tailor to my specific project, so you wanna change stuff to match your requirements. Please also note that I use a “SecureController” that all my Controllers inherit from if they require Admin access. I did this to save exactly one line of code on all of my controllers! So instead of inheriting from just “Controller” and adding the “Secure” attribute they just inherit from “SecureController”, which has the attribute and inherits from “Controller”. Perhaps a bit over the top, but you never know; one day I might add some more stuff here.

If anyone can see anything wrong with this implementation, please let me know! I am fairly new to MVC and the ASP.Net Membership stuff… Smilefjes

MVC 3, EF 4.1 and some more…

So I’ve begun work on a new application, using ASP.Net MVC 3 (with Razor) and Entity Framework 4.1 (Code First). So far it looks like a good combo of technology, some head-aches and obstacles, but with the help of Google I’ve found my way through them all.

Earlier today I needed to do an “if check” before printing some data on a page, so I did something like this:

@if(!String.IsNullOrEmpty(item.Compliant))
                @Html.DisplayFor(modelItem => item.Deadline, Model)
            }

And then on the next line I did the exact same, but for a different property (ie. not “Deadline”). I felt a slight pain as I repeated myself (ie. the if test) and started to look at how to avoid that. I tried a number of different things, all documented below.

1. Custom code to do check and return value

My first attempt was to just take the code out of the view and put it in a static class. The code looked a little like this:

public static string DisplayBasedOnCompliantStatus(SomeClass eval, string displayText)
{
    if (!String.IsNullOrWhiteSpace(eval.Compliant) && eval.Compliant.Equals(“Yes”, StringComparison.InvariantCultureIgnoreCase))
        return displayText;

    return String.Empty;
}

This code worked as expected, but the return value was a string, so I lost the dataformatting of the input value (DateTime). So i figured there had to be a better way…

2. Reuse of “DisplayFor” extension methods

For my next attempt I tried to take as input whatever I needed to use to call the “Html.DisplayFor” method I used in the view code. One of my attempts looked a little like this:

public static MvcHtmlString DisplayOnlyIfCompliant<TValue>(HtmlHelper<TModel> html, TModel model, Expression<Func<TModel, string>> compliantExpression, Expression<Func<TModel, TValue>> expression)
{
    Func<TModel, string> deleg = compliantExpression.Compile();
    var compliant = deleg(model);
    if (!String.IsNullOrWhiteSpace(compliant) && compliant.Equals(“Yes”, StringComparison.InvariantCultureIgnoreCase))
    {
        return html.DisplayFor(expression);
    }

    return new MvcHtmlString(null);
}

This I could never make work, not even compile, but I felt as if I was on the right track.

3. Create another extension method

For my third attempt I had a very close look at the orignal method (“Html.DisplayFor”) and suddenly realized that it was an extension method and I could probably create another extension method myself! So the third attempt looks like this:

public static MvcHtmlString DisplayFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression, SomeClass model)
        {
            if (!String.IsNullOrWhiteSpace(model.Compliant) && model.Compliant.Equals(“Yes”, StringComparison.InvariantCultureIgnoreCase))
            {
                return html.DisplayFor<TModel, TValue>(expression);
            }
            return new MvcHtmlString(null);
        }

And what-do-you-know? It works! To use it all I had to do was this:

@Html.DisplayFor(modelItem => item.Deadline, Model)

But when looking at the code I can see that it’s a little less flexible than it could have been. What if I need the same functionality for another property beside “Compliant”? Then I have to create another method, rename the original (it already has a bad name!) and then I’m back to repeating myself! So a fourth attempt should be tried!

4. generic Extension method

My final requirement is that the extension method can handle any model to check for null-string. This meant that I had to take the model specific code out of my extension method and add another parameter to be able to define the property to check for null-string. The code looks like this:

    public static MvcHtmlString DisplayFor<TModel, TValue>(
        this HtmlHelper<TModel> html,
        Expression<Func<TModel, TValue>> expression,
        Expression<Func<TModel, string>> compliantExpression,
        TModel model)
    {
        var compliant = compliantExpression
                               .Compile()
                               .Invoke(model);

        if (!String.IsNullOrWhiteSpace(compliant) && compliant.Equals(“Yes”, StringComparison.InvariantCultureIgnoreCase))
        {
            return html.DisplayFor<TModel, TValue>(expression);
        }
        return new MvcHtmlString(null);
    }
}

And in use:

@Html.DisplayFor(m => item.PropertyToDisplay, c => item.PropertyToCheck, Model)

I guess it would be possible to do a more generic “null check”, so let’s make a fifth attempt…

5. 100% Pure Generic Extension Method

The final step in making the extension method 100% pure from any “non-generic noise” is to remove the “string” part in the “compliantExpression” input definition. There is really just one obstacle to make that happen; I need a generic null check. I tried using “IComparable” and requiring the input type to inherit from it, but this caused some issues when it was null (NullReferenceException). So I had to do a som Googling and found a great question on Stackoverflow that helped me out! Turns out I can write the method like this:

public static MvcHtmlString DisplayFor<TModel, TValue, TCheck>(
this HtmlHelper<TModel> html,
            Expression<Func<TModel, TValue>> expression,
            Expression<Func<TModel, TCheck>> compliantExpression,
            TModel model)

{
            TCheck compliant = compliantExpression
                            .Compile()
                            .Invoke(model);

            if (!Equals(compliant, default(TCheck)))
            {
                return html.DisplayFor<TModel, TValue>(expression);
            }
            return new MvcHtmlString(null);
        }
}

And of course no need to adjust how we call the method, since types are inferred when using expressions (I guess?).

There is however a serious issue with the extension method now; I’ m only testing for “null”, not for an actual value compare, which of course I need… So, enter attempt number six.

6. 100% Pure Generic Extenstion Method with compare function

I had to make it possible to compare the actual value with a provided value, such as “Yes” or “1”. To do this I needed to add a parameter to the method enabling the caller to input a function to compare the value of “valueExpression” with a caller defined value. It now looks like this:

public static MvcHtmlString DisplayForIfEqual<TModel, TValue, TCheck>(
       this HtmlHelper<TModel> html,
          Expression<Func<TModel, TValue>> valueExpression,
          Expression<Func<TModel, TCheck>> checkExpression,
          Func<TCheck, bool> compareFunction,
          TModel model)
       {
           TCheck checkValue = checkExpression
                              .Compile()
                              .Invoke(model);

           if (!Equals(checkValue, default(TCheck)) && compareFunction(checkValue))
               return html.DisplayFor<TModel, TValue>(valueExpression);
           return new MvcHtmlString(null);
       }

To call it:

@Html.DisplayForIfEqual(
m => item.SomeDisplayProperty,
c => item.SomeCheckProperty,
m => m.Equals(“No”, StringComparison.InvariantCultureIgnoreCase),
Model)

A curiosity is that the “m” variable does not give you IntelliSense in Visual Studio today. I was puzzled by this, but no big deal really.

There might be some issues with the “Equals” method in the null-check (like boxing), but for now I’ll be using this method.