Automatically updating Custom DotNetNuke Modules using Selenium IDE for Firefox

May 31, 2012

If you develop DNN modules and need to support several installations in sync, any automated help is welcome.

I tried to use Selenium to automate Firefox to upload module packages into a DNN installation. (I did not find any references as to whether DNN has a built-in update mechanism for custom modules). Download Selenium IDE and press Record.

The result is a Selenium Test Case that performs the following operations

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head profile="http://selenium-ide.openqa.org/profiles/test-case">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="selenium.base" href="http://localhost/" />
<title>dnn2ml update BGT.Flash</title>
</head>
<body>
<table cellpadding="1" cellspacing="1" border="1">
<thead>
<tr><td rowspan="1" colspan="3">dnn2ml update BGT.Flash</td></tr>
</thead><tbody>
<tr>
	<td>open</td>
	<td>http://localhost/dnn/GettingStarted/tabid/83/ctl/Login/Default.aspx?returnurl=%2fdnn%2fMain.aspx</td>
	<td></td>
</tr>

Retrieve the login URL by right-clicking the Login button and copying the URL. The tabid usually changes between installations.

<tr>
	<td>type</td>
	<td>id=dnn_ctr_Login_Login_DNN_txtUsername</td>
	<td>host</td>
</tr>
<tr>
	<td>type</td>
	<td>id=dnn_ctr_Login_Login_DNN_txtPassword</td>
	<td>PASSWORD</td>
</tr>

Edit Host (Superuser) username and password

<tr>
	<td>clickAndWait</td>
	<td>id=dnn_ctr_Login_Login_DNN_cmdLogin</td>
	<td></td>
</tr>
<tr>
	<td>clickAndWait</td>
	<td>//div[@id='dnn_cp_RibbonBar_adminMenus']/ul/li[2]/div/ul/li/ul/li[10]/a/span</td>
	<td></td>
</tr>

I  added these two steps to change to Edit mode (I have no idea how the View/Edit mode is set right after login). This will cause a timeout if DNN is already in Edit mode.

<tr>
	<td>select</td>
	<td>id=dnn_cp_RibbonBar_ddlMode</td>
	<td>label=Edit</td>
</tr>
<tr>
	<td>clickAndWait</td>
	<td>css=option[value="EDIT"]</td>
	<td></td>
</tr>

Invoke Install Extension Wizard

<tr>
	<td>click</td>
	<td>link=Install Extension Wizard</td>
	<td></td>
</tr>
<tr>
	<td>type</td>
	<td>id=dnn_ctr_Install_wizInstall_cmdBrowse</td>
	<td>C:\path\to\MyModule\packages\MyModule_00.00.01_Source.zip</td>
</tr>

Select package file to be uploaded

<tr>
	<td>clickAndWait</td>
	<td>id=dnn_ctr_Install_wizInstall_StartNavigationTemplateContainerID_nextButtonStart</td>
	<td></td>
</tr>
<tr>
	<td>clickAndWait</td>
	<td>id=dnn_ctr_Install_wizInstall_chkRepairInstall</td>
	<td></td>
</tr>

This is for updating modules, so we need to check the Repair flag

<tr>
	<td>clickAndWait</td>
	<td>id=dnn_ctr_Install_wizInstall_StepNavigationTemplateContainerID_nextButtonStep</td>
	<td></td>
</tr>
<tr>
	<td>clickAndWait</td>
	<td>id=dnn_ctr_Install_wizInstall_StepNavigationTemplateContainerID_nextButtonStep</td>
	<td></td>
</tr>
<tr>
	<td>clickAndWait</td>
	<td>id=dnn_ctr_Install_wizInstall_StepNavigationTemplateContainerID_nextButtonStep</td>
	<td></td>
</tr>
<tr>
	<td>click</td>
	<td>id=dnn_ctr_Install_wizInstall_chkAcceptLicense</td>
	<td></td>
</tr>
<tr>
	<td>clickAndWait</td>
	<td>id=dnn_ctr_Install_wizInstall_StepNavigationTemplateContainerID_nextButtonStep</td>
	<td></td>
