Wiring ASP.NET MVC Error Handling with Castle Windsor

Monday, 14 December 2009 06:59:32 UTC

In my previous posts I discussed how to enable global error handling in ASP.NET MVC and how to inject a logging interface into the error handler. In these posts, I simplified things a bit to get my points across.

In production we don't use a custom ErrorHandlingControllerFactory to configure all Controllers with error handling, nor do we instantiate IExceptionFilters manually. What I described was the Poor Man's Dependency Injection (DI) approach, which I find most appropriate when describing DI concepts.

However, we really use Castle Windsor currently, so the wiring looks a bit different although it's still exactly the same thing that's going on. Neither ErrorHandlingActionInvoker nor LoggingExceptionFilter are any different than I have already described, but for completeness I wanted to share a bit of our Windsor code.

This is how we really wire our Controllers:

container.Register(AllTypes
    .FromAssemblyContaining(representativeControllerType)
    .BasedOn<Controller>()
    .ConfigureFor<Controller>(reg => 
        reg.LifeStyle.PerWebRequest.ServiceOverrides(
            new { ActionInvoker = typeof(
                ErrorHandlingControllerActionInvoker)
                .FullName })));

Most of this statement simply instructs Windsor to scan all types in the specified assembly for Controller implementations and register them. The interesting part is the ServiceOverrides method call that uses Windsor's rather excentric syntax for defining that the ActionInvoker property should be wired up with an instance of the component registered as ErrorHandlingControllerActionInvoker.

Since ErrorHandlingControllerActionInvoker itself expects an IExceptionFilter instance we need to configure at least one of these as well. Instead of one, however, we have two:

container.Register(Component.For<IExceptionFilter>()
    .ImplementedBy<LoggingExceptionFilter>());
container.Register(Component.For<IExceptionFilter>()
    .ImplementedBy<HandleErrorAttribute>());

This is Windsor's elegant way of registering Decorators: you simply register the Decorator before the decorated type, and it'll Auto-Wire everything for you.

Finally, we use a ControllerFactory very similar to the WindsorControllerFactory from the MVC Contrib project.

To reiterate: You don't have to use Castle Windsor to enable global error handling or logging in ASP.NET MVC. You can code it by hand as I've demonstrated in my previous posts, or you can use some other DI Container. The purpose of this post was simply to demonstrate one way to take it to the next level.


LoggingExceptionFilter

Monday, 07 December 2009 06:20:27 UTC

In a previous post I described how to enable global error handling in ASP.NET MVC applications. Although I spent some time talking about the importance of DRY, another major motivation for me was to enable Dependency Injection (DI) with exception handling so that I could log stack traces before letting ASP.NET MVC handle the exception.

With the ErrorHandlingControllerActionInvoker I described, we can inject any IExceptionFilter implementation. As an example I used HandleErrorAttribute, but obviously that doesn't log anything. Once again, it would be tempting to derive from HandleErrorAttribute and override its OnException method, but staying true to the Single Responsibility Principle as well as the Open/Closed Principle I rather prefer a Decorator:

public class LoggingExceptionFilter : IExceptionFilter
{
    private readonly IExceptionFilter filter;
    private readonly ILogWriter logWriter;
 
    public LoggingExceptionFilter(IExceptionFilter filter,
        ILogWriter logWriter)
    {
        if (filter == null)
        {
            throw new ArgumentNullException("filter");
        }
        if (logWriter == null)
        {
            throw new ArgumentNullException("logWriter");
        }        
 
        this.filter = filter;
        this.logWriter = logWriter;
    }
 
    #region IExceptionFilter Members
 
    public void OnException(ExceptionContext filterContext)
    {
        this.logWriter.WriteError(filterContext.Exception);
        this.filter.OnException(filterContext);
    }
 
    #endregion
}

The LoggingExceptionFilter shown above is unabridged production code. This is all it takes to bridge the gap between IExceptionFilter and some ILogWriter interface (replace with the logging framework of your choice). Notice how it simply logs the error and then passes on exception handling to the decorated IExceptionFilter.

Currently we use HandleErrorAttribute as the decorated filter so that behavior stays as expected.

