2012/03/11

Script registration labyrinth in ASP.NET WebForms


I'm always lost when trying to register a javascript fragment that must be executed on the client side after the postback. There are several usable methods in ASP.NET WebForms and I never know which one to choose.

Page.ClientScript
Page.ClientScript.RegisterStartupScript – registers the startup script. What does it mean “startup”? It is something that is executed when the browser finishes page loading, which is guaranteed by the fact that “startup” scripts are rendered just before closing <form> tag. Almost all elements on the page are processed by the browser at this point and can be referenced from that “startup” script.
Page.ClientScript.RegisterClientScriptBlock – registers the script block, so it is rendered somewhere near after the <form> element opening. This block is executed before the DOM is fully processed and before any “startup” scripts are executed. “ClientScript” blocks are good place for javascript functions.

Page
Page.RegisterStartupScript and Page.RegisterClientScriptBlock are marked as obsolete and they do nothing but Page.ClientScript call. Just ignore them.

ScriptManager
Now what about ScriptManager class? RegisterClientScriptBlock and RegisterStartupScript are there as well. What is the justification for such duplication? The only difference, according to the documentation (here and here), is that the scripts are “included every time that an asynchronous postback occurs”. This formulation is slightly confusing. Scripts registered by ScriptManager’s methods are rendered by non-asynchronous postback as well. ClientScript’s methods are never rendered by asynchronous-postbacks.

Script registration after asynchronous postback
The javascript block is not executed if it is a part of markup in AJAX response. Browser simply doesn’t process such block. Consider such silly ASPX:
<asp:Button runat="server" ID="Button1" Text="Do postback" OnClick="Button1_Click" />
<asp:Literal runat="server" ID="Literal1" />

and C# code behind with a script:
protected void Button1_Click(object sender, EventArgs e)
{
    Literal1.Text = "<script>alert('Button1 clicked')</script>";
}

Button1 causes postback (when clicked) and event handler fills Literal1 with the javascript block. This javascript block is execeuted and the alert message is shown when browser loads the (synchronous) postback response.

Let’s move to asynchronous postback:
<asp:UpdatePanel runat="server" ID="UpdatePanel1">
    <ContentTemplate>
        <asp:Button runat="server" ID="Button1" Text="Do AJAX call" OnClick="Button1_Click" />
        <asp:Literal runat="server" ID="Literal1" />
    </ContentTemplate>
    <Triggers>
        <asp:AsyncPostBackTrigger ControlID="Button1" />
    </Triggers>
</asp:UpdatePanel>

Code behind remains unchanged.

No message is shown after the Button1 is clicked. Body of the response should look something like this:
139|updatePanel|UpdatePanel1|
        <input type="submit" name="Button1" value="Do AJAX call" id="Button1" />
        <script>alert('Button1 clicked')</script>
|152|hiddenField|__VIEWSTATE|/wEPDwUKLTUxODY2NjI0NQ9kFgICAw9kFgICAw9kFgJmD2QWAgI
DDxYCHgRUZXh0BSk8c2NyaXB0PmFsZXJ0KCdCdXR0b24xIGNsaWNrZWQnKTwvc2NyaXB0PmRk88Fv/gu
MXM8Xq/lT5WC+dG66354=|48|hiddenField|__EVENTVALIDATION|/wEWAgL/oouVBgKM54rGBmox+
1LEg7FJSnLOTrjRf5eL73gK|7|asyncPostBackControlIDs||Button1|0|postBackControlIDs|
||13|updatePanelIDs||tUpdatePanel1|0|childUpdatePanelIDs|||12|panelsToRefreshIDs|
|UpdatePanel1|2|asyncPostBackTimeout||90|13|formAction||WebForm8.aspx|

Alert script is rendered into markup but it is not executed by the browser. How is it possible that script registration via ScriptManager works?

This code behind modification could discover the secret:
protected void Button1_Click(object sender, EventArgs e)
{
    ScriptManager.RegisterStartupScript(this, this.GetType(), "script", "<script>alert('Button1 clicked')</script>", false);
}

The alert message box is shown this time. Here is the response:
98|updatePanel|UpdatePanel1|
        <input id="Button1" name="Button1" type="submit" value="Do AJAX call" />
    |52|hiddenField|__VIEWSTATE|/wEPDwUKLTUxODY2NjI0NWRkwPvseEH2ojph8EJh0MFS5L+TksA