</tr>
<tr>
	<td>clickAndWait</td>
	<td>//body[@id='Body']/div[4]/div/a[2]</td>
	<td></td>
</tr>
<tr>
	<td>clickAndWait</td>
	<td>id=dnn_LOGIN1_loginLink</td>
	<td></td>
</tr>
<tr>
	<td></td>
	<td></td>
	<td></td>
</tr>
</tbody></table>
</body>
</html>

Logout after upload.

Note that this simple script expects the browser to be logged out in DNN.

The sample may be made more stable by using conditions such as provided by Selenium IDE Flow Control.


Unicode Versions supported in SQL Server (2000-2012)

May 30, 2012

Update to a previous post on Unicode support in SQL Server.

Which version of the Unicode Standard is supported by MS SQL Server?

SQL Server Version Unicode Version
2000 3.0
2005 3.2
2008 5.0
2008 R2 5.0
2012 5.0*

* The documentation on SQL Server 2012 does not explicitly refer to a Unicode version number. Even if there was no change, SQL Server 2012 introduced native support for supplementary characters.


DNN 6.0 “The Child Site Name You Specified Already Exists”

May 24, 2012

Just tried to test the DotNetNuke 6.0.4 “export/import templates” functionality in preparation of the deployment process.

To export your site, go to Host/Site Management, hover over Manage, and select the Export Site Template menu. Select the site, enter template file name and description, check “Include Content”, and hit Export Template. (source)

This will create the files mytemplatefilename.export.data.template (XML file) and mytemplatefilename.export.data.template.resources (zip file) in the DNN directory Portals/_default.

To import, click the Add New Site menu on the Manage button. Select the saved template from the dropdown box. (source)

Attention: If you happen to enter a trailing slash in the Site Alias field, DNN displays the following error message:

The Child Site Name You Specified Already Exists. Please Choose A Different Child Site Name.

Which is funny, because you cannot enter a site name. Nowhere. Ever. It’s always Site Alias, Title, but never Name.

Fortunately, I found this bug report stating exactly the problem I had. I had already checked file system permissions etc., but did not find anything obvious. Removing the trailing slash allowed me to create the cloned site.


400.000 Views

May 22, 2012

Thank you everybody.

37.220.5.194, please leave your spam below.


Dealing with “Circular group reference” errors in xsd.exe

May 22, 2012

I continued to research the problem of XSLT files that cannot be processed by xsd.exe. In case of xslt.xsd (contained in the Visual Studio 2010 installation under the XML directory), xsd generates the error message

>xsd "C:\Program Files\Microsoft Visual Studio 10.0\Xml\Schemas\xslt.xsd" 
      /classes

Error: Error generating classes for schema ‘C:\Program Files\Microsoft Visual Studio 10.0\Xml\Schemas\xslt.xsd’.
- Group ‘char-instructions’ from targetNamespace=’http://www.w3.org/1999/XSL/Transform&#8217; has invalid definition: Circular group reference.

Here is how I proceeded:

Create copy1.xsd

To work around this error, I created a copy of the original xslt.xsd (named here copy1), and located the offending XSD definitions.

Replace circular references by reference to new (dummy) element

The two definitions that cause the circular reference error are the groups “char-instructions” and “instructions”. To find out where these definitions are used in the generated C# classes, the groups’ references are replaced by a reference to a new element:

  <xs:group name="char-instructions">
    <xs:choice>
<!--    
      <xs:element name="apply-templates" type="apply-templates" />
      <xs:element name="call-template" type="call-template" />
      <xs:element name="apply-imports" type="apply-imports" />
      <xs:element name="for-each" type="for-each" /> 
      <xs:element name="value-of" type="value-of" />
      <xs:element name="copy-of" type="copy-of" />
      <xs:element name="number" type="number" />
      <xs:element name="choose" type="choose" />
      <xs:element name="if" type="if" />
      <xs:element name="text" type="text" />
      <xs:element name="copy" type="copy" />
      <xs:element name="variable" type="variable" />
      <xs:element name="message" type="message" />
      <xs:element name="fallback" type="fallback" />
      -->
      <xs:any namespace="##other" processContents="lax" />
      <xs:element name="ci-dummy" type="ci-dummy" />
    </xs:choice>
  </xs:group>
  <xs:group name="instructions">
    <xs:choice>
      <xs:group ref="char-instructions" />
