Archive for April, 2009

Asp.Net MVC Conditional TextBox

Wednesday, April 8th, 2009

So I’m really enjoying working with the new Asp.Net MVC framework its refreshing to not be fighting the Asp.Net page life cycle for a change.

One of the things that I don’t like about the MVC Framework is it love affair with strings.  Jeremy Miller puts it far more eloquently than I ever could so I definitely recommend you read that article on his approach with working with the MVC framework even if it is a few months old now.

So like Jeremy I’m a big fan of passing strongly typed objects between my view and my controller.  The other day I was working on a page where I wanted to send an email.  Before the email had been sent I wanted to render out a series of TextBoxes to capture the email information. Once it had been  sent I then wanted to make the textbox read-only.  I thought it  would be good to write an HtmlHelper extension method with a fluent interface so that I could pass a condition (as a Lambda) into it so that I could make a declaration something like code below.

This code example uses the MVC Futures assembly which you can utilize by referencing the Microsoft.Web.Mvc assembly in your solution.

 <%= Html.ConditionalTextBoxFor(model => model.FromEmail)
      .MakeReadOnlyIf(() => Model.Sent) %>

So how did I implement this. First of all I had to write the HtmlHelper extension method which looks like this.

 public static IControlForOptions ConditionalTextBoxFor<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> action)
           where TModel : class
{
   return new TextBoxForOptions<TModel, TProperty>(helper, action);
}

 

This method returns an IControlForOptions interface which looks like this. Using an interface means we can provide different concrete implementations for different controls.

public interface IControlForOptions{
string MakeReadOnlyIf(Func<bool> predicate);}

Our concrete implementation of  our IControlForOptions for our TextBox looks like this:

 public class TextBoxForOptions<VIEWMODEL, TProperty> : IControlForOptions where VIEWMODEL : class
 {
private readonly Expression<Func<VIEWMODEL, TProperty>> _expression;
private readonly HtmlHelper<VIEWMODEL> _helper;
/// <summary>
/// Initializes a new instance of the <see cref="TextBoxForOptions&lt;VIEWMODEL, TProperty&gt;"/> class.
/// </summary>
/// <param name="helper">The helper.</param>
/// <param name="expression">The action we will use </param>
 public TextBoxForOptions(HtmlHelper<VIEWMODEL> helper, Expression<Func<VIEWMODEL, TProperty>> expression)
    {
     _helper = helper;
 _expression = expression;
}

/// <summary>
/// Based upon our predicate condition we will either render out a textbox or a readonly textbox
/// </summary>
/// <param name="predicate">The condition we wish to test.</param>
/// <returns>Either a normal textbox or an readonly textbox</returns>
public string MakeReadOnlyIf(Func<bool> predicate)
{
var makeReadOnly = predicate();
if (makeReadOnly)
{
return _helper.TextBoxFor(_expression, new { ReadOnly = true });
}

return _helper.TextBoxFor(_expression, null);
}
}

In this example I have created a fluent interface that can conditionally out put a Textbox which is readonly. Using this approach you could easily extend this to any HTML control and modify any attribute you wanted to.

kick it on DotNetKicks.com

Unit Testing LightSpeed Entities

Thursday, April 2nd, 2009

If you have not heard of LightSpeed or had a play with it then you should check out the excellent lightweight ORM from the boys at Mindscape.  I have worked with it for a couple of years now and really like it for certain type of projects, I think its simplicity is a good stepping stone for developers making that transition from old data access strategies to ORM technologies.

The one thing I don’t like about it is that your domain objects are not persistant ignorant of the underlying ORM technology, and have to inherit from an Entity base class.

I have run into problems when trying to unit test code that use my Lightspeed entities because I cannot just create a new entity without hitting the database.  Normally when you request an entity from the database the construction of that entity is handled by the Lighspeed framework.

Some of the things that were causing me problems were:

  • I could not assign my own Id for the entity.
  • The Entities throw an exception if they don’t have UnitOfWork set.
  • Could not set up EntityCollection relationships between domain objects as they are read only properties.

