Sunday, April 17, 2011

Creating a Validation Label Helper – Part 1

Presenting validation messages is a pain.  Programmers usually tack validation messages on to a User Interface is a way that gets the job done, but also is clunky and detracts from the overall UI design.  Let me show you an example.  Below is a really simple form from my HireFlo application. 

image

Here’s the markup that creates the form fields and buttons.  I just use a simple layout with a label followed by a validation message, and a Textbox created using MVC’s strongly typed Html helper methods.

    <div class="form-row">
        <label class="form-label" for="folder.FolderName" title="The name for this folder" >
Enter a name for your folder:
</label>
        <%= Html.ValidationMessageFor(model => model.Folder.FolderName)%><br /> 
       <%= Html.TextBoxFor(model=>model.Folder.FolderName, new {style="width:300px;", maxlength="50"})%>
</div>
                            
    <div>
        <input id="SaveButton" type="submit" class="button-green" value=" Save Folder " /> 
        <input id="CancelButton" type="button" class="button-gray" value=" Cancel " />          
    </div>

The only validation on the form is that you have to enter a name for the folder you’re creating.  If you don’t, you get a validation error that looks like this.

image

While functional, this doesn’t look very good. The validation message for the field is just kind of tacked on after the label, but where else am I going to put it. I could put it underneath the field, beside the field, but these options all result in extra text, and an interface that looks cluttered to me. 

I’ve become more and more of a minimalist when it comes to UI design.  I want to put as few things on the page as possible.  So I started thinking, what is the function of the label on a form?  It’s there to tell the user what data to put into a given field.  Now what is the purpose of the label on a form with a validation message?  The validation message and the label are both trying to tell you what goes into a given field.  Maybe it makes sense to combine them.  So I tried that out and the results look like this.

image

All right.  This is looking better to me.  The interface is clean and clear.  I have to make sure that my validation messages always start with the field name, and they need to be fairly short, but those both sound like good design constraints so I’m willing to work with them. The ValidationLabel is now the standard way that I’m going to handle error messages in my application. 

So how should I implement the ValidationLabel?  I’m already using the ValidationMessage Html helper method and that works pretty well, I’ll just customize that and add the Label functionality to it.  I write an extension method for HtmlHelper that will take all of the parameters required to behave as both a label and an error message.  If there’s no error, my helper will render a label.  If there is an error, my helper will render an error message.  Simple.  Here’s how my markup will look with the new helper.

    <div class="form-row">
        <%= Html.ValidationLabel("Folder.FolderName", "Enter a name for your folder", null)%>
        <%= Html.TextBoxFor(model=>model.Folder.FolderName, new {style="width:300px;", maxlength="50"})%>
</div>
                           
    <div>
        <input id="SaveButton" type="submit" class="button-green" value=" Save Folder " /> 
        <input id="CancelButton" type="button" class="button-gray" value=" Cancel " />          
    </div>

Hmmmm, cleaner interface and cleaner markup.  I like the way this is going.  Now let’s write the ValidationLabel helper method.  It’s actually surprisingly simple.  Here’s the code.

        // ValidationLabel
        public static MvcHtmlString ValidationLabel(this HtmlHelper htmlHelper,
string modelName,
string labelText,
IDictionary<string, object> htmlAttributes)
        {
            if (modelName == null) { throw new ArgumentNullException("modelName"); }
            ModelState modelState = htmlHelper.ViewData.ModelState[modelName];
            ModelErrorCollection modelErrors = (modelState == null) ? null : modelState.Errors;
            ModelError modelError = ((modelErrors == null) || (modelErrors.Count == 0)) ? null : modelErrors[0];
            // If there is no error, we want to show a label.  If there is an error,
            // we want to show the error message.
            string tagText = labelText;
            string tagClass = "form_field_label_normal";
            if ((modelState != null) && (modelError != null))
            {
                tagText = modelError.ErrorMessage;
                tagClass = "form_field_label_error";
            }
            // Build out the tag
            TagBuilder builder = new TagBuilder("span");
            builder.MergeAttributes(htmlAttributes);
            builder.MergeAttribute("class", tagClass);
            builder.MergeAttribute("validationlabelfor", modelName );
            builder.SetInnerText(tagText);
            return MvcHtmlString.Create(builder.ToString(TagRenderMode.Normal));
        }

Here’s how it works.  This is an extension method on the HtmlHelper class so the first parameter is the HtmlHelper.  Next we pass in the modelName, the labelText, and a dictionary of Html Attributes that can be used for custom formatting.  The first thing we do is make sure that we have a modelName and then check to see if there’s an item in the ModelErrorsCollection for that modelName. 

Note that modelName is not the name of your entire model, it’s the name of your field.  In my folder form example the model name is “Folder.FolderName”, because I have view model class that contains a Folder object and that Folder object has a property called FolderName.  If you’re ever uncertain about what a field’s modelName is, just load up your page and look at the markup for your input tag. It will look something like this, and your model name is the value that ASP.Net MVC puts in the name attribute for your tag.

<input id="Folder_FolderName" maxlength="50" name="Folder.FolderName" style="width:300px;" type="text" value="">

Let’s get back to our method. Now we know we have a modelName, we know what the modelName is, and we’ve checked the ModelState’s ModelErrorsCollection to see if we have any errors for our modelName.  From this point on the logic is pretty simple. If we do have an error we set the tagText to the error message text and we set the tagClass to “form_field_label_error”.  If we don’t have an error we set the tagText to the labelText and we set tagClass to “form_field_label_normal”.  Then we just use a TagBuilder to render out a span using the tagText and tagClass that we defined.  I also added a custom “validationlabelfor” attribute that holds the model name and is used for client side (javascript) validation.