=|48|hiddenField|__EVENTVALIDATION|/wEWAgKaoIz3DwKM54rGBr7RMEQMtuoxxWPUsRRwWxmrCH
/Z|7|asyncPostBackControlIDs||Button1|0|postBackControlIDs|||13|updatePanelIDs||t
UpdatePanel1|0|childUpdatePanelIDs|||12|panelsToRefreshIDs||UpdatePanel1|2|asyncP
ostBackTimeout||90|13|formAction||WebForm8.aspx|45|scriptStartupBlock|
ScriptContentWithTags|{"text":"alert(\u0027Button1 clicked\u0027)"}|

There are two significant changes in the response: the script is not rendered (unsurprisingly) in the Literal control and there is something more in the response: scriptStartupBlock.  ASP.NET AJAX library ensures that script from this “section” is executed after receiving the response. ScriptManager.RegisterClientScriptBlock is very similar but it uses scriptBlock “section”.

It is quite easy to navigate through the labyrinth when it is clear how things work under the hood.

2012/01/08

I apologize for my ignorance, dear RadWindow

I use RadWindow and RadWindowManager for a while and yet I know hardly anything about them. This StackOverflow question about RadWindow in ajax scenario has initiated manifestation of my ignorance. For me it was always clear that RadWindow must be declared inside RadWindowManager and there can be only one RadWindowManager instance on a page. Perverse consequences of this combination are obvious when you use WebForms – ASPX and ASCX entanglement through RadWindow instances. ASPX must contain RadWindowManager and RadWindow that is used on the ASCX as well. What a festival of ignorance!

First of all, what is RadWindowManager useful for? I managed to find 3 reasons from the documentation:
  1. It is a convenient way how to declare property values shared among several RadWindow instances.
  2. It adds radopen, radalert, radconfirm and radprompt functions to the global window obect.
  3. Window managment API (tile, cascade, etc...).
Documentation also says that it is possible to instantiate RadWindow without manager participation. And both ways are viable: either declaratively in markup or imperatively from code behind:

var window1 = new RadWindow();
window1.NavigateUrl = "http://www.google.com";
window1.VisibleOnPageLoad = true;
window1.ID = "RadWindow1";
window1.Width = 500;
window1.Title = "Google";
window1.Height = 300;
Panel1.Controls.Add(window1);


The last line is the most important one from my perspective. Window instance is added into normal asp Panel and no manager is involved.  The window is displayed even after partial postback when the panel is ajaxified. It is due to fact that RadWindow is control like any others and it is rendered in the same way as any other controls are. The same fact is valid in the case when the window is placed within RadWindowManager. RadWindow is rendered at the same place as the RadWindowManager. In ajax scenario you have to enclose the RadWindowManager into panel that is also updated in given partial postback. It sounds weird in connection with the fact that there can be only one RadWindowManager.

Fortunately this fact is not a fact but delusion. A page could easily contain more than one manager instance. In such case radopen and similar functions always use the first manager instance.

What about performance? Other managers like RadStyleSheetManager and RadScriptManager improve Telerik-based application performance. It seems to be not true for RadWindowManager according to this site.

What is the moral of this sad story? It is not worth to be afraid to work directly with RadWindow instances. As an application does not use tons of windows it would be better to use RadWindowManager only as support for radopen & Co. functions.

2011/05/22

Delegates serialization: Limits

When I heard about delegates’ serializability for the first time, my reaction was romantic. I dreamt about some mystical process that serializes delegate’s IL and about other magical things. It is, of course, absolute nonsense, but I love those fairy tales :).

All delegates in C# are inherited directly or indirectly from Delegate. Delegate class is class like any other. It is just marked as serializable – no black magic is needed.

What is buried there?

Basically, there are two properties: Method (MethodInfo) and Target (object). It is all what is needed to invoke any .NET method. When delegate points to a static method, then the Target property is null. There are some other internal details that I don’t understand but I hope they are irrelevant.

These facts reveal weaknesses of delegates’ serialization:
  1. Target property is serialized as well when using binary formatter. It could lead some serious issues when object referenced by Target is part of complex object graph. On the other side if Target is not serialized then the delegate cannot be deserialized at all – there wouldn’t be any suitable instance to make a method call.
  2. Versioning issues.
  3. State of static class is not serialized. Delegate of method that is using static fields (directly or indirectly) is deserialized into completely different context.
