Web Site Globalization With ASP.NET Routing

For those who don’t know, I have this web site http://PauloMorgado.NET/ that I use both as a web presence besides my blogs and a playfield.

Because I write both in English and Portuguese, I wanted the web site to have both English and Portuguese versions. This is easily accomplished by using ASP.NET Globalization and Localization.

But I wanted to do more than guessing the user’s language form her/his web browser languages. I wanted something like the MSDN and TechNet web sites have where the culture is embedded in the URL which makes it easy for the user to choose in which language she/he wants to see the web site.

With the release of the ASP.NET Routing, this is as easy as writing a custom route handler that sets the culture for the request and returns the requested page handler.

Something like this:

public class GlobalizationRouteHandler : global::System.Web.Routing.IRouteHandler
{
    System.Globalization.CultureInfo culture;
    System.Globalization.CultureInfo uiCulture;

    public GlobalizationRouteHandler(System.Globalization.CultureInfo culture)
        : this(culture, culture)
    {
    }

    public GlobalizationRouteHandler(CultureInfo culture, CultureInfo uiCulture)
    {
        if (culture == null)
        {
            throw new ArgumentNullException("cultureInfo", "cultureInfo is null.");
        }

        if (uiCulture == null)
        {
            throw new ArgumentNullException("uiCulture", "uiCulture is null.");
        }

        this.culture = culture;
        this.uiCulture = uiCulture;
    }

    private GlobalizationRouteHandler()
    {
    }

    #region IRouteHandler Members

    public IHttpHandler GetHttpHandler(RequestContext requestContext)
    {
        Thread.CurrentThread.CurrentCulture = this.culture;
        Thread.CurrentThread.CurrentUICulture = this.uiCulture;

        string path = "~/" + (requestContext.RouteData.Values["path"] as string);

        var physicalPath = requestContext.HttpContext.Server.MapPath(path);
        if (System.IO.Directory.Exists(physicalPath))
        {
            path = VirtualPathUtility.Combine(path, "Default.aspx");
        }

        var httpHandler = BuildManager.CreateInstanceFromVirtualPath(path, typeof(IHttpHandler)) as IHttpHandler;

        return httpHandler;
    }

    #endregion
}


And now it’s only a matter of registering the handled cultures:



routes.Add("en", new Route("en/{*path}", new GlobalizationRouteHandler(CultureInfo.GetCultureInfo("en-US"))));
routes.Add("pt", new Route("pt/{*path}", new GlobalizationRouteHandler(CultureInfo.GetCultureInfo("pt-PT"))));

Coupling ASP.NET Session State With Forms Authentication

Today I was talking with João about a way to couple the lifetime of the ASP.NET session state with the lifetime of Forms Authentication ticket.

My idea was to store the session ID in the UserData property of the forms authentication ticket upon logon and retrieve it with a custom session ID manager.

The login code would be something like this:

protected void Login1_Authenticate(object sender, AuthenticateEventArgs e)
{
    bool isPersistent = this.Login1.RememberMeSet;
    string username = this.Login1.UserName;
    var ticket = new FormsAuthenticationTicket(
        0,
        username,
        DateTime.Now,
        DateTime.Now.AddMinutes(2),
        isPersistent,
        Guid.NewGuid().ToString("N"));

    // Encrypt the ticket.
    var encryptedTicket = FormsAuthentication.Encrypt(ticket);

    // Create the cookie.
    this.Response.Cookies.Add(new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket));

    // Redirect back to original URL.
    this.Response.Redirect(FormsAuthentication.GetRedirectUrl(username, isPersistent));
}



For the purpose of this test I am using a Guid as the session ID.




The session ID manager will return this session ID when queried by the session state HTTP module:




public class SessionIdManager : global::System.Web.SessionState.ISessionIDManager
{
    #region ISessionIDManager Members

    public string CreateSessionID(HttpContext context)
    {
        return GetDummySessionIdOrRedirectToLoginPage(context);
    }

    public string GetSessionID(HttpContext context)
    {
        return GetSessionIdFromFormsIdentity(context);
    }

    public void Initialize()
    {
    }

    public bool InitializeRequest(HttpContext context, bool suppressAutoDetectRedirect, out bool supportSessionIDReissue)
    {
        supportSessionIDReissue = false;
        return GetSessionIdFromFormsIdentity(context) == null;
    }

    public void RemoveSessionID(HttpContext context)
    {
    }

    public void SaveSessionID(HttpContext context, string id, out bool redirected, out bool cookieAdded)
    {
        redirected = false;
        cookieAdded = false;
    }

    public bool Validate(string id)
    {
        return true;
    }

    #endregion

