Showing posts with label C#. Show all posts
Showing posts with label C#. Show all posts

Wednesday, 30 January 2013

Don't assume anything about the lifetime of ActionFilters in MVC3

In previous versions of ASP.NET MVC, action filters were created per request except in a few cases. This behavior was never a guaranteed behavior but merely an implementation detail and the contract for filters was to consider them stateless. In ASP.NET MVC 3, filters are cached more aggressively. Therefore, any custom action filters which improperly store instance state might be broken.

Taken from the 'breaking changes' section of the release notes for MVC3.

The statement is clear enough to someone feeling the sting still from a recent live issue, but I've outlined a bad and good example of custom action filters below. Basically, if you find yourself needing to store state for the lifetime of a request, use the filterContext.HttpContext.Items collection.


Bad custom action filter

public class BadActionFilter : ActionFilterAttribute
{
    private string _userState;

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        _userState = someSortOfDataUniqueToUser();
    }

    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        // using _userState here is a bad idea!
    }
}

Good custom action filter

public class GoodActionFilter : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var userState = someSortOfDataUniqueToUser();
        filterContext.HttpContext.Items["userState"] = userState;
    }

    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        var userState = filterContext.HttpContext.Items["userState"];
        // using userState here is perfectly fine!
    }
}

Saturday, 13 October 2012

Tolerance and the Equal constraint in NUnit tests

Those pesky tests that fail every once and a while because something took slightly longer than usual. Sure you could just run them again and they probably pass a second time round. There is another simple way to avoid this, the NUnit Within modifier for the Equal constraint.

[Test]
public void CreationDateTimeIsSetOnConstruction()
{
   var timeObject= new TimeClass();
   
   Assert.That(timeObject.CreationDateTime, Is.EqualTo(DateTime.Now)
         .Within(new TimeSpan(2000)));
}

Monday, 17 October 2011

Should I Dispose of my LINQ DataContext?

Most developers construct a DataContext within a using statement to make sure that resources are cleaned up when leaving the block.

using( var dataContext = new LinqDataContext() )
{
   // Perform some data operations
   dataContext.Insert(obj)

} // Dispose of the DataContext and release resources

However it's not needed, the .Net garbage collector does that for you and the need to dispose of the DataContext is made less of critical requirement knowing that LINQ DataContexts do not keep expensive database connections open (something that surprised me) like some other ADO.Net objects.

To summarise, it isn't the end of the world and you aren't a bad developer if you don't dispose of your DataContext objects. I do however think it's good practice to work with IDisposable classes in this way; plus it releases those resources slightly quicker than just leaving it to the garbage collector.

Wednesday, 16 February 2011

Removing XmlDocument Whitespace C#

I've recently been working on matching certain API calls with XML data pulled from an XML file for testing purposes. I noticed there was a large amount of white space left in the XML when pulled from the resourced XML file; which is something I didn't want.

I thought setting the XmlDocument.PreserveWhitespace property to false would remove this for me, but it just seems to remove the preceding and trailing white space; making it similar to the string.Trim() method. I needed to use something akin to string.Replace() (this replaces a specific substring with another substring), but more powerful. Here comes the Regex.Replace function to the rescue, which is a bit like string.Replace() on steroids! Regex.Replace() allows replacement of text using regular expressions, something which can make make complex replacements a piece of cake.

Here is the code to replace white space in XML or any XML dialect (such as HTML - or XHTML):

// Remove inner Xml whitespace
Regex regex = new Regex(@">\s*<");
string cleanedXml = regex.Replace(dirtyXml, "><");

Wednesday, 26 January 2011

Memory stream is not expandable

An upgrade to .Net 4 for an MVC app highlighted an issue with the MemoryStream class we were using in the framework. Seems that unless you use the default constructor, the stream cannot be expandable. If the stream expands you'll get a lovely System.NotSupportedException: Memory stream is not expandable error thrown at you like a ninja star.