So that it! We now have a method that renders our field label, and will magically present any error messages for that field if they exist in the ModelState (In case you’re wondering, ASP.Net MVC automatically stores all errors resulting from model validation or model binding in the ModelState).  Plus the syntax is really clean and simple.  A ValidationLabel, input pair is just 2 lines.

          <%= Html.ValidationLabel("Folder.FolderName", "Enter a name for your folder", null)%>
        <%= Html.TextBoxFor(model=>model.Folder.FolderName, new {style="width:300px;", maxlength="50"})%>

There is one more thing I want to do though.  Notice how my ValidationLabel requires me to manually enter the modelName “Folder.FolderName”, but the TextBoxFor method uses a lambda instead?  That’s pretty cool, plus it eliminates the need to use a “magic string” in our UI code.  For Part 2 I’m going to cover how we can create our very own strongly-typed ValidationLabelFor method that will take a lambda as a parameter instead of that modelName string.

Friday, March 4, 2011

.Net as an Awesome Startup Platform

This is the short (10 slide) deck from my presentation at the Denver Tech Trifecta.   I used slideshare to share the presentation.  If you click the menu button there is a View Fullscreen option. 

First, this is all my own personal opinion, not the views of Microsoft or anybody associated with the Tech Trifecta. If it seems a little terse that’s because most of the content was spoken.  I favor short slides and lots of talking with code demos. The main theme of the presentation was that classic ASP was an awesome startup platform. Then Microsoft pushed out ASP.Net WebForms, and they took over corporate software development, but they lost the startup community.  I think the reason is that it takes too long and costs too much money to build anything real with WebForms (it’s also painful to make significant changes to an existing app).  Open source tools like Ruby/Rails and PHP on the other hand provide a much faster and lower friction development experience, plus they’re free.

But now that’s all changed.  Microsoft is supporting startups in a big way with the BizSpark program which will basically give your startup every product that Microsoft makes for FREE for 3 years. The biggest and most important change for me personally is ASP.Net MVC. Three years ago I was ready to throw away a decade of work on Microsoft platforms and go do Ruby/Rails.  WebForms is a never ending source of bad code and frustration for me. Then ASP.Net MVC came along and it was like a love letter written to web developers.  Every place I turned the MVC Framework had given me just the right levels of abstraction and access to support me in what I needed to code. Plus there’s no ridiculous artificial page lifecycle that tries to make the web look like Windows, awesome!  I love MVC and because of it I am excited to keep building on the .Net stack.  Unfortunately, now that I’ve experienced the light, I cry every time I’m forced to go back and work in WebForms.  One place that I do think the page event lifecycle model works well is Silverlight.  Silverlight gives you the ability to write apps with a user experience that is so good that I think building with it will become a competitive advantage for line of business apps.   All these changes add up to Microsoft once again being an awesome platform to build your web startup on.

Startup Links

For those who are just looking for the resource links at the end of the presentation, here they are.  These are all great startup resources and well worth checking out, especially if you live in the Boulder/Denver area.  -rudy

newtech Meetup
About 4 tech startups present in Denver and Boulder every month. The Denver meetup meets on Auraria Campus. The Boulder meetup has free beer!
http://www.bdnewtech.com/

TechStars
One of the first Y Combinator style accelerator programs for early stage startups.
http://www.techstars.org/

Open Angel Forum
Angel Investors meet in Boulder about twice a year to hear pitches from early stage startups and possibly fund them.
http://openangelforum.com/

StartupDigest
Weekly email digest by Chris McCann that tracks all of the tech startup related events in the Boulder / Denver area.
http://startupdigest.com/

Lean Startup
Best practices for launching a startup by Eric Reis. Must see video here:
http://ecorner.stanford.edu/authorMaterialInfo.html?mid=2329

Feld Thoughts
Amazing blog by Brad Feld, Boulder resident and vocal venture capitalist.
http://www.feld.com/wp/

Monday, February 21, 2011

Easy XML Feed using LINQ to XML and ASP.Net MVC2

I recently had to create an XML feed for an app I’m working on.  The use case is simple.  I have a database of jobs and I need to provide an XML feed containing any jobs that were posted in the last week. I’m going to need to do this for several different 3rd party companies that each use a different XML format, so I want to do a little object oriented design to make sure that creating a feed using a new XML format is as easy as possible.

I’ve always heard that LINQ to XML makes working with XML much easier, and I know that MVC2 makes it easy to package up and return any type of data so I’m going to use them. It should make for a pretty painless XML feed.  Let’s see.

Starting at the controller

I want to start by writing the consuming code and let that drive the shape of my business layer code.  That means I start by writing a Feed action method on one of the controller classes in my MVC2 app.  I want to return XML data so i pick a return type of ContentResult, which will allow me to set the content type to “text/xml”.  The logic for this method is simple.  I have a feedKey that distinctly identifies the 3rd party company / XML schema that I want to generate a feed for.  All companies will hit the same action method, but they’ll pass in a different feedKey, which will result in them getting the appropriate XML feed.  My action method takes the feedKey as a parameter and then passes it to a factory method on my FeedService class that returns an instance of the appropriate FeedBuilder object.  The FeedBuilder is the class that I’ll use to encapsulate logic for getting job data and formatting it as an XML document. I’ll have a different FeedBuilder for each feedKey.  The design is a variation on the Strategy pattern.  So, back to controller action method. Here’s what it looks like.

        // Feed
        [AcceptVerbs(HttpVerbs.Get)]
        public ContentResult Feed(string feedKey)
        {
            var feedBuilder = this.FeedService.GetFeedBuilderFor(feedKey);
            return this.Content(feedBuilder.GetFeedXml(), "text/xml");
        }

