Thursday, 27 November 2008

Mocking Void Methods with Rhino Mocks

I’ve finally found a need to mock a method that has a void return option.  Here is how to do it with Rhino Mocks.

// Setup the delete methods
Expect.Call(delegate { items.Delete(_TestItems[0].Item); })
    .Throw(new System.Data.ConstraintException("duplicate row"))
    .Repeat.AtLeastOnce();

You can also have it return nothing and now throw any exceptions like so.

Expect.Call(delegate { items.Delete(_TestItems[1].Item); })
    .Repeat.AtLeastOnce();

Wednesday, 19 November 2008

Cloning objects in C# / Performing a Deep Copy

I’ve come from a C++ background as many C# programmers seem to have.  Once of the things that will eventually bite you in the foot once you move to .NET is that not only is everything passed by reference, but the language does not support cloning or deep copying of an object. 

When you copy an object there are two ways to do it.  The first is a shallow copy where your copy result references the same in memory object as your original as follows.

image

Obviously here any changes to the original will be made to the copy as well.  This is not really a copy of the object but a copy of the reference, and it is the most common way to copy an object in C# and .NET.

The other way is a deep copy.  A deep copy makes a duplicate of the original object for the new reference as follows.

image

Changes to your original object will no longer effect the copied object.  But guess what, there is no way to do this cleanly in C#.

Before anyone jumps up and down and says that there are ways to do this, well yes there are some methods:

1. Binary Serialization

You can serialize the object and restore it into the copy.  This will work but it will require that the class that you’re copying is serlializable.

2. XML Serialization

You can serialize the object to XML and restore it into the copy.  This will not require that you have the class as serializable, but it will only copy the public members and properties.

3. Reflection

I’ve used reflection a fair bit and it’s very nice, but if you wish to make a generic Clone method it will not let you set private members and nested objects will be harder to do in this fashion.

4. Custom Clone Method

If you implement the IClonable (I wouldn’t suggest it as it appears that it will be deprecated at some point in the future) or your own cloneable base class or interface all objects that implement it could be manually copied using reflection with access to private members.  But any classes that do not inherit from your custom clonable class will not be able to be cloned (the entity framework for example).

What it all boils down to is that if you have private members that are not serializable then you will not be able to clone or deep copy the object, and if this is true then it would make all sense to never do it.  In my opinion this is not necessarily a bad thing, but a design choice of the Microsoft developers.  As long as you’re aware of it then developing around it should be simple enough, if you hack a solution to the problem into place then you are destined to come across issues in the future.

Thursday, 13 November 2008

Strongly typed View Names

I like the MVC framework but I want to type

public ActionResult Index()
{
    return View(Views.Home.Index);
}

Instead of

public ActionResult Index()
{
     return View("Index");
}

So that my code is strongly typed.  I don’t use View() by itself because in unit testing I want to be sure my controller is returning the correct view.  Well I’ve found a nice way to do it.  If you don’t have a base controller you’ll need one, like so:

public class BaseController : Controller
{
    protected ActionResult View(Type viewType, object viewData)
    {
        return (View(viewType.Name, viewData));
    }
 
    protected ActionResult View(Type viewType)
    {
        return (View(viewType.Name));
    }
}

This will take the view name from the strongly typed reference to the class when you pass it by type and allow you to return your views like this:

public ActionResult Index()
{
    return View(typeof(Views.en.Home.index));
}
 
public ActionResult About()
{
    return View(typeof(Views.en.Home.about), AboutModel);
}

This is compile time checking and will save you from misspelling the view name (even if you unit test this can happen, particularly if you’re familiar with the dreaded copy and paste).

Testable LINQ to Entities with Table Joins

I’m enjoying LINQ to Entities and the Entity Framework, but sometimes it feels like someone forgot to write up the documentation.  It’s nice to have the product, but it can be very hard to use without adequate training or documentation.  But I suppose it’s very new and I’ll just have to wait for more people to jump on board.

In the mean time, I came across a problem.  We are following the repository model design pattern in our data access objects and when using LINQ to Entities we define the table that the model is concerned with as a private member from the Entity Model.  This allows us to use TDD and override this private member with our own queryable datasets for testing.

So your data repository will look something like this:

public class SecurityUserRepository : ISecurityUserRepository
{
    private IQueryable<rfSysAction> _rfSysActionData;
    private MyEntities _Entities;
 
    public SecurityUserRepository()
    {
        _Entities = new MyEntities();
        _rfSysActionData = _Entities.rfSysAction;
    }
 
    public SecurityUserRepository(IQueryable<rfSysAction> sysAction)
    {
        _rfSysActionData = sysAction;
    }
}

Nice code, easy to test, but what if I want to join several tables together to get a set of data back?  For example, my user is part of several security groups, my security groups are linked to my MVC actions and my actions are defined in a table specifying their names. 

