Archive for November, 2014

Debugger display attribute

Wednesday, November 19th, 2014

Every developer has to debug the code he is working on. You IDE helps you by showing your local variable watches and, allowing you to define watches. Those watches are the ToString() representation of the objects/expressions you watch.

That’s nice, but you can improve this experience a lot by defining your own debugger display! Of course, there some types in .NET that show you more than the default implementation of object (ToString(){ return GetType().FullName; }), but for you own classes, this is the behavior, by default.

So, what to do? Well, you can implement ToString() for your class, but there are a lot of scenario’s (take ToString() for XDocument) where the result of ToString() is not what you want for your debugger display. Fortunately, .NET gives you the opportunity to add the DebuggerDisplayAttribute. This attrubute decorates your class with an instruction so that your debugger knows what to do, when showing a watch on it.

Basically, you can write a full expression in the attribute constructor argument, but referring to a (non public) property is more convenient. You can refer to a method too, but this can lead to unintended behavior. The expression is evaluated by the runtime and debugging a VB.NET project will give you a warning “Because the evaluation could cause side effects, it will not be executed, until enabled by the user”, even if the debugger display is implemented in C#. Using properties will not lead to this kind of situations.

For most situations you want to return a string, but you can return other objects as well. The IDE will call the DebuggerDisplay of that object. The cases where this can be of value, is where you want to show 17 instead of “17”. Most of the time returning a string is what you want.

using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;

namespace HelloWorld
{
	[DebuggerDisplay("{DebuggerDisplay}")]
	public class DebuggerDisplayClassStringProperty
	{
		public int Number { get; set; }
		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		private string DebuggerDisplay { get { return this.Number.ToString(CultureInfo.InvariantCulture); } }
	}

	[DebuggerDisplay("{DebuggerDisplay()}")]
	public class DebuggerDisplayClassStringMethod
	{
		public int Number { get; set; }
		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		private string DebuggerDisplay() { return this.Number.ToString(CultureInfo.InvariantCulture); }
	}

	[DebuggerDisplay("{DebuggerDisplay}")]
	public class DebuggerDisplayClassObjectProperty
	{
		public int Number { get; set; }
		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		private int DebuggerDisplay { get { return this.Number; } }
	}

	[DebuggerDisplay("{DebuggerDisplay()}")]
	public class DebuggerDisplayClassObjectMethod
	{
		public int Number { get; set; }

		[ExcludeFromCodeCoverage]
		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		private int DebuggerDisplay() { return this.Number; }
	}
}

If you want to create unit tests for it, is up to you, and if you expose the property publicly. If you don’t want to unit test the functionality, I recommend the use of the ExcludeFromCodeCoverage attribute. If you want to test it, you can use reflection.

using NUnit.Framework;
using System.Reflection;

namespace HelloWorld.UnitTests
{
	[TestFixture]
	public class DebuggerDisplayClassTest
	{
		[Test]
		public void DebuggerDisplay_StringMethod_String17()
		{
			var cls = new DebuggerDisplayClassStringMethod() { Number = 17 };
			var dd = cls.GetType().GetMethod("DebuggerDisplay", BindingFlags.Instance | BindingFlags.NonPublic);

			var act = dd.Invoke(cls, new object[0]);
			var exp = "17";

			Assert.AreEqual(exp, act);
		}

		[Test]
		public void DebuggerDisplay_ObjectMethod_Int17()
		{
			var cls = new DebuggerDisplayClassObjectMethod() { Number = 17 };
			var dd = cls.GetType().GetMethod("DebuggerDisplay", BindingFlags.Instance | BindingFlags.NonPublic);

			var act = dd.Invoke(cls, new object[0]);
			var exp = 17;

			Assert.AreEqual(exp, act);
		}

		[Test]
		public void DebuggerDisplay_StringProperty_String17()
		{
			var cls = new DebuggerDisplayClassStringProperty() { Number = 17 };
			var dd = cls.GetType().GetProperty("DebuggerDisplay", BindingFlags.Instance | BindingFlags.NonPublic);

			var act = dd.GetValue(cls);
			var exp = "17";

			Assert.AreEqual(exp, act);
		}

		[Test]
		public void DebuggerDisplay_ObjectProperty_Int17()
		{
			var cls = new DebuggerDisplayClassObjectProperty() { Number = 17 };
			var dd = cls.GetType().GetProperty("DebuggerDisplay", BindingFlags.Instance | BindingFlags.NonPublic);

			var act = dd.GetValue(cls);
			var exp = 17;

			Assert.AreEqual(exp, act);
		}
	}
}

Example of handling cookies Domain-driven

Wednesday, November 5th, 2014

A lot of web applications use cookies for enabling special features. For my company (Exact) for example, we use a cookie to store the latest division (code) that was selected by a user. This is not modelled DDD right now. How should it look like if it did? How to tackle the fact that an HTTP cookie is sealed, as we don’t want to introduce some (static) tooling or helper class?

First of all, I created an abstract wrapped cookie class. This allows developers to add extra (factory) methods, constructors, and properties based on the domain where the specific cookie has to be used. A cookie is a quiet generic thing, and we want to model domain specific implementations. Note that, as a result of that, the Value and Values property of the HTTP cookie are not publicly exposed.

In this case, the base class has besides the required wrapping a constructor with a user ID (GUID) and a static method to create a cookie name, as that is the default for our company. That is not necessarily something everybody should need.

For the specific cookie we have one public constructor, that creates an instance based on the user ID and its division code (a custom value object, containing that logic). Because, in the end, that is what this cookie is all about in our domain.

In this case it is extremely important that is always possible to (implicitly) cast between the wrapped and the original cookie. That makes the usage if the class way more easy.