In addition to these disadvantages, there is a limitation associated with anonymous delegate that is closed over a variable. It is simply not serializable.

It is clear that “persistable continuation” implemented in C# by delegate serialization as it was suggested by Mike Hadlow would be very limited, which is a pity.

2011/05/15

NHibernate: Serializing Delegates

Mike Hadlow discovered very interesting delegate feature for me. They are serializable! In outher words they can be stored in a database, e.g. with NHibernate.

Entity that represents a persistable entity could look like this:
public class PersistableDelegate
{
    public virtual Delegate Delegate { get; set; }
    public virtual string Name { get; set; }
    public virtual int Id { get; set; }

    private byte[] SerializedDelegate {
        get {
            if (Delegate == null)
                return null;

            var formatter = new BinaryFormatter();
            using (var stream = new MemoryStream()) {
                formatter.Serialize(stream, this.Delegate);
                return stream.ToArray();
        }

        set {
            if (value != null) {
                var formatter = new BinaryFormatter();
                using (var stream = new MemoryStream(value))
                    Delegate = (Delegate)formatter.Deserialize(stream);
            }
            else
                Delegate = null;
        }
    }
}

Your model can manipulate with Delegate property. SerializedDelegate property provides access to serialized data of the delegate for NHibernate – it is implementation detail and is marked as private. Getter of this property returns the delegate serialized to an array and the setter reconstructs the delegate from provided data.

FNH mapping is simple as breath then:
public class PersistableDelegateMap : ClassMap<PersistableDelegate> {
    public PersistableDelegateMap() {
        Id(x => x.Id);
        Map(x => x.Name);
        Map(Reveal.Member<PersistableDelegate>("SerializedDelegate"))
            .Length(int.MaxValue);
    }
}
Reveal class makes it possible to map private property.

Corresponding database table for MS SQL is:
CREATE TABLE [dbo].[PersistenceAction](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [Name] [nvarchar](255) NULL,
    [SerializedDelegate] [image] NULL,
)

Now it is possible to store a delegate in database:
var action = new PersistableDelegate();
action.Delegate = (Action)(() => { Console.WriteLine("Hello from persisted delegate!"); });
action.Name = "First test";

session.Save(action);
session.Flush();

and load back:
var action = session.Query<PersistableDelegate>().Where(x => x.Name == "First test").FirstOrDefault();
action.Delegate.DynamicInvoke();

I am not sure yet how can be this useful. There are definitely many limitations, e.g. lambda expression closed over local variable is not serializable. In any case such feature is very promising...

2011/04/18

Integration tests, NHibernate and Sqlite, part 3 – enhanced in memory database

Integration tests, NHibernate and Sqlite, part 1
Integration tests, NHibernate and Sqlite, part 2 – in file database
Integration tests, NHibernate and Sqlite, part 3 – enhanced in memory database

In previous post I introduced a database scope that builds the database schema only once per test suit run. Some performance was sacrificed to achieve this: the database had to be stored in a file. Database stored in memory is obviously faster than database stored in a file. Is there a way how to move the database back to memory?

Yes, we can build a master database in-memory and then make copy of this master database for each test. The problem is how to duplicate the master database. Sqlite provides Online Backup API, which is not available in System.Data.SQLite wrapper yet.

Sqlite Backup API
Fortunately it is quite easy to wrap the required API:
[DllImport("System.Data.SQLite.DLL", CallingConvention = CallingConvention.Cdecl)]
internal static extern IntPtr sqlite3_backup_init(IntPtr destDb, byte[] destname, IntPtr srcDB, byte[] srcname);

[DllImport("System.Data.SQLite.DLL", CallingConvention = CallingConvention.Cdecl)]
internal static extern int sqlite3_backup_step(IntPtr backup, int pages);

[DllImport("System.Data.SQLite.DLL", CallingConvention = CallingConvention.Cdecl)]
internal static extern int sqlite3_backup_finish(IntPtr backup);

public static void Backup(SQLiteConnection source, SQLiteConnection destination)
{
    IntPtr sourceHandle = GetConnectionHandle(source);
    IntPtr destinationHandle = GetConnectionHandle(destination);

    IntPtr backupHandle = sqlite3_backup_init(destinationHandle, SQLiteConvert.ToUTF8("main"), sourceHandle, SQLiteConvert.ToUTF8("main"));
    sqlite3_backup_step(backupHandle, -1);
    sqlite3_backup_finish(backupHandle);
}

There is only one catch. Handles needed by Sqlite API are stored as private fields in System.Data.SQLite wrapper. But it can be retrieved by this little trick:
private static IntPtr GetConnectionHandle(SQLiteConnection source)
{
    object sqlLite3 = GetPrivateFieldValue(source, "_sql");
    object connectionHandle = GetPrivateFieldValue(sqlLite3, "_sql");
    IntPtr handle = (IntPtr)GetPrivateFieldValue(connectionHandle, "handle");

    return handle;
}

private static object GetPrivateFieldValue(object instance, string fieldName)
{
    var filedType = instance.GetType().GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance);