    private static string GetSessionIdFromFormsIdentity(HttpContext context)
    {
        var identity = context.User != null ? context.User.Identity as FormsIdentity : null;

        if ((identity == null) || (identity.Ticket == null) || string.IsNullOrEmpty(identity.Ticket.UserData))
        {
            return GetDummySessionIdOrRedirectToLoginPage(context);
        }
        else
        {
            return identity.Ticket.UserData;
        }
    }

    private static string GetDummySessionIdOrRedirectToLoginPage(HttpContext context)
    {
        if (context.Request.CurrentExecutionFilePath.Equals(FormsAuthentication.DefaultUrl, StringComparison.OrdinalIgnoreCase)
                        || context.Request.CurrentExecutionFilePath.Equals(FormsAuthentication.LoginUrl, StringComparison.OrdinalIgnoreCase))
        {
            return Guid.NewGuid().ToString("N");
        }
        else
        {
            FormsAuthentication.RedirectToLoginPage();
            return null;
        }
    }
}



NOTE: Although this might work, it’s just an intellectual exercise and wasn’t fully tested.


Playing With LINQ: Getting Interface Property Implementations

LINQ With C# (Portuguese)

Today, my friend Nuno was writing some code to get the PropertyInfos of a class implementation of an interface.

Given this interface:

public interface ISomeInterface { int IntProperty { get; set; } string StringProperty { get; } void Method(); }




and this class:



public class SomeClass : ISomeInterface
{
    int ISomeInterface.IntProperty { get; set; }
    public int IntProperty { get; private set; }
    public string StringProperty { get; private set; }
    public void Method() { }
}


Nuno wanted to retrieve:



  • Int32 ISomeInterface.IntProperty
  • System.String StringProperty


The code is fairly simple. First we need to get the interface mappings for the class:



typeof(SomeClass).GetInterfaceMap(typeof(ISomeInterface)).TargetMethods



and get all PropertyInfos for which the MethodInfo in the list is part of the implementation of the property (is either the set method or the get method).



Something like his:



public static bool Implements(this MethodInfo methodInfo, PropertyInfo propertyInfo)
{
    return (propertyInfo.GetGetMethod(true) == methodInfo) || (propertyInfo.GetSetMethod(true) == methodInfo);
}


But what caught my eye was that, with the above extension methods, I can use LINQ to retrieve a list of the desired PropertyInfos.



Something like this:



public static IEnumerable<PropertyInfo> GetInterfacePropertyImplementation(Type implementer, Type implemented)
{
    return (from propertyInfo in implementer.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).AsEnumerable()
            from methodInfo in implementer.GetInterfaceMap(implemented).TargetMethods.AsEnumerable()
            where methodInfo.Implements(propertyInfo)
            select propertyInfo).Distinct();
}



For the sample class and interface, the usage would be something like this:



var q = GetInterfacePropertyImplementation(typeof(SomeClass), typeof(ISomeInterface));

foreach (var p in q)
{
    Console.WriteLine(p);
}


Which would produce the following output:



Int32 ISomeInterface.IntProperty
System.String StringProperty


UPDATED: The previous implementation was overcomplicated and had some string based logic. Kudos to Nuno.

A TraceListener For Tests

In my code, I make extensive use of debug assertions (see System.Diagnostics.Debug.Assert). These assertions are very helpful while debugging because you don’t need to step into every line of code to see if all pre-conditions are met. As soon as a pre-condition fails, an assertion failed window will pop up and will allow us to either abort, ignore or go to the assertion instruction (retry).


Imagine you have this code:

private void IKnowForSureThatANullStringWillNeverBePassed(string text)
{
    System.Diagnostics.Debug.Assert(string != null, “text is null.”);

    // …
}

Because this method is private, I have full control of what is passed to the text parameter, therefore I’m asserting that it will never be null. Because it might not be obvious that text will never be null, the assertion also acts as documentation.


I usually run my unit tests and integration test on debug compilations and these assertions would be helpful by making the test fail on an assertion fail instead of running through the method and failing with an NullReferenceException. That’s why I (and more people out there) wrote this simple TraceListener:

public class TraceListener : global::System.Diagnostics.TraceListener
{
    public static readonly TraceListener Default = new TraceListener();

    protected TraceListener()
    {
        this.Name = “Testing Trace Listener”;    
    }

    protected TraceListener(string name)
        : base(name)
    {
    }

    public override void Write(string message)
    {
    }

    public override void WriteLine(string message)
    {
    }

    public override void Fail(string message, string detailMessage)
    {
        var builder = new global::System.Text.StringBuilder();

        builder.Append(message);

        if (detailMessage != null)
        {
            builder.Append(” “);
            builder.Append(detailMessage);
        }

        throw new global::Microsoft.VisualStudio.TestTools.UnitTesting.AssertFailedException(builder.ToString());

    }
}