The Factory Method

The factory method on my FeedService is pretty straight forward.  It just returns an instance of the right FeedBuilder for the feedKey that we pass in to it.  Note that the return type is FeedBuilderBase which is an abstract class that defines the shape of a FeedBuilder.

        // GetFeedBuilderFor
        public virtual FeedBuilderBase GetFeedBuilderFor(string feedKey)
        {
            switch(feedKey)
            {
                case FeedKey.SimplyHired:
                    return new SimplyHiredFeedBuilder();
                case FeedKey.Indeed:
                    return new IndeedFeedBuilder();
                default:
                    return new EmptyFeedBuilder();
            }
        }

The FeedBuilderBase

Remember we’re using a Strategy pattern.  Usually you would define the shape of your strategy class with an interface, but I’m going to use an abstract class because there’s some boilerplate code that will be the same for all of my concrete FeedBuilder classes and I want to implement that code in a single base class.  My abstract class is FeedBuilderBase and it looks like this.

    public abstract class FeedBuilderBase
    {
        //**************************************************************************************
        // PROPERTIES
        //**************************************************************************************
 
        // FeedService
        private FeedService _feedService;
        public virtual FeedService FeedService
        {
            get { return NewIfNull(_feedService); }
            set { _feedService = value; }
        }


        //**************************************************************************************
        // ABSTRACT METHODS
        //**************************************************************************************

        // GetFeedData
        public abstract List<JobFeedItem> GetFeedData();

        // BuildXmlFor
        public abstract XDocument BuildXmlFor(List<JobFeedItem> list);


        //**************************************************************************************
        // HELPER METHODS
        //**************************************************************************************
       
        // NewIfNull
        public virtual T NewIfNull<T>(T obj) where T : new()
        {
            if (obj == null) { obj = new T(); }
            return obj;
        }

        // GetFeedXml
        public virtual string GetFeedXml()
        {
            List<JobFeedItem> list = GetFeedData();
            XDocument xdoc = BuildXmlFor(list);
            var sb = new StringBuilder();
            var sw = new StringWriterUtf8(sb);
            xdoc.Save(sw);
            return sb.ToString();
        }
    }

I have two abstract methods, GetFeedData and BuildXmlFor.  These methods represent the two things that change for each XML feed. Each company has slightly different business rules around what data they want to pull and each company has it’s own proprietary XML format.  These 2 methods will have to be overridden whenever we create a concrete FeedBuilder.   

You’ll also notice that we implemented GetFeedXml which is the method we called in our action method to get the text of our XML document. GetFeedXml should have been very easy to write, but it took a little time due to an unexpected encoding problem that I described in How to Create XML in C# with UTF-8 Encoding.

The Concrete FeedBuilder

Now I’m ready to create my first concrete FeedBuilder class.  I’m going to start with a jobsite aggregator called SimplyHired.  So I create a new SimplyHiredFeedBuilder class that inherits from FeedBuilderBase an I override my GetFeedData and BuildXmlFor methods.  GetFeedData is just a wrapper for the appropriate data access method in my FeedService class. GetFeedData returns a list of JobFeedItem objects.  JobFeedItem is a simple Data Transfer Object (DTO) that I created to contain the aggregate of data needed to build a feed item.

BuildXmlFor is more interesting.  It takes a list of JobFeedItem objects returned by our GetFeedData method and transforms it into an XDocument using a LINQ query.  The LINQ query is just a select with a bunch of nested XElement constructors that create the XML elements needed to represent each job.  We then take the expression created to represent the list of jobs as XElements and we wrap it in a single top level XElement called, wait for it…. jobs.  BTW, it is at this point that the LINQ expression actually executes.  Up to now it has just been an expression.  As soon as we use it in the constructor for our jobs XElement the expression compiles and executes.