    object result = filedType.GetValue(instance);
    return result;
}

Yes, it is a hacky solution but it works well and it can be viewed as temporary replacement for the missing wrapper part.

SqliteInMemoryPrivateScope
Modification of SqliteInFilePrivateScope is easy with such helper method.

The master database is duplicated by the new wrapper method:
public SqliteInMemoryPrivateScope()
{
    EnsureMasterDatabaseExistence();

    this.privateConnection = new SQLiteConnection(connectionString);
    this.privateConnection.Open();

    SqliteBackup.Backup(masterConnection, this.privateConnection);
}

And a connection to the master database must be held by the scope instance. It is similar to SqliteInMemorySharedScope:
private static SQLiteConnection masterConnection;

private void EnsureMasterDatabaseExistence()
{
        // to support asynchronous scenario
        lock (configurationSync) {
            if (configuration == null) {
                configuration = BuildConfiguration ();
                sessionFactory = configuration.BuildSessionFactory();

                masterConnection = new SQLiteConnection(connectionString);
                masterConnection.Open();

                SchemaExport schemaExport = new SchemaExport(configuration);
                schemaExport.Execute(false, true, false, masterConnection, TextWriter.Null);
            }
        }
}

Now we have a database scope that builds configuration, session factory and database schema only once per test suit run which saves a lot of time. In addition the database is stored in memory so integration tests run blazingly fast. The isolation between tests is very good and the test can be executed in parallel. What to want more?:).

Full implementation of SqliteInMemoryPrivateScope can be found here.
Complete source code can be downloaded here.

2011/04/11

Integration tests, NHibernate and Sqlite, part 2 – in file database

Integration tests, NHibernate and Sqlite, part 1
Integration tests, NHibernate and Sqlite, part 2 – in file database
Integration tests, NHibernate and Sqlite, part 3 – enhanced in memory database

SqliteInMemorySharedScope issues
The disadvantage is that the time needed byc SqliteInMemorySharedSope instantiation grows with the size of the tested domain model. When the domain model is complex enough then execution of test suit may take unacceptable amount of time.

Storing the database in a file
Sqlite is able to store the database in a file as well. We create a database with its schema at first and store it in a file, let’s call it master file. Then it is easy to create a copy of the master file. Individual tests touch only own copy of the master file. So isolation is preserved and dependency between the time of database scope instantiation and complexity of the domain is significantly more moderate.

SqliteInFileDatabaseScope
The new session is connected to the private copy of the master file.
public ISession OpenSession()
{
    ISession session = SqliteInFilePrivateScope.sessionFactory.OpenSession(this.privateConnection);

    return session;
}

The private connection is created in the default constructor.
public SqliteInFilePrivateScope()
{
    EnsureMasterDatabaseExistence();

    // to avoid name collisions in parallel scenario
    this.privateDatabaseFileName = Guid.NewGuid().ToString() + ".db";

    File.Copy(masterDatabaseFileName, this.privateDatabaseFileName);

    string connectionString = BuildConnectionString(this.privateDatabaseFileName);
    this.privateConnection = new SQLiteConnection(connectionString);
    this.privateConnection.Open();
}

The master file, configuration and session factory are created only once per test suit run.
private static object configurationSync = new object();