Well it’s actually not that hard.

Most often when trying to write this join you’ll get examples that make you reference the entity model to get all the tables you want to join.  This works fine, but it’s not good for me because I have only mocked up a copy of my root object.

Then I found this great example showing how it can be done.  So if I want to return an action table record for a specific action, controller and user my LINQ should look like this:

IQueryable<rfSysAction> query = 
    from sa in _rfSysActionData
        from sas in sa.rfSysActionSecurity
        from usg in sas.rfSecurityGroup.UserSecurityGroup
    where usg.UserID == userIdparam 
        && sa.Controller == controller
        && sa.Name == action
    select sa;

This query will find all security actions and then limit the selection to those for the user, controller and action specified.  This is what my model looks like for the tables in the above query:

image

The code is simple and makes sense when you know what to do, but now that I have it, how do I test it.  With rfSysAction as my base table, all I have to do is mock this up and add in the child table data like this:

private IQueryable<rfSysAction> GetTestUserSecurityGroupData()
{
    List<rfSysAction> data = new List<rfSysAction>
    {
        new rfSysAction()
        {
            ActionID = 1,
            Controller = "controllera",
            Name = "actiona",
            rfSysActionSecurity = new EntityCollection<rfSysActionSecurity>()
            {
                new rfSysActionSecurity()
                {
                    rfSecurityGroup = new rfSecurityGroup()
                    {
                        Name = "groupa",
                        UserSecurityGroup = new EntityCollection<UserSecurityGroup>()
                        {
                            new UserSecurityGroup()
                            {
                                UserID = 1
                            }
                        }
                    }
                }
            }
        }
    };
 
    return data.AsQueryable();
}

And then use the override constructor to set the data:

ISecurityRepository target = new SecurityRepository(GetTestUserSecurityData());

There you have it, testable LINQ to Entities and I haven’t had to overwrite several table object. 

Monday, 10 November 2008

Localization with ASP.NET MVC

When investigating the subject of Areas I came across some recent posts from Phil Haack and Steve Sanderson that made great use of areas to provide exactly what I wanted.  But it got me to thinking, in our application we wish to implement localisation as well as areas where the views have their own sub directories depending on the browser language selection, defaulting to English when no supported language is chosen.

I came up with a very simple solution, and while it’s not the most elegant it works very well.  Using Phil Haack’s code, I implemented my view engine, however I subdivided my views into separate directories for English and Japanese like so:

image

Setting up for English in my view engine was very easy, I just changed the view engine’s constructor to specifically point to my EN views like so in the AreaViewEngine.cs.

public AreaViewEngine() : base() 
{
    ViewLocationFormats = new[] 
    { 
        "~/{0}.aspx",
        "~/{0}.ascx",
        "~/Views/EN/{1}/{0}.aspx",
        "~/Views/EN/{1}/{0}.ascx",
        "~/Views/EN/Shared/{0}.aspx",
        "~/Views/EN/Shared/{0}.ascx",
    };
 
    MasterLocationFormats = new[] 
    {
        "~/{0}.master",
        "~/Shared/{0}.master",
        "~/Views/EN/{1}/{0}.master",
        "~/Views/EN/Shared/{0}.master",
    };
 
    PartialViewLocationFormats = ViewLocationFormats;
}

And made sure the formatting functions in Phil’s view engine looked specifically for my views.

private static string FormatViewName(ControllerContext controllerContext, string viewName) 
{
    string controllerName = controllerContext.RouteData.GetRequiredString("controller");
 
    string area = controllerContext.RouteData.Values["area"].ToString();
    return "Areas/" + area + "/Views/EN/" + controllerName + "/" + viewName;
}
 
private static string FormatSharedViewName(ControllerContext controllerContext, string viewName) 
{
    string area = controllerContext.RouteData.Values["area"].ToString();
    return "Areas/" + area + "/Views/EN/Shared/" + viewName;
}

But how do I tell the system that when Japanese is the default language to look into the JP folder?

There are two ways that I can see.  Phil’s source uses the base.FindView from within the FindView method of his custom view engine.  By completely overriding the FindView method you could specify the language directories to look into depending on the language selection.  This seemed like quite a difficult task and quite a lot of code.

I went down the very simple path of redirecting to the Japanese views once the view selection is complete.

protected override IView CreateView(ControllerContext controllerContext, string viewPath, string masterPath)
{
    viewPath = viewPath.Replace("/EN/", "/JP/");
    return base.CreateView(controllerContext, viewPath, masterPath);
}

I do realise that this code will ALWAYS route from English into Japanese, it’s just an example.  And before anyone jumps up and down and shouts “Bad Developer” I realise this is not the prettiest way to do it, but it is exactly ideal for our purposes and it is very simple.

The view must exist in the English language for it to be routable to in any other language and must exist in exactly the same location in the Japanese folders.