c.ActionInvoker = 
    new ErrorHandlingControllerActionInvoker(
        new LoggingExceptionFilter(
            new HandleErrorAttribute(), logWriter));

This is not too different from before, except that a LoggingExceptionFilter now decorates the HandleErrorAttribute instance.


Building and assigning arrays with AutoFixture

Saturday, 05 December 2009 00:41:45 UTC

A reader asked me how AutoFixture can deal with arrays as fields on a class. More specifically, given a class like MyClassA, how can AutoFixture assign a proper array with initialized values to Items?

public class MyClassA
{
    public MyClassB[] Items;
    public MyClassC C;
    public MyClassD D;
}

Ignoring the bad practice of publicly exposing fields, the main problem is that AutoFixture has no inherent understanding of arrays, so if we try to create a new instance of MyClassA by invoking the CreateAnonymous method, we would end up with Items being an array of nulls.

Obviously we want a populated array instead. There are at least a couple of ways to reach this goal.

The simplest is just to create it and modify it afterwards:

var mc = fixture.CreateAnonymous<MyClassA>();
mc.Items = fixture.CreateMany<MyClassB>().ToArray();

Although the CreateAnomymous method will assign an unitialized array, we immediately overwrite the value with an initialized array. The CreateMany method returns an IEnumerable<MyClassB> on which we can use the ToArray extension method to create an array.

The next option is to do almost the same thing, but as a single operation:

var mc = fixture.Build<MyClassA>()
    .With(x => x.Items, 
        fixture.CreateMany<MyClassB>().ToArray())
    .CreateAnonymous();

Besides the different syntax and the lower semicolon count, the biggest difference is that in this case the Items field is never assigned an unitialized array because the With method ensures that the specified value is assigned immediately.

If you get tired of writing this Builder sequence every time you want to create a new MyClassA instance, you can Customize the Fixture:

fixture.Customize<MyClassA>(ob =>
    ob.With(x => x.Items, 
        fixture.CreateMany<MyClassB>().ToArray()));

With this customization, every time we invoke

var mc = fixture.CreateAnonymous<MyClassA>();

we will get an instance of MyClassA with a properly initialized Items array.

I hope you find one or more of these methods useful.


Comments

Murali #
Thanks Mark for your very quick answer to my question.

Murali
2009-12-07 14:33 UTC

Global Error Handling in ASP.NET MVC

Tuesday, 01 December 2009 06:37:01 UTC

ASP.NET MVC comes with an error-handling feature that enables you to show nice error Views to your users instead of the dreaded Yellow Screen of Death. The most prominently described technique involves attributing either you Controller or a single Controller action, like we see in the AccountController created by the Visual Studio project template.

[HandleError]
public class AccountController : Controller { }

That sure is easy, but I don't like it for a number of reasons:

  • Even though you can derive from HandleErrorAttribute, it's impossible to inject any dependencies into Attributes because they must be fully constructed at compile-time. That makes it really difficult to log errors to an interface.
  • It violates the DRY principle. Although it can be applied at the Controller level, I still must remember to attribute all of my Controllers with the HandleErrorAttribute.

Another approach is to override Controller.OnException. That solves the DI problem, but not the DRY problem.

Attentive readers may now point out that I can define a base Controller that implements the proper error handling, and require that all my Controllers derive from this base Controller, but that doesn't satisfy me:

First of all, it still violates the DRY principle. Whether I have to remember to apply a [HandleError] attribute or derive from a : MyBaseController amounts to the same thing. I (and all my team members) have to remember this always. It's unnecessary project friction.

The second thing that bugs me about this approach is that I really do favor composition over inheritance. Error handling is a cross-cutting concern, so why should all my Controllers have to derive from a base controller to enable this? That is absurd.

Fortunately, ASP.NET MVC offers a third way.

The key lies in the Controller base class and how it deals with IExceptionFilters (which HandleErrorAttribute implements). When a Controller action is invoked, this actually happens through an IActionInvoker. The default ControllerActionInvoker is responsible for gathering the list of IExceptionFilters, so the first thing we can do is to derive from that and override its GetFilters method:

