Noocyte’s Weblog

October 10, 2011

Howto use configurable rolenames to authorize attribute

Filed under: Work — Tags: , — noocyte @ 12:40

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

October 4, 2011

MVC 3, EF 4.1 and some more…

Filed under: Work — Tags: , — noocyte @ 9:33

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.

February 1, 2008

Brad Abrams : ASP.NET MVC Example Application over Northwind with the Entity Framework

Filed under: Link — Tags: , — noocyte @ 14:53

Nice! I really, really wanna look into ASP.Net MVC. I haven’t done any ASP.Net development in years, so I sort of miss it. But then I really wanna learn WPF and WCF too… So there you have it! 

Link to Brad Abrams : ASP.NET MVC Example Application over Northwind with the Entity Framework

December 7, 2007

Rob Conery » ASP.NET MVC: Using RESTful Architecture

Filed under: Link, Work — Tags: , , , — noocyte @ 16:39

REST looks interesting, but not 100% sure I really get the value-prop from it.  

Link to Rob Conery » ASP.NET MVC: Using RESTful Architecture

November 14, 2007

ASP.NET MVC Framework (Part 1) – ScottGu’s Blog

Filed under: Link — Tags: , , — noocyte @ 13:24

Might be interesting, but not for Synergi, we’re basically using our own framework to do this… 

Link to ASP.NET MVC Framework (Part 1) – ScottGu’s Blog

Blog at WordPress.com.