Archive for the ‘Asp.Net MVC’ Category


You are currently browsing the archives for the Asp.Net MVC category.

Archives

  • Categories

  • MVC 3 Preview Is Out…

    Wednesday, July 28th, 2010

      Scott Gu announced yesterday that the new MVC 3 Preview has been released which includes the new Razor View engine…

    Download it from here..

    Razor – Unit Testing Your Views in MVC2 with QUnit

    Monday, July 19th, 2010

    Ok this is a bit of a follow up from my earlier blog about the newly announced MVC view engine Razor from Scot Guthries blog a couple of  weeks ago. Below is a quote that Scott has made in the comments to the original post.

    “The Razor parser and view engine can be instantiated and used outside of the ASP.NET application domain.  This means you can directly instantiate and use it within a unit test project without any dependencies on running ASP.NET.

    From a unit testing perspective you can indicate the view template you want to run, supply it with any dependencies, and then pass your own test models/viewmodels to it and have it run and render back a string to you. You could then verify that the correct content came back.  This would isolate the views from your controllers and any data access, and allow you to also isolate them from the runtime environment.  View engines in ASP.NET MVC VNext (both Razor and the .ASPX one) will also support and integrate with dependency injection as well.”

    Let’s start with talking about the current testing story with the current MVC framework. Now clearly you want to put as much logic into your controller as possible which is currently testable with the current MVC framework. But on the  modern MVC websites that I’ve been working on there ends up being a considerable amount of JQuery in most pages.

    This is where I hear you shout “but what about QUnit you can test your JQuery with that”  Yes you can but do I do it..No I don’t.  I never really got QUnit it always seemed great in theory but in reality it seemed like too much work to implement.

    Let me elaborate. All the examples I could find when I was starting out with QUnit involved testing some JavaScript discreet function that did some work and returned a value.  For example a function that added two numbers together and gave you the total back. QUnit works really well for that kind of thing. However I don’t find myself writing much of that kind of  logic in JQuery when I am using MVC. I know its possible to do it in JQuery but most of the time I try to push that kind of logic back into the .NET world and onto the server  where it belongs rather than in the browser.

    So typically I find myself writing JQuery that does fairly trivial stuff. Hiding and showing stuff and manipulating items in the Dom. Now when I say trivial it is still important. If you hide your submit button when it should be displayed you have broken your page.

    Now it is possible to test this logic with QUnit, but for each test or  group of tests  you had recreate the HTML for your page or part of your page to test your JavaScript against. It is this that always seemed a bit lame to me. You were never really testing against your view proper but a mock up of your view.  Not only is it a lot more work to write your tests initially but there is a lot more maintenance work to do going forward. Any change to your HTML mark up in your view needs to be replicated across your test HTML.  Now I know you have to do maintenance with your .NET tests but most of the time we have compile-time checking. If you change the name a property on a class and you don’t update your unit test it won’t compile. Change the name of a div in your mark up and forget to implement that in your test HTML and there is nothing to tell you that there is a mismatch.

    To counter this John Teague over at Los Techies outlines a technique that you can use to generate your markup automatically. To be honest I haven’t used this approach as it still seems like a lot of extra hard work, but it’s worth considering.

    Therefore going back to Scott Guthrie’s  comment that we will now be able to  isolate the view from the controller pass in some data and render back a screen  as HTML. This is just fantastic, and for me the last piece in the puzzle with regards to testing. With this functionality it will should be relatively trivial to produce the markup that we can run our QUnit tests against and it means that we are actually testing our view rather than a mock up of it.

    Well done Microsoft I think this is a positive step, and I can’t wait to get my hands on the framework. Keep up the good work.

    Razor View Engine For MVC2

    Thursday, July 8th, 2010

    Check out Scott Guthrie’s new blog post on  Razor the new view engine that will ship with MVC 2 shortly.

    At first glance it looks really nice and simple to learn. Essentially rather than wrapping your code elements in your view with <% %> tags you can simply use an @ symbol. The view engine has syntactic awareness built into it so there is  no need to close off your tags. If you want to declare multiple lines of code you use the following you wrap your code in the following symbols @{  code goes here } This will go a long way to reduce the tag soup that you get in your views with the current out the box MVC view engine.

    In Scott Gu’s blog he also states that it will be possible to fully Unit Test your views without the need of a web controller or web server. This sounds really interesting to me and I wonder how far Microsoft will take it as I would love to see this extend into being able to test your JQuery in your views as well, as these days I find this is where the majority of the logic sits. I know it is possible test JQuery with frameworks such as QUnit but I haven’t been altogether comfortable with the amount of duplicated HTML that you have create in order to write your tests…I digress maybe that’s a subject for another post.

    Anyway I look forward to it’s release.

    ASP.Net MVC Option Group DropDown Control

    Tuesday, December 15th, 2009

    Option Groups for drop down lists have been an HTML feature for many years now but have never been supported in any Asp.Net control. It was a bit of a shame recently whilst working on a new Asp.Net MVC web site to find that its still not possible to do out of the box.

    optiongroup

    However the good thing about MVC is that its a really easy  to write your own custom controls in the shape of HTML helpers so I thought I’d go about writing my own.

    What did I want the control to do?

    Firstly I wanted it to be strongly typed so no magic strings. I also wanted to be able to pass the control an enumerable collection of objects and use lambda expressions to tell the control which properties to render the text, value and how to group the dropdown items by.

    
    <%= Html.OptionGroupDropDownList(
              ViewData.Model.Cars,
              car =>  car.CountryOfOrigin,
              car => car.Brand,
              car => car.Brand,
              car => car.Brand == "BMW")%>
    

    Line 2 above represents the collection of cars we wish to render as option items.
    Line 3 is the property value of a car we wish to group them by.
    Line 4 is the property value of a car we wish to use as the option value.
    Line 5 is the property value a car we wish to use for the option text.
    Line 6 is a condition we can supply to tell the control which drop down item should be selected.

    which renders HTML that looks something a little like this:

    
    

    Ok so the code looks like this..

    public static string OptionGroupDropDownList<T, TProperty, TProperty1, TProperty2>
    ( this HtmlHelper htmlHelper,
      string name,
      string optionLabel,
      IEnumerable<T> collection,
      Func<T, TProperty> optionGroupProperty,
      Func<T, TProperty1> optionValueProperty,
      Func<T, TProperty2> optionTextProperty,
      Func<T, bool> isSelectedCondition)
    {
          var groupedCollection = collection.GroupBy(optionGroupProperty);
    
          // We are trying to generate the Html that looks something like this...
          //<select>
          //  <optgroup label="Swedish Cars">
          //      <option value="volvo">Volvo</option>
          //      <option value="saab">Saab</option>
          //  </optgroup>
          //</select>";
          using (var stringWriter = new StringWriter())
          using (var writer = new HtmlTextWriter(stringWriter))
          {
              writer.AddAttribute(HtmlTextWriterAttribute.Name, name);
              writer.AddAttribute(HtmlTextWriterAttribute.Id, name);
              //<Select>
              writer.RenderBeginTag(HtmlTextWriterTag.Select); 
    
              if(string.IsNullOrEmpty(optionLabel) == false)
               {
                   writer.RenderBeginTag(HtmlTextWriterTag.Option);
                   writer.Write(optionLabel);
                   writer.RenderEndTag();
                }
    
               // Group by our optGroup parameter...in the above example that would be
               // "Swedish Cars"
               foreach (var optionGroup in groupedCollection)
               {
                    var optionGroupLabel = optionGroup.Key;
                    // label="Swedish Cars"
                    writer.AddAttribute(Label, optionGroupLabel.ToString());
                    writer.RenderBeginTag(Optgroup); //<optgroup>  
    
                     foreach (var option in optionGroup)
                     {
                       var optionValue = optionValueProperty.Invoke(option).ToString();
                       var optionText = optionTextProperty.Invoke(option).ToString();
    
                       var isOptionSelected = isSelectedCondition.Invoke(option);
    
                       if (isOptionSelected)
                         writer.AddAttribute(HtmlTextWriterAttribute.Selected, "true");
    
                       // value = "volvo"
                       writer.AddAttribute(HtmlTextWriterAttribute.Value, optionValue); 
    
                       // <option>
                       writer.RenderBeginTag(HtmlTextWriterTag.Option);
                       // Volvo
                       writer.Write(optionText);
                       // </option>
                       writer.RenderEndTag();
                      }
                      // </optiongroup>
                       writer.RenderEndTag();
                    }
                     //</Select>
                    writer.RenderEndTag();
    
                    return stringWriter.ToString();
                }
            }
    

    Mocking HtmlHelpers in ASP.Net MVC

    Friday, December 4th, 2009

    NB: This post relates to version 1 of ASP.Net MVC

    I recently added a static extension method for generating a custom drop down list and wanted to test it using Rhino Mocks (version 3.5).
    One issue I kept banging my head against was how to create a Mock HtmlHelper in order to call the method correctly.
    A number of posts later, and various attempts at using some of the sample code and I finally came across this post detailing a bunch of MVC tests.

    After a minor amount of customising, I ended up with the following, which works like a charm for me to use in my tests.

            ///
            /// Creates a HTML helper for use in tests.
            ///
            private HtmlHelper CreateHtmlHelper()
            {
                var userControl = new ViewUserControl();
                var container = new ViewPage();
                container.Controls.Add(userControl);
                var context = MockRepository.GenerateMock<ViewContext>();
                userControl.ViewContext = context;
    
                return userControl.Html;
            }

    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