public class ErrorHandlingActionInvoker :
    ControllerActionInvoker
{
    private readonly IExceptionFilter filter;
 
    public ErrorHandlingActionInvoker(
        IExceptionFilter filter)
    {
        if (filter == null)
        {
            throw new ArgumentNullException("filter");
        }
 
        this.filter = filter;
    }
 
    protected override FilterInfo GetFilters(
        ControllerContext controllerContext,
        ActionDescriptor actionDescriptor)
    {
        var filterInfo = 
            base.GetFilters(controllerContext, 
            actionDescriptor);
        filterInfo.ExceptionFilters.Add(this.filter);
        return filterInfo;
    }
}

Here I'm simply injecting an IExceptionFilter instance into this class, so I'm not tightly binding it to any particular implementation - it will work with any IExceptionFilter we give it, so it simply serves the purpose of adding the filter at the right stage so that it can deal with otherwise unhandled exceptions. It's pure infrastructure code.

Notice that I first invoke base.GetFilters and then add the injected filter to the returned list of filters. This allows the normal ASP.NET MVC IExceptionFilters to attempt to deal with the error first.

This ErrorHandlingActionInvoker is only valuable if we can assign it to each and every Controller in the application. This can be done using a custom ControllerFactory:

public class ErrorHandlingControllerFactory : 
    DefaultControllerFactory
{
    public override IController CreateController(
        RequestContext requestContext,
        string controllerName)
    {
        var controller = 
            base.CreateController(requestContext,
            controllerName);
 
        var c = controller as Controller;
        if (c != null)
        {
            c.ActionInvoker = 
                new ErrorHandlingActionInvoker(
                    new HandleErrorAttribute());
        }
 
        return controller;
    }
}

Notice that I'm simply deriving from the DefaultControllerFactory and overriding the CreateController method to assign the ErrorHandlingActionInvoker to the created Controller.

In this example, I have chosen to inject the HandleErrorAttribute into the ErrorHandlingActionInvoker instance. This seems weird, but it's the HandleErrorAttribute that implements the default error handling logic in ASP.NET MVC, and since it implements IExceptionFilter, it works like a charm.

The only thing left to do is to wire up the custom ErrorHandlingControllerFactory in global.asax like this:

ControllerBuilder.Current.SetControllerFactory(
    new ErrorHandlingControllerFactory());

Now any Controller action that throws an exception is gracefully handled by the injected IExceptionFilter. Since the filter is added as the last in the list of ExceptionFilters, any normal [HandleError] attribute and Controller.OnException override gets a chance to deal with the exception first, so this doesn't even change behavior of existing code.

If you are trying this out on your own development machine, remember that you must modify your web.config like so:

<customErrors mode="On" />

If you run in the RemoteOnly mode, you will still see the Yellow Screen of Death on your local box.


Comments

Very nice article..
2009-12-04 16:25 UTC
Excellent! I like this for the same reason of DRY as well! I've implemented this in our project now as well!

One question, just to confirm your dependency injection concern: During your CreateController() override, I would have to obtain an instance of ErrorHandlingActionInvoker() from my IoC container, right?

Feels kind of dirty doing it there. Well, it would feel even dirtier if i had to reference a property from the controller to get an instance of what I want.

Just wondering what you ended up with for your dependency injection pattern of this error handler.

2010-01-30 00:23 UTC
You are correct that in our production applications, we don't manually request the ErrorHandlingActionInvoker from the container and assign it to the property. Rather, we simply configure the container to automatically set the ActionInvoker property as part of wiring up any Controller.

This follow-up post provides an example.
2010-01-30 09:27 UTC
I've tried extending the view model to have some of my custom data needed by master page and I keep getting empty result. Any ideas?
2010-03-15 21:42 UTC
I'm not sure I understand how your question relates particularly to this blog post, so I'll need more details than that to be able to say anything meaningful.

May I suggest asking your question on Stack Overflow? That site has good facilities for asking development-related questions, including syntax highlighting. You are welcome to point me to any questions you may have, and I'll take a look and answer if I have anything to add.
2010-03-15 22:17 UTC
petrux #
Great post!!! I was wondering... is it possible to handle the authentication issue the same way? I mean: is it possible to handle it dealing with controllers? Or is it a bad practice and shall I deal with this stuff in the service/busines layer?