var ninjaStarStream = new MemoryStream(buffer); // Potential error
var fluffyStream = new MemoryStream(); // Stream is expandable :)

Consider yourself warned!

Wednesday, 20 October 2010

Read an Embedded Resource Text File in C#

Here's a little snippet I use quite a lot in my test projects to read out an embedded resource text file as a string. The resourceName parameter is the full namespace of the resource, e.g. myproject.files.MyEmbeddedTextFile.txt

internal string GetFromResources(string resourceName)
{
    Assembly assem = this.GetType().Assembly;
    using (Stream stream = assem.GetManifestResourceStream(resourceName))
    {
        using (var reader = new StreamReader(stream))
        {
            return reader.ReadToEnd();
        }
    }
}

P.S. You may want to add some error handling to the above ;)

Tuesday, 14 September 2010

MailMessage's Subject ArgumentException

Just a quickie today... if you get an ArgumentException when setting the subject on the .Net MailMessage object (or on the constructor) like this...

System.ArgumentException: The specified string is not in the form required for a subject.

You'll want to cleanse your string input for non-printable characters. The most likely culprit is a carriage return or line feed. Which is "\r" or "\n" to the C# developers :)

Thursday, 24 June 2010

Multiple types were found that match the controller

I'm starting to make use of the new Areas feature in my MVC 2 applications. I've found it great for separating my applications into distinct sections rather than staring at a massive list of controllers/views all bundled into one folder. I came across an issue when I created a controller with the same name as a controller within a different or the default area:

Multiple types were found that match the controller named XXXXXXXX...

I thought it was a little cheap of Microsoft requiring you to give your controllers unique names across all areas. I was relieved to find out giving the same name within different areas is perfectly OK, you just need to specify the full namespace for the controller when setting up the route for it, like so:

public override void RegisterArea(AreaRegistrationContext context)
{
 context.MapRoute(
  "Members_default",
  "Members/{controller}/{action}/{id}",
  new { controller = "Home", action = "Index", id = UrlParameter.Optional },
  new string[] { "MyWebApp.Areas.Members.Controllers" }
 );
}

I knew Microsoft wouldn't let me down ;)

Friday, 18 June 2010

Mock ControllerContexts in ASP.Net MVC

After performing an upgrade to MVC 2 for a web application last week, I had a number of tests failing. This gave me an opportunity to refactor some controller tests and create a base class for my controller test classes. This new base class is straight forward and allows me to mock HttpRequestBase and HttpSessionStateBase easily on the mock ControllerContext - it also has an overload for mocking AJAX requests too. I expect this class to grow in time but it serves my needs for now:

public class TestController
{
 public static ControllerContext GetMockControllerContext()
 {
  return GetMockControllerContext("GET", false, null, null);
 }

 public static ControllerContext GetMockControllerContext(string httpMethod, bool isAjaxRequest)
 {
  return GetMockControllerContext(httpMethod, isAjaxRequest, null, null);
 }

 public static ControllerContext GetMockControllerContext(Mock httpRequestBase, Mock httpSessionStateBase)
 {
  return GetMockControllerContext("GET", false, httpRequestBase, httpSessionStateBase);
 }

 public static ControllerContext GetMockControllerContext(string httpMethod, bool isAjaxRequest, Mock httpRequestBase, Mock httpSessionStateBase)
 {
  var headerCollection = new NameValueCollection();

  // Add header value for ajax requests
  if (isAjaxRequest) headerCollection.Add("X-Requested-With", "XMLHttpRequest");

  if (httpRequestBase == null)
  {
   httpRequestBase = new Mock();
   httpRequestBase.Setup(r => r.HttpMethod).Returns(httpMethod);
   httpRequestBase.Setup(r => r.Headers).Returns(headerCollection);
   httpRequestBase.Setup(r => r.Form).Returns(new NameValueCollection());
   httpRequestBase.Setup(r => r.QueryString).Returns(new NameValueCollection());
  }

  if (httpSessionStateBase == null)
  {
   httpSessionStateBase = new Mock();
  }

  var mockHttpContext = new Mock();
  mockHttpContext.Setup(c => c.Request).Returns(httpRequestBase.Object);
  mockHttpContext.SetupGet(c => c.Session).Returns(httpSessionStateBase.Object);

  return new ControllerContext(mockHttpContext.Object, new RouteData(), new Mock().Object);
 }
}

