Friday, 4 June 2010

ASP.NET: Handing an empty Repeater control

The ASP.NET Repeater control is very useful and gives you lots of control over your output when compared to other controls such as the GridView. However, that comes at a cost of having to wire up all of your own events, sorting and paging etc.

Additionally, another drawback is that for a reason I can't explain, there is no EmptyDataTemplate or EmptyDataText property in a repeater which you can use when there are no items to display. Rumour abounded that ASP.NET 2.0 would include such a template, but it was not included.

Several people have tried different methods of handling this situation, but I found one which I think works nicely. I have a user control with a repeater in it, and on the Page_PreRender event I check that the Repeater's DataSource has rows in it. If not, then a label is made visible that tells the user no rows are present. If it does have data, then the Repeater is displayed.

Code

Label:


<asp:Label ID="LabelNoProducts" runat="server" Text="You haven't added any products yet" visible="false" ></asp:Label>

Event: (User Control PreRender)

Private Sub Page_PreRender(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.PreRender
Dim ds As DataTable = RepeaterProductsList.DataSource

If ds.Rows.Count = 0 Then
RepeaterProductsList.Visible = False
LabelNoProducts.Visible = True
Else
RepeaterProductsList.Visible = True
LabelNoProducts.Visible = False
End If
End Sub

Et voila. Each time your user control is loaded, it checks if there are rows in the repeater, and lets the user know if not.

ASP.NET: Read Contents of Text File

In my Web Application Project, I wanted to read some CSS styles in from a file to dynamically style a system generated email.

It was pretty easy, but I thought I should record my code for future:


Dim emailCss As String = vbNullString

Dim fileName As String = HttpContext.Current.Server.MapPath("~/utilities/Email.css")

If File.Exists(fileName) Then
Dim ioFile As New StreamReader(fileName)

emailCss = ioFile.ReadToEnd()

ioFile.Close()

End If

Thursday, 3 June 2010

ASP.NET: Render Control into HTML String

Occasionally there is a need to get string representation of ASP.NET control in other words - render it into string instead of let it be rendered on the page. For example, you may want to grab the HTML rendering of an ASP.NET server control and attach it to an email.

The following method renders control into HTML string.

Namespaces used:


using System.Text;
using System.IO;
using System.Web.UI;

Below is RenderControl method implementation, which receives any control and returns its HTML string representation.

C#

public string RenderControl(Control ctrl)
{
StringBuilder sb = new StringBuilder();
StringWriter tw = new StringWriter(sb);
HtmlTextWriter hw = new HtmlTextWriter(tw);

ctrl.RenderControl(hw);
return sb.ToString();
}

VB.NET

Public Function RenderControl(ByVal ctrl As Control) As String
Dim sb As New StringBuilder()
Dim sw As New StringWriter(sb)
Dim htw As New HtmlTextWriter(sw)

ctrl.RenderControl(htw)

Return sb.ToString()

End Function

There are a few drawbacks to this approach, in that any LinkButtons or other controls which depend on being inside an HTML form will fail unless you include the form in the email body too.

See these two (rather old) posts on 4GuysFromRolla.com by Scott Mitchell:

Part 1
http://www.4guysfromrolla.com/articles/091102-1.aspx

Part 2:
http://www.4guysfromrolla.com/articles/102203-1.aspx

Friday, 30 April 2010

VB.NET: Use a Ternary Operator to check variable before assignment

It's a nice thing to be able to quickly check a value before assigning it to a variable, perhaps in a situation where you want to avoid a NullReferenceException.

If you want to do this, you can use a Ternary Operator which allows you to do the whole thing on one line:

Dim s As String
s = If(Session("mySessionVar") Is Nothing, String.Empty, Session("mySessionVar").ToString)


For more detail, refer to this blog post.

Monday, 12 April 2010

ASP.NET: Reset Selected Value of AJAX Combo Box

I have been banging my head off my desk for hours and hours, trying to find a way to reset the value of an ASP.NET Control Toolkit Combo Box.

Fundamentally it's a brilliant control and lends some superb ease of use to an application when applied properly, but for some reason it's lacking a straightforward and functional way to reset its value to a default of something like:

<asp:ListItem Value="0"> -- Select -- </asp:ListItem>


I tried various combination of these, plus messing about with the AppendDataBoundItems property and the ViewState setting:


ComboBoxSelector.SelectedIndex = -1
ComboBoxSelector.SelectedIndex = 0
ComboBoxSelector.SelectedIndex.ClearSelection()
ComboBoxSelector.SelectedIndex.Dispose()
ComboBoxSelector.Items.Clear()

Those are not important, the thing to note is that using any of the above will not actually reset the value of the Combo Box.

To reset it, you have to loop through the hidden controls that are created at runtime, and reset those to the default value:


Dim ctl As Control
For Each ctl In ComboBoxAllKeywordCategories.Controls
If TypeOf ctl Is HiddenField Then
CType(ctl, HiddenField).Value = "0"
End If
Next

This works, and resets the Combo back to the default value you want. I no longer feel the need to put my fist through my monitor, so, result.

Friday, 9 April 2010

ASP.NET: How to Group Data in the GridView Control

One of my clients was not happy with a GridView control that repeated a category name next to every product inside that category. He asked if we could group the table to display the category name only once rather than displaying it for every product, e.g. something like:


'Crap', I thought. 'This doesn't come easily to the GridView control.'

But after some research into several different methods, I found a good one that worked well for me. It was created by a developer called 'dotNetSoldier', and the control is called the ZNet Extended GridView.

You just download the DLL file and drop it into your bin folder, add the control to your Toolbox and drag it onto your page. Then follow the instructions on his blog to get started.

I'd rather not have had to add another reference in my project or use a third party control, but I couldn't get the traditional GridView to behave in this way.

Monday, 22 March 2010

SQL Server: Deleting duplicates using a Common Table Expression (CTE)

In a recent project I had to figure out how to delete a series of duplicates from a tablet to prevent a report becoming bloated with them.

There's more than one way to skin a cat, but I think I have found a pretty efficient way of deleting dupes. Of course it would be preferable to avoid creating the duplicate rows in the first place, but sometimes you just have to delete them after they have been created.

A recent development in the SQL Server world is that of Common Table Expressions (CTEs). These can be used to help you delete duplicates using a single command, rather than using a temporary table or too many joins.

The CTE is formed by selecting the table into a temporary result set which you can then instantly relate back to the original table to find which rows to delete. You could use syntax similar to the following:

WITH Duplicates_CTE
(FirstName, LastName, Email, Phone, id)
AS (
SELECT FirstName, LastName, Email, Phone, MIN(PersonId) id
FROM tblPerson GROUP BY FirstName, LastName, Email, Phone
)
DELETE FROM tblPerson WHERE PersonId NOT IN (
SELECT id FROM Duplicates_CTE
)


The first select statement gets a distinct result set (without duplicate rows) from the problem table by using the MIN function and a GROUP BY clause. Then you can join back to the original table from the CTE result set and delete every row that does not correlate to the CTE - which means that you're left without any duplicate rows.

Et voila, simples! No duplicates and it's all done in one command.

Tuesday, 16 March 2010

ASP.NET Code Behind Intellisense Not Working

This has been infuriating.

So many times when developing web applications using Visual Studio 2008 Enterprise Edition or Visual Studio Web Developer Express 2008, the intellisense in the code behind would stop working, and when the project is deployed any reference to page controls would result in a null reference exception.

There are quite a few things to try:

  • Close Visual Studio (Or VSWDE) and delete the intellisense files which are normally stored in your Windows profile.
  • Open the IDE again and rebuild the project.
  • Check that your aspx page is properly wired up to your code behind in the page directive.
  • Delete the project dll file in the bin folder and rebuild your project.
  • This is the one that worked for me: Check that there is a designer file associated with that page. If there is not, then in Visual Studio, right click on the project in Solution Explorer and click Convert to Web Application. That should regenerate the designer file for you.

If your intellisense isn't working and your code behind just can't seem to reference the controls, there are a lot of things that could be wrong. But if you try all of those, then hopefully you'll be back coding again instead of angrily trying to figure out what's wrong.

Friday, 5 March 2010

Styling GridView Controls with CSS

Doing a lot of ASP.NET development usually means that GridView controls will be a regular feature in your applications, unless you prefer to go for the manual approach or use a repeater.

One of the biggest pains I've had in the past with GridViews is styling them consistently. But it wasn't enough of a pain to motivate me to spend the time styling them with CSS, until I started an entirely new application which would feature dozens of them.

So I located this tutorial which was absolutely perfect - just what I was looking for. It has a screen shot of the end result, good instructions and easily duplicated code and CSS that will get you on your way to having a consistent look and feel for all your GridView controls throughout your application.

Tuesday, 2 March 2010

CSS min-height and IE6

I've been working on a new application which has to be fully compatible with IE6 and IE8. Being quite a fan of using min-height to avoid nasty squished pages, I noticed that the min-height CSS property is rendered properly in IE8, but NOT in IE6 (shock).

A nice, easy workaround I found is this:

content {
min-height: 630px;
height: auto !important;
height: 630px;
}


This works in IE6, without messing up the formatting in IE8 and other browsers.