<!--    
      <xs:element name="processing-instruction" type="processing-instruction" />
      <xs:element name="comment" type="comment" />
      <xs:element name="element" type="element" />
-->
      <xs:element name="i-dummy" type="i-dummy" />
      <xs:element name="attribute" type="attribute" />
    </xs:choice>
  </xs:group>

Of course, the new dummy types also need to be declared in copy1.xsd:

  <xs:complexType name="ci-dummy" mixed="true">
    <xs:attribute name="dummy" type="xs:string" />
  </xs:complexType>
  <xs:complexType name="i-dummy" mixed="true">
    <xs:attribute name="dummy" type="xs:string" />
  </xs:complexType>

Running xsd.exe on copy1.xsd will now run successfully and generate copy1.cs.

Replace references to dummy classes by original classes

Search the generated classes for references to the dummy classes. You can start by commenting out the declaration of the dummy class and follow the compiler errors. In the example of xslt.xsd, replace

[System.Xml.Serialization.XmlElementAttribute("ci-dummy", typeof(cidummy))]

by

[System.Xml.Serialization.XmlElementAttribute("attribute-set", typeof(attributeset))]
[System.Xml.Serialization.XmlElementAttribute("decimal-format", typeof(decimalformat))]
[System.Xml.Serialization.XmlElementAttribute("include", typeof(include))]
[System.Xml.Serialization.XmlElementAttribute("key", typeof(key))]
[System.Xml.Serialization.XmlElementAttribute("namespace-alias", typeof(namespacealias))]
[System.Xml.Serialization.XmlElementAttribute("output", typeof(output))]
[System.Xml.Serialization.XmlElementAttribute("param", typeof(param))]
[System.Xml.Serialization.XmlElementAttribute("preserve-space", typeof(preservespace))]
[System.Xml.Serialization.XmlElementAttribute("strip-space", typeof(stripspace))]
[System.Xml.Serialization.XmlElementAttribute("template", typeof(template))]
[System.Xml.Serialization.XmlElementAttribute("variable", typeof(variable))]

However, the types that were previously referenced by other elements are not part of the generated code, as no reference to the elements exist anymore.

Add elements for previously referenced types

Create a second copy of the xsd file by copying copy1.xsd to copy2.xsd. Add the xs:element definitions that have been commented out in the first copy

    <xs:element name="apply-templates" type="apply-templates" />
    <xs:element name="apply-imports" type="apply-imports" />
    <xs:element name="call-template" type="call-template" />
    <xs:element name="for-each" type="for-each" />
    <xs:element name="value-of" type="value-of" />
    <xs:element name="copy-of" type="copy-of" />
    <xs:element name="number" type="number" />
    <xs:element name="choose" type="choose" />
    <xs:element name="if" type="if" />
    <xs:element name="text" type="text" />
    <xs:element name="copy" type="copy" />
    <xs:element name="variable" type="variable" />
    <xs:element name="message" type="message" />
    <xs:element name="fallback" type="fallback" />
    <xs:element name="processing-instruction" type="processing-instruction" />
    <xs:element name="comment" type="comment" />
    <xs:element name="element" type="element" />

Run xsd on copy2.xsd generating copy2.cs. copy2.cs need not be part of the C# project.

Copy C# classes

Next, copy all C# classes missing in copy1.cs from copy2.cs until copy1.cs compiles successfully.

Clean up attributes

Your C# classes can now be compiled and will successfully load an XML file conforming to the original XSD.

In case of the xslt.xsd, I noticed that elements and texts are handled by two different arrays, namely