Bye bye and... sorry for my broken English! :-)
petrux from Italy
2011-03-01 08:56 UTC
RonJ #
Mark, Your code works up to a point. When an exception occurs in a controller's HttpGet method the method SystemError is reached. However, when an exception occurs in a controller's HttpPost method the exception "A public action method 'SystemError' was not found on controller 'Cmrs_Web.Controllers.CalmErrorController'." is raised on the line of code "httpHandler.ProcessRequest(this.Context);" in global.asa.cs

Here is the global.asa.cs code:
protected void Application_Error(object sender, EventArgs e)
{
// Log the exception to CALM
Guid errorLogNumber = new Guid();
var error = Server.GetLastError();
string logMessage = Calm.Logging.Utilities.FormatException(error);
Response.Clear();
Server.ClearError();
if (Logger.IsFatalOn)
{
errorLogNumber = Logger.Fatal(error);
}

// Put CALM Error Id into session so CalmError controller can get it for displaying in view
Session.Add("CalmErrorId", errorLogNumber.ToString());

// Display Error View
string path = Request.Path;
this.Context.RewritePath("~/CalmError/SystemError");
IHttpHandler httpHandler = new MvcHttpHandler();
httpHandler.ProcessRequest(this.Context);
this.Context.RewritePath(path, false);
}

Here is simplified code for the Controller (device is a simple object with 6 properties - forceErr I manually set to false/true then ran a Debug session)
[HttpGet]
public ActionResult CreateManualAsset()
{
bool forceErr = false;
if (forceErr)
{
throw new Exception("forced error in CreateManualAsset post");
}
return this.View("Manual Asset");
}

[HttpPost]
public ActionResult CreateManualAsset(Device device)
{
bool forceErr = false;
if (forceErr)
{
throw new Exception("forced error in CreateManualAsset post");
}
return this.View("Manual Asset");
}
2012-07-27 18:53 UTC

Anonymous Do

Thursday, 26 November 2009 21:23:46 UTC

In unit testing an important step is to exercise the SUT. The member you want to invoke is often a method that takes one or more parameters, but in some test cases you don't care about the values of those parameters - you just want to invoke the method.

You can always make up one or more Dummy parameters and pass them to the method in question, but you could also use one of AutoFixture's Do convenience methods. There are several overloads that all take delegates that specify the action in question while providing you with Dummies of any parameters you don't care about.

A good example is WPF's ICommand interface. The most prevalent method is the Execute method that takes a single parameter parameter:

void Execute(object parameter);

Most of the time we don't really care about the parameter because we only care that the command was invoked. However, we still need to supply a value for the parameter when we unit test our ICommand implementations. Obviously, we could just pass in a new System.Object every time, but why not let AutoFixture take care of that for us?