If anyone reading this knows a better way this should be done, please let me know. 

Asynchronous Data Loading in ASP.NET MVC Components

I recently came across a problem when designing my ASP.NET MVC enterprise application where I needed a user control to hit the database to load some information dynamically without refreshing the page.  I did a bit of searching and found a few possible ways of doing it, but when I asked the question on Stack Overflow I got a great answer.

The example uses jQuery, if you’re not familiar with it try this site as I found it quite helpful.  Your controllers are not restricted to returning views only, action results can be in the form of Json data if you wish or many other types of data.  Using System.Web.Mvc you can find the JsonResult action result.

If we call an action that returns a JsonResult from an Ajax control using java script we can asynchronously get the data we need and not have to worry about postbacks on the page.

For my example I’m going to do almost exactly the same as my answer from stackoverflow, but I found a few things that didn’t work for me so I’ll repair them.  I want a text box to auto complete.  When I type the first letter I want it to fill out the remainder for me and select the whole text.

My action looks something like this

public ActionResult GetSuggestions(string searchText)
{
    return Json(new { SearchText = searchText + "completestring"});
}

No checking of the database here, it’s out of the scope of this post, just return the letter or letters entered and add “completestring” to the end. 

Now all I need to do is use some javascript inside my HTML link so.

function startAutoComplete() {
    var searchText = $("#inputText").val();
    $.getJSON("/Search/GetSuggestions?searchText=" + searchText, null, autoCompleteResponse);
}
 
function autoCompleteResponse(data) {
    if (data.SearchText) {
        $("#inputText").val(data.SearchText);
        $("#inputText").select();
    }
}

This code will input component called inputText and set the value of the text box to the output of the JSON based action.  The data is returned via an event handler (autoCompleteResponse(data)) so that it is handled asynchronously.

This example is the simplest use case I could think of, and it’s not terribly useful.  But this same method is going to be very useful for me when searching for data to complete entry fields (user search for a user field for example) and when creating other asynchronous components.

Friday, 7 November 2008

Encrypting Password Fields in C#

This is probably nothing new to many people, but for me it was something new so I’m blogging about it.  There is often the need to encrypt password fields (or any other field for that matter) when storing it in the database.  There are a few ways to do it in the database too, but if you’re using an ORM like LINQ to SQL or NHibernate for .NET then you’ll find that the SQL used to encrypt and decrypt can add un-necessary complexity to your application.  Instead .NET provides you with many means to encrypt and decrypt data using cryptography.

Don’t Decrypt Passwords

The first lesson I’ve learned when dealing with cryptography is that you should never decrypt a password.  If you need to validate a password then you should re-encrypt the password and then validate the two encrypted passwords against each other.

.NET provides encryption by the System.Security.Cryptography namespace and uses the provider model that’s so prominent in .NET.  The different encryption types I won’t go into here, that’s something you’ll have to find out for yourself, however the most popular seems to be MD5 or SHA1.

The code to encrypt a string field is very simple.

MD5CryptoServiceProvider md5crypto = new MD5CryptoServiceProvider();
byte[] data = System.Text.Encoding.ASCII.GetBytes(inputString);
data = md5crypto.ComputeHash(data);
return System.Text.Encoding.ASCII.GetString(data);

Convert the string to a byte array, compute the hash, return the encrypted hash.  This can be used by any type of data that allows conversion into a byte array.

I would highly recommend wrapping up the MD5 encryption in an interface so you can plug in other encryption types that are appropriate for your security concerns.

Tuesday, 4 November 2008

Faking HTTPContext in Unit Tests

You may often come across some area of your application where you need to test using the HTTPContext values.  Thing is that HTTPContext doesn’t exist in a test application and you probably don’t want to mess around with HostType() variables or trying to create a “real” context in code.  So here’s a snippet that will create a simple worker request context for your application to test with

TextWriter tw = new StringWriter();
HttpWorkerRequest wr = new SimpleWorkerRequest("/webapp", "c:\\inetpub\\wwwroot\\webapp\\", "default.aspx", "", tw);
HttpContext.Current = new HttpContext(wr);

I can’t take credit for it, I found it here on Jeff’s Junk (good on ya Jeff!).  Once you have put your HttpContext in place you can setup whatever information you need for your unit test.  In my case I wanted to test a user called “usernotfound” so my unit test starts off like so;

// Setup the user account for testing.
IIdentity identify = new System.Security.Principal.GenericIdentity("usernotfound");
IPrincipal currentUser = new System.Security.Principal.GenericPrincipal(identify, null);
 
TextWriter tw = new StringWriter();
HttpWorkerRequest wr = new SimpleWorkerRequest("/webapp", "c:\\inetpub\\wwwroot\\webapp\\", "default.aspx", "", tw);
HttpContext.Current = new HttpContext(wr);
 
System.Web.HttpContext.Current.User = currentUser;

And away I go….