// many more XmlElementAttribute declarations
[System.Xml.Serialization.XmlElementAttribute("some-element-name", typeof(someelementname))]
public object[] Items {
  get { return this.itemsField; }
  set { this.itemsField = value; }
}
[System.Xml.Serialization.XmlTextAttribute()]
public string[] Text {
  get { return this.textField; }
  set { this.textField = value; }
}

This will cause your code to lose the original order of elements and texts in the XML file. To combine both types of data into one array, add the XmlTextAttribute to the Items property as well:

[System.Xml.Serialization.XmlTextAttribute(typeof(string))]
public object[] Items

and completely remove the declaration of the string[] Text property.


Supplementary Characters in C#

May 20, 2012

Inspired by my posting about supplementary characters in SQL Server 2012, I checked the capabilities of .Net to support supplementary characters:

string s143743 = "𣅿";
Console.WriteLine(s143743.Length.ToString());
Console.WriteLine(new StringInfo(s143743).LengthInTextElements.ToString());
string s131518 = "𠆾𠇀𠇃";
Console.WriteLine(s131518.Length.ToString());
Console.WriteLine(new StringInfo(s131518).LengthInTextElements.ToString());

The results are

“𣅿” 
Length: 2
LengthInTextElements: 1
“𠆾𠇀𠇃”
Length: 6 
LengthInTextElements: 3

As you can see, the string.Length property returns the number of 16-bit words (= .Net char structure) the string contains. To handle supplementary characters correctly in .Net, you need to use the StringInfo class.


Official XSD definition for XSLT?

May 19, 2012

I tried to look for an official XSD definition for XSLT files for some XSLT experiments.

What I did find was an xslt.xsd file on w3.org, and an xsd in the Xml directory of my Visual Studio installation (“C:\Program Files\Microsoft Visual Studio 10.0\Xml\Schemas\xslt.xsd”). Unfortunately, both versions could not be processed using the xsd.exe tool from VS resulting in different error messages.

Then I found an xslt10.dtd file on w3.org, and converted it to XSD using Trang:

java -jar trang.jar -I dtd -O xsd xslt10.dtd  xslt10.xsd

The resulting .xsd file can be converted to a C# file by xsd.exe

xsd xslt10.xsd /classes /n:Xslt

However I am not sure if the DTD, the XSD and thus the C# definitions are really really standards-compliant, or if the .xsd requires some editing to produce correct code.

Please leave a comment if you have any information on this topic.


Supplementary Characters in SQL Server

May 13, 2012

I originally intended to write an update to my post Collation Support in SQL Server Versions to include coverage of SQL Server 2012 collations. I was surprised to find that the number of supported collation names (reduced by the various suffixes such as _CI, _CS, etc.) did not change from SQL Server 2008.

What did change though was that there is a new collation suffix named “_SC” which stands for Supplementary Character support.

Once you declare a database with an _SC collation, the various string functions in SQL Server are not only Unicode-aware, but also Supplementary Character-aware (NCHAR, UNICODE, LEN).

Compare these statements in SQL Server 2012

CREATE DATABASE test_sc COLLATE  Latin1_General_100_CI_AI_SC; 
-- 2012 collation

DECLARE @d nvarchar(10)  = N'𣅿' ;
SELECT NCHAR(0xD84C) + NCHAR(0xDD7F); 
       -- Old style method using surrogate characters
SELECT NCHAR(143743), 
       UNICODE(@d), NCHAR(UNICODE(@d)), LEN(@d), DATALENGTH(@d)

SET @d = N'𠆾𠇀𠇃';
SELECT @d, UNICODE(@d), NCHAR(UNICODE(@d)), LEN(@d), DATALENGTH(@d)

resulting in

𣅿

𣅿       143743    𣅿    1    4

𠆾𠇀𠇃    131518    𠆾    3    12

with the results on a non-SC database in SQL Server 2012 or earlier

𣅿

NULL     55372    �    2    4

𠆾𠇀𠇃    55360    �    6    12

Example data taken from MSDN NCHAR() and SolidQ.

(Note that Management Studio 2008 does not display the characters in the query window, but does correctly show them in the results window)

