Policing ActionResults

Wednesday, June 30, 2010 by K. Scott Allen
5 comments

In the previous post we looked at using unit tests and reflection to ensure every controller derived from a specific base class in an ASP.NET MVC application. You might use a base class to ensure action filters are always in place for auditing, logging, or other general purpose security and runtime diagnostics.

You can also use action filters to inspect the result of a controller action. For example, you might want to check the Url of every RedirectResult to prevent  open redirects in your application. Spammers love sites with open redirects.

Edit: thanks, Sergio for catching a copy/paste error (update to put the throw inside the if check). Sergio also pointed out the code allows redirects to non-HTTP URIs, and as shown doesn't allow a redirect to a local path (/home/index/123).

public class VerifyRedirects : ActionFilterAttribute
{
    public override void OnResultExecuting(ResultExecutingContext filterContext)
    {
        var redirect = filterContext.Result as RedirectResult;
        if(redirect != null)
        {
            var host = new Uri(redirect.Url).Host;
            if(_whiteList.Any(host.EndsWith))
            {
                return;
            }            
            throw new InvalidOperationException(BadRedirectMessage);
        }
    }

    string[] _whiteList =
        {
            "microsoft.com", "odetocode.com", "pluralsight.com"
        };

    const string BadRedirectMessage = "...";
}

In this case we are checking the URL against a white list of known destinations. If the host isn't found, the request stops with an exception.

Enforcing a Base Controller

Tuesday, June 29, 2010 by K. Scott Allen
5 comments

In the previous post we talked about using a base controller class in ASP.NET MVC. The truly paranoid will worry about new developers on the team who don't know the rules and don't use the base class. One automated solution to this problem is to write a unit test to enforce the rule.

[TestMethod]
public void AllControllersDeriveFromFootballController()
{
    var badControllers =
        GetConcreteTypesAssignableTo<IController>()
       .Where(TypeIsNotDerivedFrom<FootballController>);

    if(badControllers.Any())
    {
        var controllerNames = AggregateTypeNames(badControllers);
        

        Assert.Fail("Controllers are out of line: {0}", 
                     controllerNames);
    }            
}

The above code uses a few helper methods:

IEnumerable<Type> GetConcreteTypesAssignableTo<T>()
{
    return
        Assembly
            .GetExecutingAssembly()
            .GetReferencedAssemblies()
            .Select(name => Assembly.Load(name.FullName))
            .SelectMany(assembly => assembly.GetTypes())
            .Where(type => typeof (T).IsAssignableFrom(type))
            .Where(type => !type.IsAbstract);
}

bool TypeIsNotDerivedFrom<TBase>(Type type)
{
    return !(typeof (TBase).IsAssignableFrom(type));
}

string AggregateTypeNames(IEnumerable<Type> types)
{
    return
        types
            .Select(type => type.Name)
            .Aggregate(new StringBuilder(),
                       (sb, name) => sb.Append(name + " "))
            .ToString();
}

Of course the test isn't so simple if controllers might use different base classes (think asynchronous controllers), and I'm sure some people question the value of a test like this in any case. Right?

Action Filter versus Controller Base Class

Monday, June 28, 2010 by K. Scott Allen
4 comments

One of the features (or challenges) with ASP.NET MVC is the number of approaches you can use to successfully implement a feature. Take the "log each action method" requirement. One possible approach is to use a custom action invoker, however, an action invoker already has enough responsibilities (see Jonathon's post), and also has a fairly low level API. A custom action filter is the better choice.

public class LogAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        // ... log stuff before execution            
    }

    public override void OnResultExecuted(ResultExecutedContext filterContext)
    {
        // ... log stuff after execution
    }
}

You can use the LogAttribute on every controller.

[Log]
public class VuvuzelaController
{
    public ActionResult Detonate()
    {
        // ...
    }
}

After you've added the attribute to a few controllers, you might start wondering why you don't use a base class instead. After all, the Controller class defines virtual methods to hook into the pre and post action execution, and with this approach you won't see the [Log] attribute on every controller.

public class LoggingController : Controller
{
    protected override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        // ... log stuff before execution               
    }

    protected override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        // ... log stuff after execution
    }
}

Now everyone just needs to use LoggingController as a base class.

public class VuvuzelaController : LoggingController
{
    public ActionResult Detonate()
    {
        // ...
    }
}

Wait! What if someone forgets to use the base class? This problem is easy to prevent - we'll look at the details in a future post (think unit test with LINQ queries and reflection).

The bigger problem is all the design issues a base class brings into play. What if someone else overrides the methods and forgets to call the base implementation? What if someone wants to manage transactions and ORM sessions in a base controller? If you follow the pattern you either end up with a fragile class hierarchy or a SessionInitializingTransactionMonitoringLoggingCachingSuperDuperController base class.

Fortunately, ASP.NET MVC finds and respects the action filters on a base controller class. You can add additional functionality without adding implementation.

[Log]
public class FootballController : Controller
{
    
}

Now every controller derived from FootballController will log.

public class VuvuzelaController : FootballController
{
    public ActionResult Detonate()
    {
        // ...
    }
}

A Pictorial and Prose Filled Guide To Impressing Designers

Sunday, June 27, 2010 by K. Scott Allen
4 comments

“Is the software installed?” asked my friend Kenny Cole.

“Yes”.

Our eyes tracked the mouse on screen as I right-clicked on a project and picked Open With –> Expression Blend 4. Diodes flickered. Hard drives whirred. A dialog box appeared.

 

install expression blend sdk for .net 4

 

Kenny’s angular face raised an eyebrow.  “A modal dialog ... interesting start,” he said.

