Signalling events from a class

For easy reference, here’s how to create an event in a class that listeners can react to:

class DeleteSubOrderEventArgs : EventArgs
{
    public int SubOrderId;
    public DeleteSubOrderEventArgs(int subOrderId)
    {
        SubOrderId = subOrderId;
    }
}

class Foobar
{
    public delegate void DeleteEventDelegate(object sender, DeleteSubOrderEventArgs e);
    public event DeleteEventDelegate DeleteSubOrderClick;
    
    protected void DeleteButton_Click(object sender, ImageClickEventArgs e)
    {
        // Signal to listeners
        if (DeleteSubOrderClick != null)
        {
            DeleteSubOrderClick(this, new DeleteSubOrderEventArgs(SubOrder.SubOrderId));
        }
    }
}

How to embed an Xslt-file in an assembly

Problem
How do I embed an Xslt file into an assembly so that I won’t have to deploy the file together with the assembly, set configuration options to refer to the file, etc?

Solution

  1. Create a resource (.resx) file in the project
  2. In the resource designer, click “Add Resource” and choose “Add Existing File…”. Select the Xslt file.
  3. Give the new resource a describing name, such as “FilterContentXslt”. The contents of the Xslt file will be available in a string property with this name in the Resource manager.
  4. Code that performs the transformation:
    // Parse the content into an XmlDocument
    XmlDocument doc = new XmlDocument();
    doc.LoadXml(xmlValue);
    
    // Retrieve the embedded resource containing the XSLT transform
    XmlDocument xsltDoc = new XmlDocument();
    xsltDoc.LoadXml(Resources.FilterContentXslt);
    
    XslCompiledTransform trans = new XslCompiledTransform();
    trans.Load(xsltDoc);
    
    // Perform the transformation
    StringWriter writer = new StringWriter();
    trans.Transform(doc, writer);
    string newXmlValue = writer.ToString();
    

Simple, and it works.

/Emil

Databinding with a GridView

Here’s how to call a codebehind function for the rows of a GridView. No rocket science, but useful for reference…

ASPX:
< %# GetStatusImage(Container) %>

Code behind:
protected string GetStatusImage(IDataItemContainer row)
{
}

or

ASPX:
< %# GetStatusImage(Container as GridViewRow) %>

Code behind:
protected string GetStatusImage(GridViewRow row{
}

/Emil

Databinding with a Repeater

This is simple stuff, but I wanted to store these code snippets somewhere for easy re-use…

This is how to do databinding with a Repeater control in ASP.NET.

In the ASPX file:

<asp :Repeater runat="server" ID="rptPuffar">
   <itemtemplate>
          <h1>< %# GetTitle(Container) %></h1>
          <p>< %# Eval("XYZ") %></p>
   </itemtemplate>
</asp>

In the code-behind file:

protected override void Page_Load(object sender, EventArgs e)
{
   if (!IsPostBack)
   {
      PageDataCollection puffar = GetChildren(this.PuffContainer);
      rptPuffar.DataSource = puffar;
      rptPuffar.DataBind();
   }
}



protected string GetTitle(RepeaterItem item)
{
   PageData page = (PageData)item.DataItem;
   return page.PageName;
}

In Page_Load(), we connect the repeater to a datasource (in this case a collection of pages from EPiServer).

GetTitle() is a function that is called by the ItemTemplate in the repeater for extracting the string to include in the page (in this case the name of the page). Eval() can also be used directly in the ASPX file to display the value of a property.

As I said, easy stuff, but now I don’t have to write the code again the next time I need it…

Forcing ASP.NET to generate valid XHTML code

Ever seen error like these when validating your ASP.NET web site using validator.w3.org?

there is no attribute "name".
<form name="aspnetForm" method="post" action="../shop/StartPage.aspx?id=122" i

document type does not allow element "input" here; missing one of "p", "h1",
"h2", "h3", "h4", "h5", "h6", "div", "pre", "address", "fieldset", "ins", "del" start-tag.
...dkZGQDrhr9OheQO96crtnJaz+8HiO6ew==" />

This will happen if you have the following doctype, indicating that the page content should be XHTML Strict:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

However, using that doctype is not enough for ASP.NET to generate valid XHTML Strict code. To make it do that, make sure that the following is set in the system.web section of Web.config (the default value is “Legacy”):

<xhtmlConformance mode="Strict"/>

Without that setting, ASP.NET will insert invalid attributes on the form tag and place the hidden input fields in invalid contexts. AFAIK, there’s no dialog where you can change this setting, you have to know it’s there. And now you do! 🙂

UPDATE:
The above solution only works in ASP.NET 2.0. Under 1.0 there is no known solution (at least not to me).

Retrieve the Html code for a Web User Control

Here’s how to extract the Html code for a web control:

public static string GetHtmlForControl(Control control)
{
    StringWriter textwriter = new StringWriter();
    HtmlTextWriter writer = new HtmlTextWriter(textwriter);
			
    control.DataBind();
    control.RenderControl(writer);
    string html = textwriter.GetStringBuilder().ToString();

    return html;
}

Tip: If you’re having problems with the generated Html being incomplete, then maybe you’re calling the function above in the wrong time? I’ve been having some problems with databound EPiServer controls until we discovered that we were doing this too early. When we started doing it in the PreRenderComplete event of the page, then it started working:

protected void Page_PreRenderComplete(object sender, EventArgs e)
{
    string html = FormHelper.GetHtmlForControl(Butikshuvud);
}

More useful regular expression examples

Here are some more Regex examples that may come in handy:

// Remove Html comments
//html = Regex.Replace(html, @"\<!--&#91;^>&#93;*-->", "");
html = Regex.Replace(html, @"\<!--.*?-->", ""); // new version!

// Validate an email address (with named groups)
Regex regex = new Regex(@"^(?<user>[^@]+)@(?<host>.+)\..+$", RegexOptions.None);
Match m = regex.Match(epost);
/* Check m.Success to decide if valid or not */

// Validate a Swedish zip code ("postnummer")
regex = new Regex(@"^(\d\d\d \d\d|\d\d\d\d\d)$", RegexOptions.None);
m = regex.Match(postnummer);

In the first example, note .*? sequence. The question mark makes the match lazy, as opposed to the default greedy matching strategy. This makes a difference when there’s more than one comment in the html string. In my first try above I used [^>] to avoid matching the end comment marker, with the unfortunate side effect of missing comments with tags as content.

I have also found a useful online Regex testing service here:

http://www.regexlib.com/RETester.aspx

(Update 2009-04-28: Changed service, the previous one is now unavailable…)