Wednesday, October 13, 2010

Insight Launch Party a Huge Success

The CodeSmith Insight Launch Party was a huge success. Thanks to the almost one hundred people that came out and partied with us. It was a blast, thank you all so much for coming out!

We did a 15 minute demo of Insight before we gave out prizes. To show that we had nothing up our sleeves the demo was completely unrehearsed and using our live production servers. I am pleased to say that it went off without a hitch! We even had some surprise audience participation as people in the crowd sent in emails to our demo instance during the presentation; not only was that fun, but it also really helped demonstrate the power and versatility of Insight in real time.

At the end of the demo we actually went overtime doing Q&A about Insight. Not only did we get asked a ton of questions from all around the room, but honestly they were great questions! This was flattering for two reasons: 1) As the speaker those questions told me that the audience was paying attention, and that what I was saying was intelligible. 2) As a developer it was great to see other developers thinking about use cases for Insight, and then being able to be one step ahead of the game and say "Yes, we support that."

Here are a few of the questions we were asked about Insight:

  • Can Insight report handled exceptions?
    • Yes. Insight's client API allows you to create cases for anything at anytime, and provides a series of CreateCase method overrides to make it especially easy to create a report from a caught exception.
  • Can Insight be used to submit feedback without reporting errors?
    • Yes. Insight can be configured to not report unhandled exceptions, and then you can still use the feedback forms and API to create and submit cases based only on user feedback.
  • Does Insight integrate with Microsoft Exchange?
    • Yes. Insight can send and receive email from almost any POP3 or IMAP server, that includes Microsoft Exchange.
  • Do you offer an installed solution?
    • This is the only question to which I had to answer "no." However, we are very interested in offering installed solutions in the future, so if you are interested in this please contact us directly (at sales@codesmithtools.com) and we will be more than happy to try and work with you!

In summary, the party was a blast. I think everyone had fun; I know I did. Insight is now released and available to log exceptions for developers everywhere. Also, feel free to check out the party photos we posted up on Facebook. (If you are in one and want to be tagged just let us know!)

Thanks again,
Tom DuPont

On behalf of,
The CodeSmith Tools

Friday, October 8, 2010

MVC2 Unit Testing, Populating ModelState

I love how testable ASP.NET MVC is, I also love MVC2's model validation. However when trying to unit test a controller method that used the ModelState, I quickly learned that the ModelState is not populated when just newing up a Controller and calling one of its public methods. As usual, I think this is best narrated by example:

Example Model and Controller

public class PersonModel
{
  [Required]
  public string Name { get; set; }
}

public class PersonController : Controller
{
  [AcceptVerbs(HttpVerbs.Get)]
  public ViewResult Register(Person person)
  {
    return View(new PersonModel()); 
  }

  [AcceptVerbs(HttpVerbs.Post)] 
  public ViewResult Register(Person person) 
  {
    if (!ModelState.IsValid) 
      return View(model); 

    PersonService.Register(person);
    return View("success");
  }
}

Example of the Problem

[Test] 
public void RegisterTest() 
{
  var model = new PersonModel { Name = String.Empty }; // This is model is invalid.
  var controller = new PersonController(); 
  var result = controller.Register(model);

  // This fails because the ModelState was valid, although the passed in model was not. 
  Assert.AreNotEqual("success", result.ViewName);
}

Solution

Other solutions I have come across were adding the errors to the model state manually, or mocking the ControllerContext as to enable the Controller's private ValidateModel method. I didn't like the former because it felt like I wasn't actually testing the model validation, and I didn't like the latter because it seemed like a lot of work to both mocking things and then still have to manually expose a private method.

My solution is (I feel) pretty simple: Add an extension method to the ModelStateDictionary that allows you to pass in a model, and it will then validate that model and add it's errors to the dictionary.

public static void AddValidationErrors(this ModelStateDictionary modelState, object model)
{
  var context = new ValidationContext(model, null, null); 
  var results = new List<ValidationResult>(); 
  Validator.TryValidateObject(model, context, results, true);

  foreach (var result in results) 
  { 
    var name = result.MemberNames.First(); 
    modelState.AddModelError(name, result.ErrorMessage);
  }
}

Example of the Solution

[Test] 
public void RegisterTest() 
{
  var model = new PersonModel { Name = String.Empty }; // This is model is invalid.
  var controller = new PersonController(); 

  // This populates the ModelState errors, causing the Register method to fail and the unit test to pass.
  controller.ModelState.AddValidationErrors(model);
  var result = controller.Register(model);
  Assert.AreNotEqual("success", result.ViewName); 
}

Real Time Web Analytics