Working with Nested Repeaters in ASP.NET

ASP.NET, Programming No Comments »

Sometimes I miss the option that you have in classic ASP, PHP or Ruby on Rails to just put a nested loop into the html page (view, presentation layer) to display nested data. Of course this is, strictly speaking, against ASP.NET best practices where you’re supposed to use web controls for everything. Then again one could make the argument that the loop actually belongs in the view. This would be .aspx page, and not in the controller or the model (code behind file in ASP.NET).

The task at hand is to iterate through parent categories and child items. The technique suggested by Microsoft is outlined here, and this article uses a nested repeater with a self-join. Starting point is the following DataSet with two related tables and a repeater in the page:

DataSet myDS = new DataSet("NestedRepeaterDemo"); … //fill the dataset myDS.Tables[0].TableName = "ParentCategories"; myDS.Tables[1].TableName = "ChildItems"; DataRelation relation = new DataRelation("myRelation", myDS.Tables["ParentCategories"].Columns["CatID"], myDS.Tables["ChildItems"].Columns["CatID"], true); relation.Nested = true; myDS.Relations.Add(relation); parentRepeater.DataSource = myDS; parentRepeater.DataBind();

So why not bind the child repeater in the page, just for the heck of it:

<table> <asp:Repeater id="parentRepeater" runat="server"> <itemtemplate> <tr class="categoryInTable"> <td colspan="2"> <%# DataBinder.Eval(Container.DataItem, "CategoryName") %> </td> </tr> <asp:Repeater ID="childRepeater" runat="server" datasource=’<%# ((DataRowView)Container.DataItem).Row.GetChildRows("myRelation") %>‘ > <ItemTemplate> <tr><td> <%# Eval("ItemName")%> </td> <td> <%# Eval("ItemDescription")%> </td> </tr> </ItemTemplate> </asp:Repeater> </itemtemplate> </asp:Repeater> </table>

 

Sure enough with this code you will run into a DataBinding: ‘System.Data.DataRow’ does not contain a property with the name x error. 

As a quick explanation for this error the following might suffice:

When the nested repeater binds to its datasource calling the GetChildRows command of the parent DataRowView.Row object the latter returns an array of DataRows (the “child rows”, an object of type DataRow[]) which each repeater Item will be bound to now. However, Eval with the above syntax will only bind to named fields of a DataView object that exposes a name property for each field. The DataRow returned by GetChildRows is merely a row in a table without the name properties so that each field can be accessed only with an indexer (DataRow["ItemName"]).

This is why you can either change the binding expressions above like so:

 

<td> <%# Eval("[\"ItemName\"]")%> </td> <td> <%# Eval("[\"ItemDescription\"]")%> </td>

or you can change the datasource to use the CreateChildView of the DataRowView directly like this:

<asp:Repeater ID=”childRepeater” runat=”server” datasource=’<%# ((DataRowView)Container.DataItem).CreateChildView(”myRelation”) %>’ >

and use old data binding syntax <%# Eval (”ItemName”) %> because now you have a DataView again (just like in the parentRepeater) which supports binding to the data field by name. Of course you have the option to do all the databinding in the code-behind file (usually the ItemDataBound event of each repeater) which gives you better debugging support than the approach above.

I find this “nested data” stuff overly complicated in ASP.NET, especially compared with how easy it is with Ruby on Rails. The plethora of objects which each behave differently is difficult to work with and the Repeater itself is limited in its built-in functionality and designer-support.

Sure enough I also ran into the

Compiler Error Message: CS0246: The type or namespace
name ‘DataRowView’ could not be found (are you missing a
using directive or an assembly reference?)

which IMHO is clearly a bug in ASP.NET as a reference to System.Data exists in the code-behind file that the .aspx web form inherits from. This issue can be fixed by either having an <%@ Import Namespace=”System.Data” %> tag in your aspx file or declaring DataRowView with the full namespace System.Data.DataRowView in the page each time.

For an in-depth view of the binding issues see this article. You might also find this post helpful.

[Slashdot] [Digg] [Reddit] [del.icio.us] [Facebook] [Technorati] [Google] [StumbleUpon]

Ubuntu in an Active Directory Windows Domain

Ruby on Rails, Ubuntu/Linux No Comments »

Ok, the title’s a bit contrived. It’s for the keywords, mainly.

Anyway, to have an Ubuntu machine in your network environment has a number of benefits:

  • Learning Linux and trying out Linux software which for the most part is high-quality (and free).
  • Have a staging server for your Ruby on Rails applications.
  • Having an SSH access point into your network for (limited) remote administration, much easier to set up (less secure though) than VPN.

You can either have a full installation of Ubuntu on one of your network machines or you can use virtualization. I’m using the latter as it can leverage the more performant server hardware.ne

As you can now get a free license key for VMWare server, you can take the following steps to host Ubuntu in your network:

  • Download and install VMWare server.
  • Download an Ubuntu .iso image, desktop, server, whatever, any version can be easily extended later.
  • Create a Virtual Machine in VMWare server using this .iso image. Be sure to use enough RAM (256 MB is minimum to run Ubuntu) and disk space (minimum 5 GB to have some space left after installation, the days of Linux fitting on a few hundred MB are definitely over). I initially could not get a bridged network connection working and had to use the NAT option in VMWare to get Ubuntu connect to the host server and the Internet. After installing the desktop I can now use the bridged network option without problems. Network and Internet connection are vital for Ubuntu so get those straightened out before you proceed.
    If you downloaded the server version you might want to install a desktop with the command:
    sudo apt-get install ubuntu-desktop
    This makes many things easier down the road.
  • Join your Ubuntu machine to the domain. Follow the instructions here and here in PARALLEL as one will make the other easier to understand. You should then be able to see the the Ubuntu machine on your Windows Active Directory Domain and ping it.

