Archive

Archive for the ‘ASP .NET’ Category

Integrating TypeMock with ASP .NET Unit tests

February 16th, 2009 Nizar 6 comments

When it comes to writing unit tests for your ASP .NET pages, there isn’t much help out there. I experimented with a few open source testing tools and found some major limitations.

Both NUnitAsp and WaitN, for instance, are “client-side” tools. In other words, you have to write your tests against the actual HTML output. For example, to get the value of a textbox, you have to specify the actual HTML id of the textbox. That’s painful! Especially, since ASP .NET ends up assigning long and complicated ID’s to your controls. Plus NUnitAsp is no longer being maintained or supported.

Unlike NUnitAsp and WaitN, VS Studio ASP .NET Unit testing let’s you examine the actual HttpRequest object. What this means is that you can call methods on your Page and get access to the controls within the page. VS Studio ASP .NET is a pretty decent tool and maybe the answer for you. IF you don’t need to use TypeMock that is. But if you do, then tough luck because VS Studio ASP .NET unit tests don’t work with TypeMock. If you give it try, you’ll get the following exception:

Test method AzAsh.WebApp.Tests.DefaultTest.LoginNotRequiredTest threw exception:  TypeMock.TypeMockException:
*** Typemock Isolator is not currently enabled.
To enable do one of the following:

* To run Typemock Isolator as part of an automated process you can:
   - run tests via TMockRunner.exe command line tool
   - use 'TypeMockStart' tasks for MSBuild or NAnt

* To work with Typemock Isolator inside Visual Studio.NET:
        set Tools->Enable Typemock Isolator from within Visual Studio

For more information consult the documentation (see 'Running' topic).

Check the enable property as they have suggested and you’ll notice that Typemock is enabled! So, what gives? I have no idea. But I do know that Ivonna – a ASP .NET testing tool that is being developed in partnership with TypeMock WILL let you work in conjunction with TypeMock. Like VS Studio, it allows you to examine the intrinsic objects, such as the Page object. In addition, it’s got another neat feature that let’s you inject setup code and assertions into your page’s lifecycle event handlers – very handy especially during type mocking. The only drawback is that it’s a little slow. The unit tests take a while to run.

So if you’ve been scratching your head trying to figure how to develop ASP .NET tests that can work with TypeMock, Ivonna is probably the tool you’ve been waiting for!

Post to Twitter Post to Yahoo Buzz Post to Delicious Post to Digg Post to Facebook Post to Reddit Reddit Post to StumbleUpon

Update Panels dont play well with Validators in Chrome

February 12th, 2009 Nizar No comments

If your page uses ASP .NET custom validators and an UpdatePanel, you will notice that your UpdatePanels will not work in Chrome. In order to fix this, you will have disable client script on the custom validators by setting EnableClientScript=false.

Hopefully this tip will save others the headache that I went through!

Happy Coding!

Post to Twitter Post to Yahoo Buzz Post to Delicious Post to Digg Post to Facebook Post to Reddit Reddit Post to StumbleUpon

Making ASP .NET Gridview a little less painful

January 28th, 2009 Nizar No comments

Isn’t it pain in the neck when you have to write the following for every input control whose value you want to extract from a Gridview:

public static void myGridView_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
   string firstname = ((TextBox)myGridview.Rows[e.RowIndex].
                                            FindControl("txtFirstname")).Text;
   string lastname = ((TextBox)myGridview.Rows[e.RowIndex].
                                            FindControl("txtLastname")).Text;
 
   //....and so on.. 
}

Well, you can make it a little easier by implementing the following method either in a class that extends GridView or by writing a extension method. In this example, I’ve written it as an extension method.

public static T FindControl<T>(this GridView gridView, string cntrlName, 
                                          int rowIndex)
      where T : Control
{
   return (T)(gridView.Rows[rowIndex].FindControl(cntrlName));
}

Now the code inside my page is little cleaner and easier to write:

public static void myGridView_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
   string firstname = gridView.FindControl<TextBox>("txtFirstname", e.RowIndex).Text;
   string lastname = gridView.FindControl<TextBox>("txtLastname", e.RowIndex).Text;
 
     //....and so on.. 
}

I admit it’s not something huge but it definitely is a big help when you have to type in that statement for every single control in your Gridview!

I hope that helps some!

Post to Twitter Post to Yahoo Buzz Post to Delicious Post to Digg Post to Facebook Post to Reddit Reddit Post to StumbleUpon

An easier way to write HTML input forms

January 23rd, 2009 Nizar 2 comments

Consider the block of code below:

<table cellpadding="3">
  <tr>
    <td valign="top">
      <b>First Name</b>
    </td>
    <td>
      <asp:TextBox ID="txtFirstName" runat="server" />
      <div>
        Please enter your first name.</div>
    </td>
  </tr>
  <tr>
    <td valign="top">
      <b>Last name</b>
    </td>
    <td>
      <asp:TextBox ID="txtLastName" runat="server" />
      <div>
        Please enter your last name.</div>
    </td>
  </tr>