(You may think that new'ing up a System.Object is something you can easily do yourself, but imagine other APIs that require much more complex input parameters, and you should begin to see the potential.)

Here's a state-based unit test that verifies that the Message property of the MyViewModel class has the correct value after the FooCommand has been invoked:

[TestMethod]
public void FooWillUpdateMessage()
{
    // Fixture setup
    var fixture = new Fixture();
    var sut = fixture.CreateAnonymous<MyViewModel>();
    // Exercise system
    fixture.Do((object parameter) => 
        sut.FooCommand.Execute(parameter));
    // Verify outcome
    Assert.AreEqual("Foo", sut.Message, "Message");
    // Teardown
}

Notice how the Do method takes an Action<object> to specify the method to invoke. AutoFixture automatically supplies an instance for the parameter parameter using the same engine to create Anonymous variables that it uses for everything else.

The Do method in question is really a generic method with this signature:

public void Do<T>(Action<T> action);

There are also overloads that take two, three or four input parameters, corresponding to the available Action types available in the BCL.

These methods are simply convenience methods that allow you to express your test code more succinctly than you would otherwise have been able to do.


Dependency Injection Podcast with me

Tuesday, 17 November 2009 18:58:47 UTC

Daniel Frost has published a podcast where he discusses Dependency Injection with me. It's about half an hour long and in Danish. Hear it here.


Using Castle Windsor's PerWebRequest lifestyle with ASP.NET MVC on IIS7

Tuesday, 17 November 2009 12:44:37 UTC

When using Castle Windsor in web applications you would want to register many of your components with a lifestyle that is associated with a single request. This is the purpose of the PerWebRequest lifestyle.

If you try that with ASP.NET MVC on IIS7, you are likely to receive the following error message:

Looks like you forgot to register the http module Castle.MicroKernel.Lifestyle.PerWebRequestLifestyleModule
Add '<add name="PerRequestLifestyle" type="Castle.MicroKernel.Lifestyle.PerWebRequestLifestyleModule, Castle.MicroKernel" />' to the <httpModules> section on your web.config.

Unfortunately, following the instructions in the error message doesn't help. There's a discussion about this issue on the Castle Project Users forum, but the gist of it is that if you don't need to resolve components during application startup, this shouldn't be an issue, and indeed it isn't - it seems to be something else.

In my case I seem to have solved the problem by registering the HTTP module in configuration/system.webServer/modules instead of configuration/system.web/httpModules.

Although I haven't had the opportunity to dive into the technical details to understand why this works, this seems to solve the problem on both Windows Vista and Windows Server 2008.


Comments

It is because IIS 7 running under Integration Pipeline(the default, and prefered mode) requires all HttpHandlers and HttpModules to be registered under:

/configuration/system.webServer/modules

It ignores the other HttpHandler and HttpModules defined in system.web.

If you have a website running under IIS6, or you have downgraded your IIS7 to run in "Classic .NET" pipeline mode, that's when you use /configuration/system.web/httpModules - as it's the OLD way of adding them.

IIS7 will even take your old web.config from IIS6 and 'upgrade it' by adding in the system.webServer/modules and /handlers section, and will copy over the older definitions. That is, if you use the IIS Manager to upgrade it. ;)
2010-01-14 22:04 UTC
Thanks for the explanation :)
2010-01-14 22:23 UTC

Creating length-constrained strings with AutoFixture

Saturday, 07 November 2009 19:56:05 UTC

The following feature suggestion was recently posted in the AutoFixture Issue Tracker board:

"We're using AutoFixture to create random rows of data in our DB. A lot of times though, it creates strings that are too long for the database columns. It would be nice if the .With<string> method had an overload that took in a min/max length. We want the random data, but capped at a limit.

"fixture.Build<MyObject>.With(x = x.MyString, 0, 100);

"As an aside, this is for a project that uses Nhibernate and Fluent Nhibernate, which has these lengths already defined. I would be nice if AutoFixture could automatically pick up on that somehow."

I think such an feature is an excellent idea, but I don't think I will include in AutoFixture. Why not?

So far, I have kept the AutoFixture API pretty clean and very generic, and it is my belief that this is one of the main reasons it is so expressive and flexible. There are no methods that only work on specific types (such as strings), and I am reluctant to introduce them now.

In the last six months, I have identified a lot of specialized usage idioms that I would love to package into a reusable library, but I think that they will pollute the core AutoFixture API, so I'm going to put those in one or more optional 'add-on' libraries.

The ability to define strings that are constrained on length could be one such feature, but rather than wait for a helper library, I will show you have you can implement such a method yourself.

The first thing we need is a method that can create anonymous strings given length constraints. One possible implementation is this ConstrainedStringGenerator class:

public class ConstrainedStringGenerator
{
    private readonly int minimumLength;
    private readonly int maximumLength;
 
    public ConstrainedStringGenerator(int minimumLength, 
        int maximumLength)
    {
        if (maximumLength < 0)
        {
            throw new ArgumentOutOfRangeException("...");
        }
        if (minimumLength > maximumLength)
        {
            throw new ArgumentOutOfRangeException("...");
        }
 
        this.minimumLength = minimumLength;
        this.maximumLength = maximumLength;
    }
 
    public string CreateaAnonymous(string seed)
    {
        var s = string.Empty;
        while (s.Length < this.minimumLength)
        {
            s += GuidStringGenerator.CreateAnonymous(seed);
        }
        if (s.Length > this.maximumLength)
        {
            s = s.Substring(0, this.maximumLength);
        }
        return s;
    }
}