Tuesday, 8 June 2010

Handling Unexpected Exceptions in ASP.Net MVC

There are way too many yellow screens of death out there on the net for my liking. But rather than trying to bullet proof your MVC web apps by putting try catch blocks in all your MVC actions to handle unexpected exceptions, there is a far easier way to do it and it keeps your code nice and DRY - see my code snippet below:

public class BaseController : Controller
{
 
 protected override void OnException(ExceptionContext filterContext)
 {
  // Record the error
  Log.Error("Unexpected error in controller", filterContext.Exception);

  // Uses customErrors element from web.config
  if (filterContext.HttpContext.IsCustomErrorEnabled)
  {
   // Set exception as handled and status code 500
   filterContext.ExceptionHandled = true;
   filterContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError;

   this.View("Error").ExecuteResult(this.ControllerContext);
  }
 }

}

I override the OnException method within a base controller for my other controllers to inherit from. Any unhandled exceptions in my action methods will hit this and I can gracefully log the exceptions and send the user to a helpful error view (as long as customErrors for the app are set to true) - it's worth noting I also set an appropriate HTTP status code :)

Wednesday, 31 March 2010

Testing Private Methods in .Net

Some developers seem to be against testing private methods, that if you need to test private methods there is a design issue. I don't think I agree in all cases and extracting some method logic into another method for further testing seems valid to me. Having to make that method public (against it's design) just for testing purposes doesn't sit right, so I test private methods using the PrivateObject class found in the Visual Studio TestTools library...

[TestMethod]
public void IsValidInput_NumberString_ReturnsTrue()
{
 // Arrange 
 var myClass = new MyClassWithPrivateMethod();
 var privateObject = new PrivateObject(myClass);

 // Act
 bool result = (bool)privateObject.Invoke("IsValidInput", new object[] { "123" });

 // Assert
 Assert.IsTrue(result);
}

Thursday, 25 March 2010

How to Check if ASP.Net Debugger is Attached

Want to know how to check if the ASP.Net debugger is attached in code?

System.Diagnostics.Debugger.IsAttached

Wednesday, 17 February 2010

Resx Resource Problems when Unit Testing

If you use resx files for something like translations in your web apps, you'll notice problems when unit testing as your web app won't be running in its natural state and those resources won't be loaded as normal. Typically you'll get the error...

Could not load file or assembly App_GlobalResources


I'm yet to find a decent solution for this problem but here's how I currently get around it in MVC apps. Here I'm replacing my dependency on Strings.resx in App_GlobalResources.

First thing to do is to create a ResourceManager property and make use of this instance within the class you're testing. Now whenever you need to make use of the resource you have to replace the normal syntax of Strings.FieldYouWant with StringsResource.GetString("FieldYouWant") as shown in the method MethodBeingTested().

public class MyController
{
   public ResourceManager StringsResource
   {
      get;
      private set;
   }

   public MyController()
       : this(Strings.ResourceManager)
   {}

   public MyController(ResourceManager stringsResourceManager)
   {
      StringsResource = stringsResourceManager;
   }

   public object MethodBeingTested()
   {
      return new ContentResult( StringsResource.GetString("FieldYouWant") );
   }
}

In your test project you'll need to create a Strings.resx mirrored source file and make use of this when testing MyController class. Do this by instantiating with a resource from the calling test assembly...

var stringsResource
   = new ResourceManager("test.assembly.Strings", Assembly.GetExecutingAssembly());
var controller = new MyController(stringsResource);
...not pretty, but at least you can run your unit tests without an exception slapping you around the face. Any one got a better solution?