So, we now have an XML tree contained in a single XElement called jobs.  To complete the method we just wrap the jobs XElement in a new XDocument, return the XDocument, and we’re done. 

    public class SimplyHiredFeedBuilder:FeedBuilderBase
    {
        //**************************************************************************************
        // FEEDBUILDERBASE OVERRIDES
        //**************************************************************************************

        // GetFeedData
        public override List<JobFeedItem> GetFeedData()
        {
            return this.FeedService.GetJobFeedItemsForSimplyHired();
        }


        // BuildXmlFor
        public override XDocument BuildXmlFor(List<JobFeedItem> list)
        {
            var xmlExpression =
                from JobFeedItem j in list
                select new XElement("job",
                    new XElement("title", j.JobTitle),
                    new XElement("job-code", j.JobGuid),
                    new XElement("job-board-name", j.CompanyName),
                    new XElement("job-board-url", j.CompanyJobPageUrl),
                    new XElement("detail-url", ""),
                    new XElement("apply-url", GetApplyUrl(j.CompanyKey, j.JobGuid)),
                    new XElement("job-category", j.JobCategory),
                    new XElement("description",
                        new XElement("summary", j.JobDescription),                  
                        new XElement("required-skills", ""),
                        new XElement("required-education", ""),
                        new XElement("required-experience", ""),
                        new XElement("full-time", j.IsFullTime),
                        new XElement("part-time", j.IsPartTime),
                        new XElement("flex-time", ""),
                        new XElement("internship", j.IsInternship),
                        new XElement("volunteer", ""),
                        new XElement("exempt", ""),
                        new XElement("contract", j.IsContract),
                        new XElement("permanent", j.IsPermanent),
                        new XElement("temporary", j.IsTemp),
                        new XElement("telecommute", "")
                        ),
                    new XElement("compensation",
                        new XElement("salary-range", ""),                  
                        new XElement("salary-amount", ""),
                        new XElement("salary-currency", ""),
                        new XElement("benefits", "")
                        ),
                    new XElement("posted-date", GetPostedOnDate(j)),
                    new XElement("close-date", GetClosedOnDate(j)),
                    new XElement("location",
                        new XElement("address", ""), 
                        new XElement("city", j.JobCity), 
                        new XElement("state", j.JobState), 
                        new XElement("zip", ""), 
                        new XElement("country", "")
                        ),
                    new XElement("contact",
                        new XElement("name", j.ContactName),
                        new XElement("email", j.ContactEmail),
                        new XElement("hiring-manager-name", ""),
                        new XElement("hiring-manager-email", ""),
                        new XElement("phone", j.ContactPhone),
                        new XElement("fax", "")
                        ),
                    new XElement("company",
                        new XElement("name", j.CompanyName),
                        new XElement("description", j.CompanyDescription),
                        new XElement("industry", ""),
                        new XElement("url", j.CompanyUrl)
                        )
                    );
            var jobs =  new XElement("jobs", xmlExpression);
            var declaration = new XDeclaration("1.0", "utf-8", null);
            return new XDocument(declaration, jobs);
        }    
    }

Conclusion

So I built it, tested it, and it works.  Except for the hour that I spend trying to figure out my UTF-8 encoding problem, the LINQ / XElement method was a relatively painless way to create XML. I love the simplicity of the MVC action method and the fact that it gives me a ContentResult type that gives me access the right parts of the stack.  The LINQ / XElement query was concise and the style of passing element data in XElement constructors makes it hard to mess up the document structure. My conclusion is that I like it and I’ll definitely be using this technique again.

Sunday, February 13, 2011

How To Create XML in C# with UTF-8 Encoding

I can’t believe that I spent over an hour on this problem.  It’s one of those things that you can’t understand how it’s possible that it doesn’t just work. But it doesn’t, so here’s the solution I found for anyone who might have the same issue.

The Problem: My XML refuses to use UTF-8 encoding

I have some code where I’m doing a query and creating an XML doc from the data that’s returned.  I used LINQ to XML to create my XML and package it up in an XDocument.  The XDocument allows me to set the XML version and the encoding. Here’s the code I used to create and return my XDocument.

            var declaration = new XDeclaration("1.0", "utf-8", "yes");
            return new XDocument(declaration, jobs);

So far so good.  Now the last (and what should be trivial) step is to write that XML to a string and return it.  This is where things go wrong.  To get an XDocument object to write out a full XML document you call it’s Save method.  No problem, the Save method has an overload that takes a StringWriter parameter so I’ll just create a StringWriter and a StringBuilder and I’ll be in business.  Here’s my initial code.

        // GetFeedXML
        public virtual string GetFeedXML()
        {
            List<JobFeedItem> list = GetFeedData();
            XDocument xdoc = BuildXmlFor(list);
            var sb = new StringBuilder();
            var sw = new StringWriter(sb);
            xdoc.Save(sw);
            return sb.ToString();
        }

That all looks good. So I run it and here’s the result.

    <?xml version="1.0" encoding="utf-16" standalone="yes" ?>
    <jobs>
      <job>
        <title>Audit Engagement Manager</title>

What the heck is that???  UTF-16??  It’s like the UTF-8 encoding that I set in my XDocument was completely ignored and .Net decided to use UTF-16 encoding.  How can this not work?  Where else do I even have an option to set the encoding? The StringWriter won’t let me set the encoding, the StringBuilder certainly won’t let me set the encoding.

So I started Googling and found that other people were having the same problem and I found several solutions that sounded plausible.  Most of them centered around creating an XMLWriter with a settings object that would allow me to set the encoding.  All of these required a fair bit of extra code and I never got one of them to actually work, but they did get me looking at the StringWriter as the place where I needed to set my encoding.

The Solution: Subclass StringWriter

At this point I’m looking into progressively more and more complex solutions when I stumble across a post by Ian Dykes called Writing XML with UTF-8 Encoding using XmlTextWriter and StringWriter.  Ian basically says to create a new StringWriterWithEncoding class that inherits from StringWriter but allows you to set the encoding in the constructor.  I used the same idea and created the StringWriterUtf8 class below.  Instead of taking the encoding in a constructor, I opted to make the Encoding property always return UTF8.

    public class StringWriterUtf8 : StringWriter
    {
        public StringWriterUtf8(StringBuilder sb) : base(sb)
        {
        }

        public override Encoding Encoding
        {
            get { return Encoding.UTF8; }
        }
    }

Now I just need to use StringWriterUtf8 in my code instead of StringWriter and I’ll be using UTF-8 encoding in my writer.  I did it, I tested it, and it worked.  My XML output now looks like this:

    <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
    <jobs>
      <job>
        <title>Audit Engagement Manager</title>