</table>

The rendered output looks something like this:
HTML Input Form
You will notice that we have to repeat the <tr> and the <td> tags, along with any style information that these contain, for every row of our input form. Ouch! That's a lot of typing. Furthermore, if, in the future, we have make layout and/or style related changes, we'd have to modify all the pages in our application that contain these HTML input forms! Fortunately, there is an easier way.

By implementing a couple of simple ASP .NET server controls, we will save ourselves the trouble of typing the above shown HTML and will be able to simply type the following:

<cc:Form runat="server">
  <cc:FormField runat="server" Name="First Name" 
                      Description="Please enter the first name.">
    <asp:TextBox ID="txtFirstName" runat="server" />
  </cc:FormField>
  <cc:FormField runat="server" Name="Last Name" 
                     Description="Please enter the last name.">
    <asp:TextBox ID="txtLastName" runat="server" />
  </cc:FormField>
</cc:Form>

Now isn't that soo much more pleasant to the eyes and easier on your fingers? So how is this accomplished? As follows:

First, create a ASP .NET Server Control name Form.cs. This simple control will simply render the <table> tags. Below is the code for it:

public class Form : WebControl
{
  public override void RenderBeginTag(HtmlTextWriter writer)
  {
    writer.Write("<table cellpadding='3'>");
  }
  public override void RenderEndTag(HtmlTextWriter writer)
  {
    writer.Write("</table>");
  }
}

Notice the use of [ParseChildren(false)] attribute. This attributes ensures that 1) we will be able to nest additional controls inside this control and 2) The nested control won't actually become a child control this control. The second point is important and will explained in greater detail shortly.

Now we move on to the more interesting control: the FormField.cs control. This control renders the
<tr>'s, <td>'s, the input field label, and the input field description. Below is the code for it:

[ToolboxData("<{0}:FormField runat=server></{0}:FormField>"), ParseChildren(false)]
public class FormField : WebControl
{
  public string Name
  {
    get { return ViewState.GetAsString("Name"); }
    set { ViewState["Name"] = value; }
  }
  public string Description
  {
    get { return ViewState.GetAsString("Description"); }
    set { ViewState["Description"] = value; }
  }
  public string NameAlign
  {
    get { return ViewState.GetAsString("NameAlign"); }
    set { ViewState["NameAlign"] = value; }
  }
  public string ControlAlign
  {
    get { return ViewState.GetAsString("ControlAlign"); }
    set { ViewState["ControlAlign"] = value; }
  }
  public override void RenderBeginTag(HtmlTextWriter writer)
  {
    string beginHtml = @"<tr><td align={0}><b>{1}</b></td><td align={2}>";
    writer.Write(string.Format(beginHtml, NameAlign, Name, ControlAlign));
  }
  public override void RenderEndTag(HtmlTextWriter writer)
  {
    string endHtml = @"<div>{0}</div></td></tr>";
    writer.Write(endHtml, Description);
  }
}

The interesting parts of the class are the RenderBeginTag() and the RenderEndTag() methods. If you inspect these methods, you’ll see that the RenderBeginTag() is responsible for rendering:

  • The opening <tr> tag
  • The column that contains the input field label. For example:
    <td><b>First Name</b></td>
  • The opening <td> tag for the column that contains the actual input field (like the <asp:TextBox ID="txtFirstName" />, for example)

And the RenderEndTag() method is responsible for rendering:

  • The closing </td> tag for the column that contains the actual input field.
  • The <div> tag containing the input field description. For example:
    <div>Please enter the first name</div>
  • The closing </tr> tag

Well, that all sounds well and good. But wait! Where is the FormField control rendering the actual input field (the asp:TextBox)? The answer is that it isn’t. The use of the [ParseChildren(false)] attribute prevents the parsing of any embedded controls that FormField may have. Thus, in our example, when the Form and the FormField control's rendering has finished, the page control tree looks something like this:

- Page
  - Form
  - FormField
  - LiteralControl("<table cellpadding="3">")
  - LiteralControl("<tr><td>")
  - TextBox <asp:TextBox ID="txtFirstName" />
  - LiteralControl("<div>Please enter first name</div>")
  .....

Notice that the TextBox (txtFirstName) is a child of the Page instead of being a child of the FormField control. What this means is that instead of having to type something convoluted like:

string firstName = ((TextBox)this.formField1.FindControl("txtFirstName")).Text;

your page can directly reference the TextBox like so:

string firstName = txtFirstname.Text

I hope you’ve found this post helpful and informative. Please take some time to leave your feedback and/or comments to help me improve.

Post to Twitter Post to Yahoo Buzz Post to Delicious Post to Digg Post to Facebook Post to Reddit Reddit Post to StumbleUpon

Bad Behavior has blocked 330 access attempts in the last 7 days.