The CreateAnonymous method uses AutoFixture's GuidStringGenerator class to create anonymous strings of the required length. For this implementation I chose a basic algorithm, but I'm sure you can create one that is more sophisticated if you need it.

The next thing we need to do is to implement the desired With method. That can be done with an extension method works on ObjectBuilder<T>:

public static class ObjectBuilderExtension
{
    public static ObjectBuilder<T> With<T>(
        this ObjectBuilder<T> ob,
        Expression<Func<T, string>> propertyPicker,
        int minimumLength,
        int maximumLength)
    {
        var me = (MemberExpression)propertyPicker.Body;
        var name = me.Member.Name;
        var generator =
            new ConstrainedStringGenerator(
                minimumLength, maximumLength);
        var value = generator.CreateaAnonymous(name);
        return ob.With(propertyPicker, value);
    }
}

The method takes the same input as ObjectBuilder<T>'s With method, plus the two integers that constrain the length. Note that the propertyPicker expression has been constrained to deal only with strings.

In this implementation, we use the ConstrainedStringGenerator class to generate the desired value for the property, where after we can use the existing With method to assign the value to the property in question.

This now allows us to write Build statements like the one originally requested:

var mc = fixture.Build<MyClass>()
    .With(x => x.SomeText, 0, 100)
    .CreateAnonymous();

The other part of the request, regarding NHibernate integration, I will leave to the interested reader - mostly because I have never used NHibernate, so I have no clue how to do it. I would, however, love to see a blog post with that addition.

This entire example is now part of the AutoFixture test suite, so if you are interested in looking at it in more detail, you can get it from the AutoFixture source code (available at CodePlex).


Comments

Troy #
I see that you have added a ConstrainedStringGenerator class to AutoFixture now but I haven't found any example of how to use it in its new form. What I'm doing currently is providing an ICustomization implementation for domain data that takes max field lengths into consideration. My first question is, is this the right place to do that? If so, how do I reliably get the ISpecimenContext to pass to the Create method? Right now I am creating a SpecimenContext instance myself but again I'm not sure where I should be getting my ISpecimenBuilder instance to pass to it. The 2 leading candidates right now are the Engine property of a Fixture instance that I pass in the constructor as a ISpecimenBuilder or create a StringGenerator instance. If the StringGenerator is what I should use though what should I pass to it in its constructor? Here is an example in case that isn't clear.

fixture.Customize<NwCategory>
(
x => x
.Without(m => m.CategoryID)
.Without(m => m.ProductSet)
.With(m => m.CategoryName, (String)stringGenerator.Create(new ConstrainedStringRequest(NwCategory.MaxLength_CategoryName), new SpecimenContext(this.SpecimenBuilder)))
);
2012-04-26 14:32 UTC
IIRC the ConstrainedStringGenerator class was added to support the [StringLength] attribute. Does this do what you'd like it to do?

There's also a recent discussion about the subject on Stack Overflow.

Finally, perhaps you'll find this post helpful.

If none of these links answer your question, please feel free to ask again. However, Stack Overflow or the AutoFixture discussion list might be better forums, as they are better targeted at Q&A.

HTH
2012-04-27 18:43 UTC

AutoFixture beta 1

Saturday, 31 October 2009 08:59:43 UTC

AutoFixture beta 1 is now available on the CodePlex site! We have been using AutoFixture quite intensively in Safewhere for almost half a year now, and the core of it has turned out to be stable and much more powerful than I originally imagined.

During that period, I have discovered and fixed a few bugs, but the most positive experience has been how extended usage has inspired us to come up with numerous ideas to new cool features. Some of these features are already implemented in the current release, and the rest are listed on the AutoFixture site.

The beta 1 release page has more details about this particular release.


Anonymous With

Monday, 26 October 2009 20:26:49 UTC

A few months ago I described how you can use AutoFixture's With method to assign property values as part of building up an anonymous variable. In that scenario, the With method is used to explicitly assign a particular, pre-defined value to a property.

There's another overload of the With method that doesn't take an explicit value, but rather uses AutoFixture to create an anonymous value for the property. So what's the deal with that if AutoFixture's default behavior is to assign anonymous values to all writable properties?