In the end I created a LightSpeedEntityFactory and some helper methods for testing purposes to create my entities and get around some of these issues.  I hope you find the following code useful.

    ///

    /// Factory class for building LightSpeedEntity, that are are divorced from a real UnitOfWork.
    /// 

    /// To be used for Unit Testing purposes only!
    internal class LightSpeedEntityFactory
    {
        #region Methods

        ///

        /// Build a LighSpeed Entity with the chosen Id, and a Fake UnitOfWork.
        /// 

        /// 
        /// 
        public static T Build<T>(object id) where T : Entity
        {
            var lightSpeedEntity = Build<T>();

            lightSpeedEntity.SetId(id);

            return lightSpeedEntity;
        }

        ///

        /// Build a LighSpeed Entity with a Fake UnitOfWork.
        /// 

        /// 
        /// 
        public static T Build<T>() where T : Entity
        {
            var lightSpeedEntity = (T)Activator.CreateInstance(typeof (T));

            IUnitOfWork unitOfWork = new UnitOfWork();

            lightSpeedEntity.SetUnitOfWork(unitOfWork);

            return lightSpeedEntity;
        }

        #endregion Methods
    }
   ///

    /// Some helper extension methods for changing the internals of a LightSpeed entity.
    /// 

    /// 
    /// We do some very naughty stuff in here using reflection and these methods
    ///  should only be used for the purposes of Unit Testing.
    /// 
    public static class LightSpeedHelper
    {
        #region Methods

        ///

        /// Set the Id of a LightSpeed Entity. This is usually only a read-accessible property.
        /// 

        public static void SetId(this Entity entity, object id)
        {
            var setIdInternalMethod = entity.GetType().GetMethod("SetIdInternal", BindingFlags.NonPublic | BindingFlags.Instance);

            setIdInternalMethod.Invoke(entity, new[] {id});
        }

        ///

        /// Sets a read-only property on a LightSpeed Entity.
        /// For setting up an object for testing purposes only.
        /// 

        /// lightspeedEntity.SetProperty(a => a.Addresses).SetValue(addresses)
        /// 
        /// The type of the ESULT.
        /// 
        public static IPropertySetter<RESULT> SetProperty<T, RESULT>(this T entity, Expression<Func<T, RESULT>> action) where T : Entity
        {
            var outerMember = (MemberExpression)action.Body;

            var outerProp = (PropertyInfo)outerMember.Member;

            var propertyName = outerProp.Name;

            IPropertySetter<RESULT> propertySetter = new PropertySetter<RESULT>(entity, propertyName);

            return propertySetter;
        }

        ///

        /// Sets the unit of work on a LighSpeed Entity.
        /// 

        public static void SetUnitOfWork(this Entity entity, IUnitOfWork unitOfWork)
        {
            var uowProperty = entity.GetType().GetProperty("UnitOfWork", BindingFlags.NonPublic | BindingFlags.Instance);

            uowProperty.SetValue(entity, unitOfWork, null);
        }

        #endregion Methods
    }
    public class PropertySetter<T> : IPropertySetter<T>
    {
        #region Fields

        private readonly object _parent;
        private readonly string _propertyName;

        #endregion Fields

        #region Constructors

        public PropertySetter(object parent, string propertyName)
        {
            _parent = parent;
            _propertyName = propertyName;
        }

        #endregion Constructors

        #region Methods

        public void SetValue(T value)
        {
            var fieldName = FormatPropertyName(_propertyName);

            var fieldInfo = _parent.GetType().GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance);

            fieldInfo.SetValue(_parent, value);
        }

        private static string FormatPropertyName(string propertyName)
        {
            // get the first letter of the property name.
            var sb = new StringBuilder();

            sb.Append("_");
            sb.Append(char.ToLower(propertyName[0]));
            sb.Append(propertyName.Substring(1));

            return sb.ToString();
        }

        #endregion Methods
    }

UPDATE – ADDED CODE FOR IPROPERTY SETTER THAT WAS MISSING

    public interface IPropertySetter<T>
    {
        #region Methods

        void SetValue(T value);

        #endregion Methods
    }

Web Development Interviews

Thursday, April 2nd, 2009

Now I realise that perhaps, this being a business blog on our business website, that maybe the tone of the posts I am making at present should be a little more sensitive to the business we are trying to garner. Guys, let me know and I will remove these at the drop of a hat. But I am a strong believer in getting to know the “people” you are working with. As the agile manifesto says “People over process” (or as they say it “Individuals and interactions over processes and tools “).

Well, I spend waaaaaay too much time doing loads of really serious stuff, which I thoroughly enjoy, but every now and again I come across something that is absolutely brilliant and needs to be shared. This is one of them.

The guys over at xtranormal have done, quite simply, an astonishing job of producing a stunning web application. I urge you, go, waste an evening, say something, anything and post the results in the comments of this blog. I would love to see what you come up with.

Me, being a passionate and somewhat geeky and opinionated web developer, built this as my first offering. I will post more should I get another evening to play :) .

Enjoy

Why SCRUM will never be the same to me again

Wednesday, April 1st, 2009

In my first foray into SCRUM we have had a great deal of success in ensuring widespread understanding of development issues and progress. This has led to a great sense of cohesive development, with everyone aware of and looking out for other issues and I would wholeheartedly recommend it to anyone.
While outlining this to a colleague at work I came up with the following summary of my experience with SCRUM.

  • Catchup – gives everyone a chance to understand what happened yesterday and intentions for today’s development, keeps everyone informed.
  • Understanding – sharing intentions and discussing risks and issues found during development, at a very high level, has helped the team approach things in a great way with a real sense of developing as a team.
  • No Timelines – this is a SCRUM meeting, not a project management meeting. Estimates, and deadlines are not discussed in the confines of the SCRUM meeting. If anyone is having issues, it is raised offline with the project manager where appropriate.

Of course, within seconds, my colleague had noted the acronym that comes out of that lot. And that is why SCRUM meetings will never be the same for me again.

Anyone who works with me should need no more than one guess as to whom the insightful developer is :)

Don’t Design For The Unknown

Wednesday, April 1st, 2009

Well this is my first blog post so bare with me whilst I get into the swing of things.

I thought I would talk about a problem we had the other week whilst working on a project for a client, when one of the developers on my project team highlighted that there was a problem with our current design. After a brainstorming session we realized that there were two solutions to our problem. The first was very simple to implement and satisfied our immediate project requirements. The second solution was more complex and the changes more far reaching on the code base.

After consulting with our representative from the business we were told that there would be a future requirement that only option two would facilitate. Everybody on the development team screamed YAGNI but we were assured that it was 99.99% certain that this requirement would be implemented in the future as it was crucial. So back to the drawing board we went trying to flesh out option two. And there lies the problem. Even though we know that there will be a future requirement we don’t have the details for our current project. Trying to design a complicated solution with incomplete knowledge is always going to lead to an imperfect solution and probably lead to further refactoring in the long run.

In the end we went with option one. Let the next project spec the requirement properly and design the solution correcty.