“Yes,” I replied with a nervous laugh, “well, this only happens once in a blue moon”.

I moved the mouse and clicked Close as fast as possible. Diodes flickered. Hard drives whirred. A dialog box appeared.

 

install the expression blend sdk for Silverlight 4

 

I could see the frown on Kenny’s face out of the corner of my eye. “Maybe you should click that link to install an S – D - K and make the software happy,” he said.

“Oh, sure”, I replied. I clicked the “Install the Expression Blend SDK for Silverlight 4” link. Diodes flickered. Hard drives whirred. A browser appeared.

 

Microsoft Download Center

 

“It doesn’t appear to be installing anything”, Kenny observed.

“No, no it’s not”.

“It appears to be an ad for Microsoft Office”, Kenny said.

“Well,” I replied, “it’s the home page of the Microsoft Download Center. Presumably from here you can search for SDKs”.

“And then ... presumably ... you can download and install them one by one?”, he asked.

“Ah ... right. Let’s just come back and do that later. I’m sure it’s ready to start now”. I flipped back to Expression and clicked the Close button. Diodes flickered. Hard drives whirred. A dialog box appeared.

 

Your project is a security risk

 

Kenny’s frown turned to a scowl. “Three times!”.

“Yes, well, it’s a security warning,” I said while clicking the Yes button. Diodes flickered. “I mean, you can’t be too secure these days, right?”. Hard drives whirred. “It’s just being cautious, you know”. A dialog box appeared.

 

image

Kenny stood up, and started walking towards the door.

“Wait!” I cried - “check out these rounded corners!”.

Optional Parameters Do Not Create Default Constructors

Thursday, June 24, 2010 by K. Scott Allen
4 comments

At least not from the reflection API's point of view.

For example, given the following class ...

public class Wig
{
    public Wig(string name = "Angry")
    {
        // ...
    }
}

... you can successfully instantiate the class as if it had a default, parameterless constructor:

var wig = new Wig();

However, trying to do this via Activator will fail:

var wig = Activator.CreateInstance<Wig>();
// MissingMethodException: 
// No parameterless constructor defined for this object.

Which makes sense once you realize optional parameters are compiler sugar, and the following code will clearly show a single constructor requiring a single argument.

var ctors = typeof(Wig).GetConstructors();
foreach (var ctor in ctors)
{
    Console.WriteLine(ctor.Name);
    foreach(var param in ctor.GetParameters())
    {
        Console.WriteLine("\t{0} {1}", 
            param.Name, 
            param.ParameterType.Name );
    }                    
}

Checking Client Download Success with ASP.NET MVC

Wednesday, June 23, 2010 by K. Scott Allen
14 comments

Scenario: You want to know if a client completes a large download successfully.

Possible Solution: Create a custom ActionResult (perhaps derived from FileStreamResult) that streams the data and checks to see if the client remains connected.

public class CheckedFileStreamResult : FileStreamResult
{
    public CheckedFileStreamResult(FileStream stream, string contentType)
        :base(stream, contentType)
    {
        DownloadCompleted = false;
    }

    public bool DownloadCompleted { get; set; }

    protected override void WriteFile(HttpResponseBase response)
    {
        var outputStream = response.OutputStream;
        using (FileStream)
        {
            var buffer = new byte[_bufferSize];
            var count = FileStream.Read(buffer, 0, _bufferSize);
            while(count != 0 && response.IsClientConnected)
            {                 
                outputStream.Write(buffer, 0, count);
                count = FileStream.Read(buffer, 0, _bufferSize);
            }
            DownloadCompleted = response.IsClientConnected;
        }
    }
    
    private const int _bufferSize = 0x1000;
}

You can now log or audit the DownloadCompleted property of the result from an action filter. I'm sure this isn't 100% foolproof, but it seems to work reasonably well. Note: The IsClientConnected property of the response only tells the truth when running under IIS. With the WebDev server the property always returns true.

Parr's Rules for MVC Views

Tuesday, June 22, 2010 by K. Scott Allen
5 comments

There are a number of ideas to chew on in this 6 year old paper by Terence Parr: "Enforcing Strict Model-View Separation in Template Engines". Parr is one of the creators of the StringTemplate template engine, which is ".. as simple, consistent, and powerful as possible without sacrificing strict model-view separation".

One of the highlights is the list of 5 rules implied by strict separation. Parr introduces them like so:

Before formalizing my intuition, I kept a few simple rules and tests in mind to evaluate entanglement. Could I reuse this template with a completely different model? Could a designer understand this template? 1f it looks like a program, it probably is. If the template can modify the model, it’s part of the program. If order of execution is important, it’s part of the program. If the template has computations or logic dependent on model data, it’s part of the program. If types are important, the template is a program.

The idea behind a strict separation is to avoid programming in the view and merely apply templating. With the web forms view engine in ASP.NET MVC we can not only break all 5 of Parr's rules, we can crumple them up like tissue paper and light them on fire. Of course, we can also behave ourselves and follow the rules of separation- or at least all of the rules except the one stating "the view cannot make data type assumptions".

Strongly-Typed Views Are Evil?

Most MVC developers I talk to prefer to use strongly-typed views. Strong typing gives us intellisense and compiler errors.  But - is there a cost? Does strongly typing the view lead to a form of bad coupling between the view and the model? Does it make the view harder to change? Does it make the designer's job more difficult?

I can hear you saying "no". Is this because the rendering phase of the processing pipeline is nearly impossible to test? Would it change your mind if testing a view template was easy?

ActionResult result = controller.ChangePassword();
var output = result.ExecuteResult();

What do you think?

by K. Scott Allen K.Scott Allen
My Pluralsight Courses
The Podcast!