private void EnsureMasterDatabaseExistence()
{
    // to support parallel execution of unit tests
    lock (configurationSync) {
        if (configuration == null) {
            string connectionString = BuildConnectionString(masterDatabaseFileName);
            configuration = BuildConfiguration(connectionString);
            sessionFactory = configuration.BuildSessionFactory();

            SchemaExport schemaExport = new SchemaExport(configuration);
            schemaExport.Execute(false, true, false); 
        }
    }
}

Connection string factoring:
private static string BuildConnectionString(string databaseName)
{
    return string.Format("Data Source={0};Version=3;New=True;", databaseName);
}

And BuildConfiguration is delegate that is injected on test suit initialization (for more details see this post):
public static Func<string, NHibernate.Cfg.Configuration> BuildConfiguration;

The full example is here.
The same example but using Microsoft Sql Server Compact Edition instead of Sqlite is here.
Complete source code can be downloaded here.

Why to support parallel scenarios in Visual Studio 2010
Tests are executed sequentially by default in Visual Studio and there is no setting to turn on parallel execution in VS2010 GUI. To achieve this, the file with test settings must be tweaked. The name of the file is Local.testsetings by default:
<TestSettings name="Local" id="caf44e0f-3ee4-46bf-a6ed-73aea6d93533" xmlns="http://microsoft.com/schemas/VisualStudio/TeamTest/2010">
  <Description>These are default test settings for a local test run.</Description>
  <Deployment enabled="false" />
  <Execution parallelTestCount="2">
    <TestTypeSpecific />
    <AgentRule name="Execution Agents">
    </AgentRule>
  </Execution>
</TestSettings>

Attribute parallelTestCount specifies how many tests are executed at one time. Parallel execution makes sense in these days of multicore processors because it can reduce the execution time of whole test suit. And it counts when doing continuous integration. You can find much more information in this blog post.

2011/04/04

Unit tests initialization in Visual Studio 2010

NHDatabaseScopes problem
I am going to dig into a nasty detail of SqliteInMemorySharedScope class in this post. The FNH configuration is built by the constructor of this class. NH configuration needs to know which assembly to load the mapping metadata from. If the knowledge is included right in the constructor then the SqliteInMemorySharedScope (like in previous post) is coupled with tested domain model and cannot be reused in other project. It would be neat to inject the metadata or just the configuration into it. The configuration and session factory is shared between all unit tests and there is usually no particular execution order defined for tests. The question is: how to inject all information needed by SqliteInMemorySharedScope?

Unit test initialization
VS2010 offers a way how run a code before any test is executed. Just decorate a static method in test class with AssemblyInitialize attribute:
[TestClass]
public class TestEnvironmentInitialization
{
   [AssemblyInitialize]
   public static void Initialize(TestContext context)
   {
      // any initialization code

Some code can be executed after all tests were finished as well – attribute AssemblyCleanup.
The execution order is:
1)    Static method marked by AssemblyInitialize attribute.
2)    Default constructor of a test class.
3)    Method marked by TestInitialize attribute.
4)    Method marked by TestMethod attribute.
5)    Method marked by TestCleanup attribute.
6)    Static method marked by AssemblyCleanup attribute.

SqliteInMemorySharedScope decoupling from domain model
Back to the SqliteInMemorySharedScope class. A delegate that builds NH configuration is injected instead of configuration itself. The advantage, but questionable, is lazy initialization. Configuration is built only when it is really needed.
SqliteInMemorySharedScope initialization:
[TestClass]
public class TestEnvironmentInitialization
{
    private static NHibernate.Cfg.Configuration BuildSqliteConfiguration(string connectionString)
    {
    var config = Fluently.Configure()
        .Database(SQLiteConfiguration.Standard.ConnectionString(connectionString))
        .Mappings(m => {
            m.FluentMappings.AddFromAssembly(typeof(Order).Assembly);
        })
        .BuildConfiguration();

    return config;
}

[AssemblyInitialize]
public static void Initialize(TestContext context)
{
    BuildConfiguration = BuildSqliteConfiguration;

And simple modification of SqliteInMemorySharedScope:
public class SqliteInMemorySharedScope
{
    public static Func<string, NHibernate.Cfg.Configuration> BuildConfiguration;

   public SqliteInMemorySharedScope()
   {
      if (configuration == null) {
         configuration = BuildConfiguration(connectionString);
      }
SqliteInMemorySharedScope is decoupled from the domain model now and can be reused in multiple projects.

Source code can be downloaded here.