You find that the functions NCHAR, UNICODE, and LEN support characters for code-points outside the Unicode BMP, whereas non-SC collations handle supplementary characters using the surrogate characters. For a list of changes in semantics, see MSDN.


Chrome, Firefox reset Flash plugin if display: property changes (Update)

May 11, 2012

To resolve the mystery of Flash plugins restarting when their display property changes (directly or inherited), I created a couple of plain and simple HTML files to test a set of operations to toggle visibity in IE 9 (9.0.8112.16421), Chrome 18 (18.0.1025.168 m), and Firefox 12 (12.0).

The Flash player has version 11.1.102.55, and the Flash object is initialized by swfobject.js.

Each of the 3 browsers were tested on 2 different pages with 3 different toggle operations:

  • Page 1 contained the Flash object inside an iframe inside a div.

DOM hierarchy:
<div><iframe><html etc><div class=”flashContent”>

  • Page 2 contains the Flash object inside a div.

DOM hierarchy:
<div><div class=”flashContent”>

The toggle operations were

  • assign a .hidden class setting visibility to hidden
.hidden { visibility: hidden; width: 0px; height: 0px; }
  • assign a .displaynone class setting display to none
.displaynone { display: none; }
  • using jquery .show() and .hide()

.show() actually does not clear the display: property, but sets it to ‘block’, ‘inline’ etc, which might interfere with other operations, such as addClass(“displaynone”), etc.

Results for Page 1 (using iframe):

IE 9 Chrome 18 Firefox 12
toggling top-level div
hidden ok ok ok
display:none ok ok restart
show/hide ok ok restart
toggling iframe
hidden ok ok ok
display:none ok ok restart
show/hide ok ok restart

Results for Page 2 (directly embedded Flash):

IE 9 Chrome 18 Firefox 12
toggling top-level div
hidden ok ok ok
display:none ok restart restart
show/hide ok restart restart
toggling flash object
hidden ok ok ok
display:none ok restart restart
show/hide ok restart restart

The only method to set a Flash object hidden and visible again while keeping the object running turns out to be setting a CSS class with visibility:hidden.

So I put the code (swf inside iframe) that worked in plain HTML files and added it into a DotNetNuke installation. It almost worked.

A new issue occurred: IE9 was not able to display a Flash object once the visibility:hidden style was removed! F12 did not help me to make the object visible again. Strangely though, using JavaScript to re-assign some other iframe to the same src URL caused the Flash to display again!

$("#someotheriframe").attr("src", 
    $("#someotheriframe").attr("src"));

A DNN page simply contains too much generated code (ASP.Net, MS Ajax, DNN framework, jQuery, various controls and .js files) so that I did not think it was worth debugging the issue further. My JavaScript functions to toggle visibility now contain a browser detection based on $.browser to decide which alternative to choose.


Encoding issues with ABCpdf8

May 11, 2012

I ran across a problem using ABCpdf8 for PDF generation: bullets and the Euro sign are displayed as garbled characters.

What’s going on here?

character name character unicode displayed as UTF-8
bullet U+2022 • 0xE2 0×80 0xA2
Euro sign U+20AC € 0xE2 0×82 0xAC

Since .Net is Unicode-based, the problem cannot be caused by .Net sting handling.

My conclusion is that the Doc.AddImageHtml method creates a temporary file in UTF-8 encoding, and the HTML rendering engine (Gecko in this case) needs to be told about the correct encoding:

doc.AddImageHtml(
  @"<!DOCTYPE html PUBLIC ""-//W3C//DTD XHTML 1.0 Transitional//EN"" ""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"">
  <html xmlns=""http://www.w3.org/1999/xhtml"">
    <head>
      <meta http-equiv=""content-type"" content=""text/xhtml; charset=utf-8"" />
  ... and more HTML content ....
");

In preparing this blog, my assumption was confirmed in the Notes section

ABCpdf saves this HTML into a temporary file and renders the file using a ‘file://’ protocol specifier. So this is a convenience function – it doesn’t offer any performance enhancements.


Follow

Get every new post delivered to your Inbox.