using System;
using System.Web;

namespace HelloWorld.Web
{
	/// <summary>Represents a cookie that stores the last division visited by an user (ID).</summary>
	public class DivisionCodeCookie : WrappedCookie
	{
		/// <summary>The key for the division code.</summary>
		private const string DivisionCodeKey = "Division";

		/// <summary>Initializes a new division code cookie.</summary>
		/// <param name="userId">The user ID.</param>
		/// <param name="code">The division code.</param>
		public DivisionCodeCookie(Guid userId, DivisionCode code)
			: base(userId)
		{
			this.Code = code;
		}

		/// <summary>Initializes a new division code cookie.</summary>
		private DivisionCodeCookie(HttpCookie cookie) : base(cookie) { }

		/// <summary>Gets and set the division code of the cookie.</summary>
		public DivisionCode Code
		{
			get { return DivisionCode.TryParse(UnderlingCookie.Values[DivisionCodeKey]); }
			set { UnderlingCookie.Values[DivisionCodeKey] = value.ToString(); }
		}

		/// <summary>Creates a copy of the division code cookie.</summary>
		public DivisionCodeCookie Copy() { return new DivisionCodeCookie(this.UserId, this.Code); }

		/// <summary>Casts an HTTP Cookie to a Division code cookie.</summary>
		/// <remarks>
		/// Making the cast implicit allows the use of wrapped cookie when a HTTP cookie is asked.
		/// </remarks>
		public static implicit operator DivisionCodeCookie(HttpCookie http) { return new DivisionCodeCookie(http); }
	}
}

The base class.

using System;
using System.Diagnostics;
using System.Web;

namespace HelloWorld.Web
{
	/// <summary>Represents a cookie.</summary>
	/// <remarks>
	/// It is a wrapper that allows to add custom logic to the cookie.
	/// </remarks>
	[DebuggerDisplay("{DebuggerDisplay}")]
	public abstract class WrappedCookie
	{
		/// <summary>Initials a new wrapped cookie based on an HTTP cookie.</summary>
		protected WrappedCookie(HttpCookie httpCookie)
		{
			if (httpCookie == null) { throw new ArgumentNullException("httpCookie"); }
			this.UnderlingCookie = httpCookie;
		}

		/// <summary>Initials a new wrapped cookie based on an user ID.</summary>
		protected WrappedCookie(Guid userId) : this(GetCookieName(userId)) { }

		/// <summary>Initials a new wrapped cookie based on cookie name.</summary>
		protected WrappedCookie(string name): this(new HttpCookie(name)){}

		/// <summary>Gets or set the underlying HTTP cookie.</summary>
		protected HttpCookie UnderlingCookie { get; set; }

		/// <summary>Gets or set the user ID of the cookie.</summary>
		public Guid UserId
		{
			get
			{
				Guid userid;

				if (this.Name.StartsWith("ExactServer{")&& Guid.TryParseExact(this.Name.Substring(11), "B", out userid))
				{
					return userid;
				}
				return Guid.Empty;

			}
			set { this.Name = GetCookieName(value); }
		}

		/// <summary>Gets or set the name of the cookie.</summary>
		public string Name 
		{ 
			get { return UnderlingCookie.Name;  }
			set{ UnderlingCookie.Name = value;}
		}
		/// <summary>Gets or set the domain of the cookie.</summary>
		public string Domain
		{
			get { return UnderlingCookie.Domain; }
			set { UnderlingCookie.Domain = value; }
		}
		/// <summary>Gets or set the path of the cookie.</summary>
		public string Path
		{
			get { return UnderlingCookie.Path; }
			set { UnderlingCookie.Path = value; }
		}
		/// <summary>Gets or set the expiration date of the cookie.</summary>
		public DateTime Expires
		{
			get { return UnderlingCookie.Expires; }
			set { UnderlingCookie.Expires = value; }
		}
		
		/// <summary>Gets or set a value that specifies whatever a cookie is accessible by client-side script.</summary>
		public bool HttpOnly
		{
			get { return UnderlingCookie.HttpOnly; }
			set { UnderlingCookie.HttpOnly = value; }
		}
		/// <summary>Gets or set a value indicating specifies whatever to transmit the cookie Secure Sockets Layers (SSL)--that is, over HTTPS only.</summary>
		public bool Secure
		{
			get { return UnderlingCookie.Secure; }
			set { UnderlingCookie.Secure = value; }
		}
		/// <summary>Determines whatever the cookie is allowed to participate in output caching.</summary>
		public bool Shareable
		{
			get { return UnderlingCookie.Shareable; }
			set { UnderlingCookie.Shareable = value; }
		}

		/// <summary>Casts a wrapped cookie (back) to an HTTP cookie.</summary>
		/// <remarks>
		/// Making the cast implicit allows the use of wrapped cookie when an HTTP cookie is asked.
		/// </remarks>
		public static implicit operator HttpCookie(WrappedCookie wrapped) { return wrapped.UnderlingCookie; }

		/// <summary>Cleans the cookie up by clearing the value and set the expire date in the past.</summary>
		public void Cleanup()
		{
			UnderlingCookie.Expires = DateTime.Now.AddMinutes(-1);
			UnderlingCookie.Values.Clear();
		}

		/// <summary>Gets the name for the cookie based on the user ID.</summary>
		public static string GetCookieName(Guid userId)
		{
			return string.Format("ExactServer{0:B}", userId);
		}

		/// <summary>Gets a debugger display for the wrapped cookie.</summary>
		protected virtual string DebuggerDisplay { get { return string.Format("Cookie[{0}], Value: {1}, Expires: {2:yyyy-MM-dd HH:mm}", this.Name, this.UnderlingCookie.Value, this.Expires); } }
	}
}