Thank you Ian for understanding more about this than I do and taking the time to put the solution out on your blog.  By the way, I think it’s worth mentioning that several people posted more “settings type” solutions in the comments to Ian’s post.  I tried them.  They didn’t work for me.  The only thing that did work was Ian’s idea of subclassing the StringWriter.  So I now have a working method and here’s the final version of GetFeedXml that uses my StringWriterUtf8 class.

        // GetFeedXML
        public virtual string GetFeedXML()
        {
            List<JobFeedItem> list = GetFeedData();
            XDocument xdoc = BuildXmlFor(list);
            var sb = new StringBuilder();
            var sw = new StringWriterUtf8(sb);
            xdoc.Save(sw);
            return sb.ToString();
        }

Tuesday, February 8, 2011

Refactoring a TrySave Method

When writing code, it’s unusual for me to get it right the first time.  Typically I’ll just write a big block of statements that do something that I’ll need done.  Then I’ll verify that it works.  Then I’ll look at it, notice what an ugly mess it is, and refactor it so that the poor developer who inherits this code (and that developer might very well be me) will have some hope of maintaining it. Here’s a typical example that came up this week.

The scenario

I’m working in a controller class in an ASP.Net MVC2 application.  I have some action methods that need to save the data passed in via a signup form.  The  signup form collects all of the data needed to create a new company and a new user in my application.  So my signup form is a composite of Company data, User data, an other data that’s needed for the UI (like a ConfirmPassword field).  I’ve chosen to encapsulate all of this stuff that the signup form needs in a view model class called SignupVM.  It looks like this.

    public class SignupVM
    {
        public User User { get; set; }
        public Company Company { get; set; }
        public string ConfirmPassword { get; set; }
        public string FormError { get; set; }
        public string FormMessage { get; set; }

        public SignupVM()
        {
            this.User = new User();
            this.Company = new Company();
            this.ConfirmPassword = string.Empty;
            this.FormError = string.Empty;
            this.FormMessage = string.Empty;
        }
    }

So that part works really well.  Here’s where it starts to get a little messy.  I have a couple of Action Methods in my controller that receive a SignupVM that’s been populated with data by the View (or more accurately, the ModelBinder) and they need to save that data.  Saving data involves three main steps.  First I need to validate the Company, the User, and my ConfirmPassword field.  Second I need to actually save the data, but I need to save the Company first and then make sure I set the correct CompanyGuid on the User before I save the User data. Third, I have some standard data that needs to get created for all new signups.  Right now the only standard data is the GeneralApplicantsJob but I know that there will be a need for more standard data down the road.  To handle this stuff, I created a TrySave() method in my controller class that looks like this.

        // TrySave - SignupVM
        private bool TrySave(SignupVM vm)
        {
            var userValidator = new UserValidator();
            var companyValidator = new CompanyValidator();
            var isError = false;
            // validate user
            try
            {
                userValidator.Validate(vm.User);
                ValidateConfirmPassword(vm);
            }
            catch (RuleException e)
            {
                isError = true;
                e.ErrorList.SetUiFieldNames(GetUserFieldNameMappings());
                e.ErrorList.CopyToModelState(ModelState, "User");
            }
            // validate company
            try
            {
                companyValidator.Validate(vm.Company);
            }
            catch (RuleException e)
            {
                isError = true;
                e.ErrorList.SetUiFieldNames(GetCompanyFieldNameMappings());
                e.ErrorList.CopyToModelState(ModelState, "Company");
            }
            // validate vm level fields
            try
            {
                ValidateConfirmPassword(vm);
            }
            catch (RuleException e)
            {
                isError = true;
                e.ErrorList.CopyToModelState(ModelState, "");
            }
            // if error, return false
            if (isError) { return false; }
            // if no error let's save the Company
            this.CompanyService.Save(vm.Company);
            // set the companyguid for the user
            vm.User.CompanyGuid = vm.Company.CompanyGuid;
            //save the user
            this.UserService.Save(vm.User);
// create the GeneralApplicants job, it's created the first time we get it.           
            this.JobService.GetGeneralApplicantsJobForCompany(vm.Company.CompanyGuid);
            return true;
        }

Let’s Refactor

So, this block of code isn’t unmanageable, but I could definitely see it becoming unmanageable if I leave it like this and it gets added to a few times.  Plus, it’s not immediately clear what this code is doing.  What am I returning? Where am I returning it?  What logic decides what my return value is? Looking at it I realize that I’m writing in a very Imperative style that puts the focus on the individual steps of “how” to do something, instead of writing in a Declarative (or Functional) style that puts the focus on “what” is being done.  The code above is just a big list of steps that are a little difficult to follow without the comments.  I’m just validating data and saving data, so why do I have all of these statements in my method?  I can do better.

First let’s extract all of the validation code into an IsValidSignup() method.  Just that one refactoring helps quite a bit.  Now our TrySave method looks like this.

        // TrySave - SignupVM
        private bool TrySave(SignupVM vm)
        {
            if (!IsValidSignup(vm)) { return false; }
            // if no error let's save the Company           
            this.CompanyService.Save(vm.Company);           
            // set the companyguid for the user           
            vm.User.CompanyGuid = vm.Company.CompanyGuid;           
            //save the user           
            this.UserService.Save(vm.User);
            // create the GeneralApplicants job, it's created the first time we get it.           
            this.JobService.GetGeneralApplicantsJobForCompany(vm.Company.CompanyGuid);
            return true;       
        }