This trace listener won’t write anything to anywhere. It will just throw an AssertFailedException if the Fail method is called, which is what happens when an assertion fails.


Because an assertion window is not desired when running the tests (specially if they are automated tests ran as part of a build process) it’s better to disable the assert UI on the configuration file of the test project.

<?xml version=1.0encoding=utf-8?>
<configuration>
    <system.diagnostics>
        <assert assertuienabled=false/>
        <trace>
            <listeners>
                <add name=TestTraceListenertype=PauloMorgado.TestTools.VisualStudio.UnitTesting.Diagnostics.TraceListener, PauloMorgado.TestTools.VisualStudio/>
            </listeners>
        </trace>
    </system.diagnostics>
</configuration>
You can find this and other tools on the PauloMorgado.TestTools on CodePlex.

How To Set Elements Of An Array Of A Private Type Using Visual Studio Shadows

Visual Studio uses Publicize to create accessors public for private members and types of a type.


But when you try to set elements of a private array of elements of a private type, things get complicated.


Imagine this hypothetic class to test:

public static class MyClass
{
    private static readonly MyInnerClass[] myArray = new MyInnerClass[10];

    public static bool IsEmpty()
    {
        foreach (var item in myArray)
        {
            if ((item != null) && (!string.IsNullOrEmpty(item.Field)))
            {
                return false;
            }
        }

        return true;
    }

    private class MyInnerClass
    {
        public string Field;
    }
}

If I want to write a test for the case when the array has “non empty” entries, I need to setup the array first.


Using the accessors generated by Visual Studio, I would write something like this:

[TestClass()]
public class MyClassTest
{
    [TestMethod()]
    public void IsEmpty_NotEmpty_ReturnsFalse()
    {
        for (int i = 0; i < 10; i++)
        {
            MyClass_Accessor.myArray[i] = new MyClass_Accessor.MyInnerClass { Field = i.ToString() };
        }

        bool expected = false;
        bool actual;

        actual = MyClass.IsEmpty();

        Assert.AreEqual(expected, actual);
    }
}

But the test will fail because, although the elements of the private array myArray can be read as MyClass_Accessor.MyInnerClass instances, they can’t be written as such.


To do so, the test would have to be written like this:

[TestClass()]
public class MyClassTest
{
    [TestMethod()]
    public void IsEmpty_NotEmpty_ReturnsFalse()
    {
        for (int i = 0; i < 10; i++)
        {
            MyClass_Accessor.ShadowedType.SetStaticArrayElement(“myArray”, new MyClass_Accessor.MyInnerClass { Field = i.ToString() }.Target, i);
        }

        bool expected = false;
        bool actual;

        actual = MyClass.IsEmpty();

        Assert.AreEqual(expected, actual);
    }
}

But, this way, we loose all the strong typing of the accessors because we need to write the name of the array field.


Because the accessor for the field is a property, we could write a set of extension methods that take care of getting the field name for us. Something like this:

public static class PrivateypeExtensions
{
    public static void SetStaticArrayElement<T>(this PrivateType self, Expression<Func<T[]>> expression, T value, params int[] indices)
    {
        object elementValue = (value is BaseShadow) ? (value as BaseShadow).Target : value;

        self.SetStaticArrayElement(
            ((PropertyInfo)((MemberExpression)(expression.Body)).Member).Name,
            elementValue,
            indices);
    }

    public static void SetStaticArrayElement<T>(this PrivateType self, Expression<Func<T[]>> expression, BindingFlags invokeAttr, T value, params int[] indices)
    {
        object elementValue = (value is BaseShadow) ? (value as BaseShadow).Target : value;

        self.SetStaticArrayElement(
            ((PropertyInfo)((MemberExpression)(expression.Body)).Member).Name,
            invokeAttr,
            elementValue,
            indices);
    }
}

Now, we can write the test like this:

[TestClass()]
public class MyClassTest
{
    [TestMethod()]
    public void IsEmpty_NotEmpty_ReturnsFalse()
    {
        for (int i = 0; i < 10; i++)
        {
            MyClass_Accessor.ShadowedType.SetStaticArrayElement(() => MyClass_Accessor.myArray, new MyClass_Accessor.MyInnerClass { Field = i.ToString() }, i);
        }

        bool expected = false;
        bool actual;

        actual = MyClass.IsEmpty();

        Assert.AreEqual(expected, actual);
    }
}

It’s not the same as the first form, but it’s strongly typed and we’ll get a compiler error instead of a test run error if we change the name of the myArray field.


You can find this and other tools on the PauloMorgado.TestTools on CodePlex.