You will soon experience first-hand that Windows comes in a shiny package but (quite a few) things DON’T WORK as expected, so often it’s off to the Knowledge Base again. In Linux (most) things JUST WORK. And because much of the work is done on the command line you get much better and friendlier error messages that the Windows Message Boxes all over the screen.

You can now connect to your Ubuntu installation with a VNC client (Ubuntu has an VNC server built in via the Remote Desktop app) and also get an SSH (Secure Shell) windows client such as the excellent PuTTY which gives you shell access to your Ubuntu box. You can also set VMWare server to start the Ubuntu VM automatically when your Windows host OS starts via VM>Settings>Options>Startup/Shutdown and setting Run this virtual machine as: to anything but “User that powers on this virtual machine”.

image

In my next post I will outline how to get Ruby on Rails running on the Ubuntu box and using Capistrano to deploy from a Windows workstation.

[Slashdot] [Digg] [Reddit] [del.icio.us] [Facebook] [Technorati] [Google] [StumbleUpon]

Vista Cursors on XP and Windows Server 2003

Uncategorized No Comments »

Vista-style cursors can be downloaded here (white pointer) and here (black pointer). Unzip anywhere on your hard drive, right-click the .inf files and select “Install…”. Then select the cursor at Start Button>Control Panel>Mouse>Pointers. One more reason NOT to upgrade to Vista. Still looking for a “red expanding circle at mouse-click location like in the Camtasia videos” which is (probably?!, I have no Mac) available for OS X but not for Windows. 

[Slashdot] [Digg] [Reddit] [del.icio.us] [Facebook] [Technorati] [Google] [StumbleUpon]

Pretty Wordpress Permalinks on IIS Shared Hosting

Blogging Software 1 Comment »

We all want pretty and search-engine friendly URLs for our blog posts. The most common format is /%year%/%monthnum%/%day%/%postname%/ as it gives users and search engines optimal information about the topic and the month of the post (er, you might want to check out the URL of this post for an example).

As it turns out, having Wordpress generate such URLs is possible on IIS in a shared hosting environment without much effort and there is no need to move to an Apache host with mod_rewrite etc.

The “official” procedure recommended by Wordpress is here. It entails editing your Windows Server’s php.ini file. However, most shared-hosting companies (I currently use Crystaltech) will not do this for the entire server just so that your blog can have pretty URLs.

There’s a much easier way:

  1. Create a text file in the root of your blog and name it php.ini. Paste the following two lines:
    cgi.fix_pathinfo = 1
    cgi.force_redirect = 0
  2. Then simply change the permalink structure in your Wordpress control panel to:
    /index.php/%year%/%monthnum%/%day%/%postname%/

To get rid of the leading “/index.php/” -which will make it easier to move to another blog engine such as Typo later-;) follow these additional steps:

  1. Download the Wordpress - Remove Index.php from Permalinks in IIS Plugin (scroll down), and install it into wordpress (upload to /wp-content/plugins/ folder, then Activate from Wordpress control panel).
  2. Change the default 404 error page of your IIS site. Most web hosting companies will offer a web form to accomplish this. At Crystaltech it looks like so:image
     Set the 404 error URL to “/index.php” or the root URL of you blog such as “/blog/index.php”. Then change the permalink structure to /%year%/%monthnum%/%day%/%postname%/.
    Hope it helps.
[Slashdot] [Digg] [Reddit] [del.icio.us] [Facebook] [Technorati] [Google] [StumbleUpon]

Validating Windows Forms Text Input

Programming No Comments »

Unlike ASP.NET (which I’m more familiar with), Windows Forms don’t have any “Validation Controls”, so validating input has to be wired into the event model of your app. After some experimenting I found this procedure to work best for validating text box input:

1. Drop an ErrorProvider component onto your form. This component appears to have designer support when you drag it, however, it is not a control but a container-level component (like ImageList and ToolTip among others). The ErrorProvider component will display an error icon (ErrorProvider icon) next to the control that you specify programmatically during validation.

2. Handle the TextChanged Event
For TextBox validation, the preferred event is TextChanged as it lets you validate the contents of the control after they have been entered. Here’s an example:

 The field of view can’t be greater than a full circle (360 degrees):
image

 

 

 

 

 

If the user enters a letter, the error icon is displayed:

 

image

 

 

 

 

 

 

If the user enters a number too large, an error icon with a different message is displayed:

image

 

 

 

 

 

Here’s the event handler for the TextChanged event:

private void textBox1_TextChanged(object sender, EventArgs e) { if (!System.Text.RegularExpressions.Regex.IsMatch(textBox1.Text, @"^\d{1,3}$")) { errorProvider1.SetError(textBox1, "Please enter only up to three digits."); } else { if (float.Parse(textBox1.Text) > 360) { errorProvider1.SetError(textBox1, "FOV cannot be larger than 360°"); } else { errorProvider1.SetError(textBox1, ""); } } }

Regular expressions come to the fore here. The beginning of line (^) and end of line ($) characters in the pattern “^\d{1,3}$” are very important as otherwise the IsMatch function will return true as long as there is at least one decimal digit in the TextBox.Text.

Regular expression are cryptic which makes memorizing them hard. This article which accompanies the Expresso utility is great to refresh your memory. Hope it helps.

[Slashdot] [Digg] [Reddit] [del.icio.us] [Facebook] [Technorati] [Google] [StumbleUpon]
WP Theme & Icons by N.Design Studio
Entries RSS Comments RSS Log in