The next step is to refactor the data saving code.  There’s two things that bother me about this code.  First it’s critical that the the entities (Company and User) are saved it the right order, and that the user.CompanyGuid needs to be set in between the saves.  Second, it’s critical that the GeneralApplicantsJobForCompany get created after the Company has been saved, plus I know that there will be a need for more standard data later on, which means at some point a developer is going to have to modify this helper method in a controller class to make sure signups are created with the right standard data.  That feels like something that should be in my business layer, not in my UI code.  So, I decided to extract all of the persistence logic (including the creation of standard data) to a new method on my SystemService class in my business layer. The mehtod is called SignupNewCompany() and now my TrySave method looks like this.

        // TrySave - SignupVM
        private bool TrySave(SignupVM vm)
        {
            if (!IsValidSignup(vm)) { return false; }
            this.SystemService.SignupNewCompany(vm.Company, vm.User);
            return true;
        }

This looks much cleaner to me.  The focus is on what I’m doing instead of how I’m doing it, and the intent of the code is much more clear even though it no longer has comments.  Now I do have three methods instead of one, but each of those three methods does one thing that is easy to understand at a glance.  Best of all, I realized that I had put some logic in my UI that really needed to live in my business layer where it would be easier to reuse and easier to maintain.  For anyone who’s interested, here are all 3 methods in their final form.

 

        // TrySave - SignupVM
        private bool TrySave(SignupVM vm)
        {
            if (!IsValidSignup(vm)) { return false; }
            this.SystemService.SignupNewCompany(vm.Company, vm.User);
            return true;
        }
 
        // IsValidSignup
        public bool IsValidSignup(SignupVM vm)
        {
            var userValidator = new UserValidator();
            var companyValidator = new CompanyValidator();
            var isError = false;
            // validate user
            try
            {
                userValidator.Validate(vm.User);
            }
            catch (RuleException e)
            {
                isError = true;
                e.ErrorList.SetUiFieldNames(GetUserFieldNameMappings());
                e.ErrorList.CopyToModelState(ModelState, "User");
            }
            // validate company
            try
            {
                companyValidator.Validate(vm.Company);
            }
            catch (RuleException e)
            {
                isError = true;
                e.ErrorList.SetUiFieldNames(GetCompanyFieldNameMappings());
                e.ErrorList.CopyToModelState(ModelState, "Company");
            }
            // validate vm level fields
            try
            {
                ValidateConfirmPassword(vm);
            }
            catch (RuleException e)
            {
                isError = true;
                e.ErrorList.CopyToModelState(ModelState, "");
            }
            return !isError;
        }
 
        public void SignupNewCompany( Company newCompany, User newUser)
        {
            // create the new company
            this.CompanyService.Insert(newCompany);
            // create the new user
            newUser.CompanyGuid = newCompany.CompanyGuid;
            this.UserService.Save(newUser);
            // create the GeneralApplicants job, it's created the first time we get it.           
            this.JobService.GetGeneralApplicantsJobForCompany(newCompany.CompanyGuid);
        }

Monday, January 17, 2011

How To Not Hate Dependency Injection.

The Dependency Injection pattern is all the rage these days and more and more DI containers are becoming part of how we build .Net applications.  I still have a love / hate relationship with Dependency Injection.  I love the idea of being able to inject any external dependencies into my classes, thereby breaking those dependencies, but I hate the idea of creating an interface for every class that I need to inject, then maintaining that interface as well as any classes that implement it.  Let me show you what I mean.

Dependency Injection on an MVC  Controller Base Class With Interfaces

Typical scenario, I have an ASP.Net MVC2 application that needs to get data from a database. All of my data access code is contained in service classes like UserService, SystemService, CompanyService, etc.  I don’t want to manually declare and instantiate whatever service classes I need in each of my controller classes, so I created an abstract base class for my controllers called AtsControllerBase which has properties that will provide instances of my service classes using a lazy creation pattern.  Here’s an abbreviated version of the base class.

    public abstract class AtsControllerBase : Controller
    {
        //******************************************************
        // PROPERTIES
        //******************************************************

        // StateBox
        private HfStateBox _stateBox;
        public HfStateBox StateBox
        {
            get { return NewIfNull(_stateBox); }
            set { _stateBox = value; }
        }
        // AuthToken
        public AuthToken AuthToken { get { return StateBox.AuthToken; } }
        // ApplicantService
        private ApplicantService _applicantService;
        public ApplicantService ApplicantService
        {
            get { return NewIfNull(_applicantService); }
            set { _applicantService = value; } 
        }
        // CompanyService
        private CompanyService _companyService;
        public CompanyService CompanyService
        {
            get { return NewIfNull(_companyService); }
            set { _companyService = value; }
        }
        // FolderService
        private FolderService _folderService;
        public FolderService FolderService
        {
            get { return NewIfNull(_folderService); }
            set { _folderService = value; }
        }       
        // JobService
        private JobService _jobService;
        public JobService JobService
        {
            get { return NewIfNull(_jobService); }
            set { _jobService = value; }
        }
        // SecurityService
        private SecurityService _securityService;
        public SecurityService SecurityService
        {
            get { return NewIfNull(_securityService); }
            set { _securityService = value; }
        }
        // SystemService
        private SystemService _systemService;
        public SystemService SystemService
        {
            get { return NewIfNull(_systemService); }
            set { _systemService = value; }
        }
        // ServicePlanService
        private ServicePlanService _servicePlanService;
        public ServicePlanService ServicePlanService
        {
            get { return NewIfNull(_servicePlanService); }
            set { _servicePlanService = value; }
        }       
        // UserService
        private UserService _userService;
        public UserService UserService
        {
            get { return NewIfNull(_userService); }
            set { _userService = value; }
        }
        // WorkflowService
        private WorkflowService _workflowService;
        public WorkflowService WorkflowService
        {
            get { return NewIfNull(_workflowService); }
            set { _workflowService = value; }
        }


        //******************************************************
        // UTILITY METHODS
        //******************************************************
       
        // NewIfNull
        public T NewIfNull<T>(T obj) where T:new()
        {
            if (obj == null) { obj = new T(); }
            return obj;
        }
    }