In short it's an opt-in mechanism that only makes sense if you decide to opt out of the AutoProperties features.

As always, let's look at an example. This time, I've decided to show you a slightly more realistic example so that you can get an idea of how AutoFixture can be used to aid in unit testing. This also means that the example is going to be a little more complex than usual, but it's still simple.

Imagine that we wish to test that an ASP.NET MVC Controller Action returns the correct result. More specifically, we wish to test that the Profile method on MyController returns a ViewResult with the correct Model (the current user's name, to make things interesing).

Here's the entire test. It may look more complicated than it is - it's really only 10 lines of code, but I had to break them up to prevent unpleasant wrapping if your screen is narrow.

[TestMethod]
public void ProfileWillReturnResultWithCorrectUserName()
{
    // Fixture setup
    var fixture = new Fixture();
    fixture.Customize<ControllerContext>(ob => ob
        .OmitAutoProperties()
        .With(cc => cc.HttpContext));
 
    var expectedUserName = 
        fixture.CreateAnonymous("UserName");
 
    var httpCtxStub = new Mock<HttpContextBase>();
    httpCtxStub.SetupGet(x => x.User).Returns(
        new GenericPrincipal(
            new GenericIdentity(expectedUserName), null));
    fixture.Register(httpCtxStub.Object);
 
    var sut = fixture.Build<MyController>()
        .OmitAutoProperties()
        .With(c => c.ControllerContext)
        .CreateAnonymous();
    // Exercise system
    ViewResult result = sut.Profile();
    // Verify outcome
    var actual = result.ViewData.Model;
    Assert.AreEqual(expectedUserName, actual, "User");
    // Teardown
}

Apart from AutoFixture, I'm also making use of Moq to stub out HttpContextBase.

You can see the Anonymous With method in two different places: in the call to Customize and when the SUT is being built. In both cases you can see that the call to With follows a call to OmitAutoProperties. In other words: we are telling AutoFixture that we don't want any of the writable properties to be assigned a value except the one we identify.

Let me highlight some parts of the test.

fixture.Customize<ControllerContext>(ob => ob
    .OmitAutoProperties()
    .With(cc => cc.HttpContext));

This line of code instructs AutoFixture to always create a ControllerContext in a particular way: I don't want to use AutoProperties here, because ControllerContext has a lot of writable properties of abstract types, and that would require me to set up a lot of Test Doubles if I had to assign values to all of those. It's much easier to simply opt out of this mechanism. However, I would like to have the HttpContext property assigned, but I don't care about the value in this statement, so the With method simply states that AutoFixture should assign a value according to whatever rule it has for creating instances of HttpContextBase.

I can now set up a Stub that populates the User property of HttpContextBase:

var httpCtxStub = new Mock<HttpContextBase>();
httpCtxStub.SetupGet(x => x.User).Returns(
    new GenericPrincipal(
        new GenericIdentity(expectedUserName), null));
fixture.Register(httpCtxStub.Object);

This is registered with the fixture instance which closes the loop to the previous customization.

I can now create an instance of my SUT. Once more, I don't want to have to set up a lot of irrelevant properties on MyController, so I opt out of AutoProperties and then explicitly opt in on the ControllerContext. This will cause AutoFixture to automatically populate the ControllerContext with the HttpContext Stub:

var sut = fixture.Build<MyController>()
    .OmitAutoProperties()
    .With(c => c.ControllerContext)
    .CreateAnonymous();

For completeness' sake, here's the MyController class that I am testing:

public class MyController : Controller
{
    public ViewResult Profile()
    {
        object userName = this.User.Identity.Name;
        return this.View(userName);
    }
}

This test may seem complex, but it really accomplishes a lot in only 10 lines of code, considering that ASP.NET MVC Controllers with a working HttpContext are not particularly trivial to set up.

In summary, this With method overload lets you opt in on one or more explicitly identified properties when you have otherwise decided to omit AutoProperties. As all the other Builder methods, this method can also be chained.


Page 71 of 76

"Our team wholeheartedly endorses Mark. His expert service provides tremendous value."
Hire me!