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…)

Open an EPiServer page

Here are a few ways to retrieve data for a given page (expressed in a PageReference instance) in EPiServer:

PageReference pageref = ...;
PageData pagedata;

// In a page (which is a sub-class of PageBase, e.g. TemplatePage, EditPage, SimplePage)
pagedata = this.Getpage(pageref);

// In a user control (which is a sub-class of UserControlBase)
pagedata = this.Getpage(pageref);

// Anywhere
pagedata = Global.EPDataFactory.GetPage(pageref);

Global.EPDataFactory also has some other useful functions:

// Open a page from a given FriendlyUrl rather than a PageReference
// (which requires knowing the Page ID)
pagedata = Global.EPDataFactory.GetPageByURL("/Bokningsbara-kurser/");

BTW, it’s also possible to initialize a PageReference with a Url (although NOT a Friendly Url):

pageref = PageReference.ParseUrl("http://localhost:8889/shop/Puff.aspx?id=130");

UPDATE (2007-06-04):

If you have a so called “simple address” such as “/foo”, then none of the above will work. In that case you have to use code such as this:

PropertyCriteriaCollection critcol = new PropertyCriteriaCollection();

PropertyCriteria crit = new PropertyCriteria();
crit.Condition = EPiServer.Filters.CompareCondition.Equal;
crit.Name = "PageExternalURL";
crit.Type = PropertyDataType.String;
crit.Value = simple_address.Trim(new char[] { '/' }); // Remove initial "/"
critcol.Add(crit);

PageDataCollection pagecol = Global.EPDataFactory.FindPagesWithCriteria(Global.EPConfig.RootPage, critcol);
if (pagecol.Count > 0)
{
   return pagecol[0].LinkURL;
}

Get URL from an EPiServer PageReference

Retrieving the URL to an EPiServer page seems like a basic thing to do, but it’s not quite obvious…

Referring to a page is normally represented by an instance of the PageReference class, so obviously that contains a public property called Url or something, right?

Wrong!

Instead, this is how to do it (as a bonus I also show how to retrieve the PageReference from a page property):

string url = "";
PropertyData pd = CurrentPage.Property["Shop_CartPage"];
if (pd != null && pd.IsNull == false)
{
	PageReference pageref = (PageReference)pd.Value;
	url = GetPage(pageref).LinkURL;
}

If anyone knows better or more efficient ways to do this, please add a comment to this post 🙂

Pages without page types in EPiServer

When creating “normal” ASPX pages (i.e. pages that are not EPiServer page types) to use in EPiServer sites it can be very useful to have them inherit from TemplatePage or SimplePage (both are EPiServer types) so that dynamic properties can be read, page methods called, etc. Unfortunately this will give rise to an error message similar to this:

The current template "/shop/Varukorg.aspx" does not match the specified page type file "/default.aspx"

This is because TemplatePage and SimplePage assumes that they are part of an EPiServer page type. This problem can be fixed by overriding ValidatePageTemplate() with an empty implementation:

public override void ValidatePageTemplate()
{
}

Voilá! No more error message.

BTW, try finding this information in the EPiServer docs. Not so easy…

User Controls in EPiServer

This is my first post about EPiServer, which basically is a framework for building web sites. It’s very capable and extensible and is in wide use in Scandinavia. For more information, look here: http://www.episerver.com.

Web User Controls in EPiServer solutions should always inherit from EPiServer.UserControlBase rather than the usual System.Web.UI.UserControl. This gives access to useful functions and properties such as

  • PageData GetPage(PageReference pageLink)
  • PageData CurrentPage
  • string Translate(string key)

Note that those functions work even if the current page is not a “proper” page type in EPiServer so it’s missing from the page hierarchy. Very useful!

Refresh Visual Studio Add-in settings

Here are some steps to try if you’re having problems with addins in Visual Studio (for example if toolbars or menus have vanished, or have been duplicated).

First, close all Visual Studio instances.

Then open a command line console with Visual Studio settings (e.g. “Visual Studio 2005 Command Prompt” from the start menu) and type:

devenv /resetaddin *

That line will clear the settings for all addins and cause them to refresh menus and toolbars the next time Visual Studio is started. To do that with an individual add-in, which requires knowing its class name, including namespace, type

devenv /resetaddin CodeAssist.Connect

If the above does not help, then try this (NOTE: This will delete all customization done to Visual Studio, such as keyboard mappings, etc!):

devenv /resetsettings
devenv /resetaddin *

When starting Visual Studio, you should now face a fresh and clean environment.