This pattern works well for me because my concrete controllers never need to instantiate a service, they can just access any of the service properties in the base class.  I don’t have the overhead of newing up a bunch of service classes that the concrete controller won’t use because the services aren’t instantiated until the first time the service property is accessed.  That’s the lazy creation part.  Finally, each property has a public setter, so I can replace any of my services if I need to inject a mock or stub or something.

So this already looks a lot like Dependency Injection.  After all we have public setters for each of the services so we could switch them out if needed.  There’s one thing missing though.  We have no interfaces.  Our properties are all using the concrete type of the service class (like FolderService) instead of some public interface (like IFolderService).  So we could inject something, but it would have to be another instance of FolderService.  That get’s us nowhere. How can we inject something else like a MockFolderService??   Hmmmm,  I guess the right way to implement Dependency Injection is to create an IFolderService interface for my FolderService class.  At least that’s the pattern that I always see in books and code samples.  Let’s try that.  Ok, FolderService only has 10 public methods.  That’s not too bad so we’ll start with that one.  Here’s the service code.

    public partial class FolderService : ServiceBase
    {

        //**************************************************************************************
        // FOLDER METHODS
        //**************************************************************************************

        // GetFolderByFolderGuid
        public virtual Folder GetFolderByFolderGuid(Guid folderGuid)
        {
            string sql = @"SELECT *
                           FROM [Folder]                            
                           WHERE [FolderGuid] = @FolderGuid";
            SqlDao dao = SharedSqlDao;
            SqlCommand command = dao.GetSqlCommand(sql);
            command.Parameters.Add(dao.CreateParameter("@FolderGuid", folderGuid));
            return dao.GetSingle<Folder>(command);
        }

        // GetListOfFolderWithCountsForCompany
        public virtual List<FolderWithCount> GetListOfFolderWithCountsForCompany(Guid companyGuid)
        {
            string sql = @"SELECT f.*, (SELECT COUNT([ApplicantGuid])
FROM [ApplicantInFolder] WHERE [FolderGuid] = f.[FolderGuid]) As ApplicantCount

                          FROM [Folder] f
                          WHERE f.[CompanyGuid] = @CompanyGuid";
            SqlDao dao = SharedSqlDao;
            SqlCommand command = dao.GetSqlCommand(sql);
            command.Parameters.Add(dao.CreateParameter("@CompanyGuid", companyGuid));
            return (dao.GetList<FolderWithCount>(command));
        }

         // GetListOfFoldersForCompany
        public virtual List<Folder> GetListOfFoldersForCompany(Guid companyGuid)
        {
            string sql = @"SELECT f.*
                                  FROM [Folder] f
                                  WHERE f.[CompanyGuid] = @CompanyGuid";
            SqlDao dao = SharedSqlDao;
            SqlCommand command = dao.GetSqlCommand(sql);
            command.Parameters.Add(dao.CreateParameter("@CompanyGuid", companyGuid));
            return (dao.GetList<Folder>(command));
        }


        // GetListOfFoldersForApplicant
        public virtual List<Folder> GetListOfFoldersForApplicant(Guid applicantGuid)
        {
            string sql = @"select f.*
                        from Folder f
                        join ApplicantInFolder aif on aif.FolderGuid = f.FolderGuid
                        where aif.ApplicantGuid = @ApplicantGuid";
            SqlDao dao = SharedSqlDao;
            SqlCommand command = dao.GetSqlCommand(sql);
            command.Parameters.Add(dao.CreateParameter("@ApplicantGuid", applicantGuid));
            return (dao.GetList<Folder>(command));
        }

        // GetCachedListOfFoldersForCompany
        public virtual List<FolderWithCount> GetCachedListOfFoldersForCompany(Guid companyGuid)
        {
            if (companyGuid.Equals(NullValues.NullGuid))
            {
                // return empty list if a null guid was passed
                return new List<FolderWithCount>();
            }
            string key = "__GetCachedListOfFoldersForCompany_" + companyGuid.ToString();
            CacheHelper helper = new CacheHelper();
            List<FolderWithCount> list = helper.TryGet<List<FolderWithCount>>(key);
            if (list == null)
            {
                RefreshCachedListOfFoldersForCompany(companyGuid);
                list = helper.TryGet<List<FolderWithCount>>(key);
            }
            return list;
        }


        // RefreshCachedListOfFoldersForCompany
        public virtual void RefreshCachedListOfFoldersForCompany(Guid companyGuid)
        {
            string key = "__GetCachedListOfFoldersForCompany_" + companyGuid.ToString();
            CacheHelper helper = new CacheHelper();
            List<FolderWithCount> list = helper.TryGet<List<FolderWithCount>>(key);
            list = GetListOfFolderWithCountsForCompany(companyGuid);
            helper.Add(key, list);
        }

        // Insert
        public virtual void Insert(Folder folder)
        {
            this.FolderPersister.Insert(folder);
        }


        // Save
        public virtual void Save(Folder folder)
        {
            this.FolderPersister.Save(folder);        
        }

        // Delete
        public virtual void Delete(Folder folder)
        {
            this.FolderPersister.Delete(folder.FolderGuid);
        }


        // AddApplicantToFolder
        public virtual void AddApplicantToFolder(Guid applicantGuid, Guid companyGuid, Folder folder)
        {
            this.FolderPersister.SafeInsertApplicantInFolder(applicantGuid, folder.FolderGuid);
            RefreshCachedListOfFoldersForCompany(companyGuid);
        }
    }

We’ve basically got 10 public data access methods. Now I need to create a public interface that defines all of the public methods, so I’m going to create a new IFolderService interface.  ReSharper even makes it easy for me with a handy Extract Interface tool.  So my interface looks like this.

    public interface IFolderService
    {
        Folder GetFolderByFolderGuid(Guid folderGuid);
        List<FolderWithCount> GetListOfFolderWithCountsForCompany(Guid companyGuid);
        List<Folder> GetListOfFoldersForCompany(Guid companyGuid);
        List<Folder> GetListOfFoldersForApplicant(Guid applicantGuid);
        List<FolderWithCount> GetCachedListOfFoldersForCompany(Guid companyGuid);
        void RefreshCachedListOfFoldersForCompany(Guid companyGuid);
        void Insert(Folder folder);
        void Save(Folder folder);
        void Delete(Folder folder);
        void AddApplicantToFolder(Guid applicantGuid, Guid companyGuid, Folder folder);
        SqlDao SharedSqlDao { get; set; }
        ApplicantPersister ApplicantPersister { get; set; }
        CareerSiteSettingsPersister CareerSiteSettingsPersister { get; set; }
        CompanyPersister CompanyPersister { get; set; }
        CompanySettingsPersister CompanySettingsPersister { get; set; }
        FolderPersister FolderPersister { get; set; }
        HistoryItemPersister HistoryItemPersister { get; set; }
        JobPersister JobPersister { get; set; }
        JobStubPersister JobStubPersister { get; set; }
        ResumePersister ResumePersister { get; set; }
        UserPersister UserPersister { get; set; }
        WorkflowPersister WorkflowPersister { get; set; }
        T NewIfNull<T>(T obj) where T : new();
        string GetSqlCsv(List<Guid> list);
        string GetSqlCsv(List<int> list);
    }

There, that wasn’t too bad. Now I just need to change my controller FolderService property to type IFolderService and I have Dependency Injection implemented for the FolderService.  I can create new classes that implement IFolderService and inject them into my controller using the public FolderService property like this.

            var controller = new FolderController();
            IFolderService mock = new MockFolderService();
            controller.FolderService = mock;

That’s great! Now I just need to do that for… wait… I’m going to have to do that for every service class in my application.  Then I’m going to have to maintain each of those interfaces every time I make a change to a service class.  That’s a lot of extra code and a lot of work that’s going to have to be repeated every time I make a change to my service classes.  Why am I doing this again?  This is starting to feel like the hate part of the love / hate relationship.

Dependency Injection on an MVC  Controller Base Class Without Interfaces

So I don’t really want to create an interface for every single dependency in my application and then have to maintain that interface as well as my concrete classes, but what other option do I have?  Everybody implements DI using interfaces right?  Interfaces are like a badge of honor that demonstrate you know how to architect an application the right way.  You haven’t been to architecture land until you have your interface badge. We love interfaces!

Well I don’t love any code that I have to spend extra time maintaining every time I make a change to my application.  All that stuff adds up after a while.  I call it the death of a thousand cuts.  One day you look up and all those little extra tasks like maintaining interfaces add up to a mountain of friction that makes it miserable to make changes to your code.  Now there are places for interfaces, but if possible I’m opting for an easier alternative.

So step one in the easier alternative, throw out the interface that I just created and change my FolderService property back to type FolderService (no more IFolderService).  Step two…. actually we don’t need a step two we’re done.  Lets take a closer look at one of the data access methods in our FolderService class.

       // GetFolderByFolderGuid
        public virtual Folder GetFolderByFolderGuid(Guid folderGuid)
        {
            string sql = @"SELECT *
                           FROM [Folder]                            
                           WHERE [FolderGuid] = @FolderGuid";
            SqlDao dao = SharedSqlDao;
            SqlCommand command = dao.GetSqlCommand(sql);
            command.Parameters.Add(dao.CreateParameter("@FolderGuid", folderGuid));
            return dao.GetSingle<Folder>(command);
        }

Hmmm, that’s a virtual method.  That means that I can create a class that inherits from FolderService and just override the GetFolderByFolderGuid() method.  The FolderService class actually functions as my interface in this scenario.   So, if I’m writing a unit test where I want to stub out my FolderService I could create the following class.

    public class FolderServiceStub: FolderService
    {
        public override Folder GetFolderByFolderGuid(Guid folderGuid)
        {
            return new Folder() {FolderGuid = folderGuid, FolderName = "Test Folder"};
        }
    }

FolderServiceStub inherits from FolderService so I can use that stub class anywhere that an object of type FolderService is expected.  The end result is that my testing code (or any other DI code) winds up looking almost exactly like my code did with full on interface based Dependency injection

    var controller = new FolderController();
    FolderService mock = new FolderServiceStub();
    controller.FolderService = mock;

Summary

So, make all of your public methods virtual and you can implement a Poor Man’s Dependency Injection that doesn’t require interfaces.  It’s not the right solution every situation, but I’ve found that it works most of the time for me. It also has the one quality that I prize most in code.  It’s so simple that I forget it’s even there.