Jun 27, 2007

Turning an ascx user control into a redistributable custom control

This is possible using the new binary compilation feature of ASP.NET 2.0 and also the availability of the ClassName property on the user control.
The ClassName property allows to specify the Namespace that is needed when consuming the usercontrol from another application.

We can publish multiple controls within a single assembly but we have to insure that the Web project contains just UserControls only (ascx along with the associated code behind files).
But if you use the "use fixed naming and single page assemblies" option then a separate assembly for each user control will be generated. However the advantage of using this option is that if you were to make changes and deploy a newer version of the user control, then you need not modify the consuming application.

This is since the assembly NAME will remain the same on each compilation of the user control project and thus we do not need to update the reference to the user control assembly from within the consuming application.

There is one more option if you decide to use the "use fixed naming and single page assemblies".
After separate assemblies are created using the Publish Website option (or using the aspnet_compiler.exe tool) we can then merge these assemblies into a single assembly using the aspnet_merge.exe tool. Another option to combine multiple user controls into a single assembly is by using the Web deployment projects (WDP).

Read this excellent MSDN magazine article by Fritz Onion on Web Deployment projects (WDP) and for info about packaging user controls into assembly for multi application use:

So the steps for converting a user control into a redistributable custom control are:
1. Create the User control in a Website project in VS2005.
The main restriction is that the User Control needs to be self contained. That is, it cannot be dependent on app global things like App_Code or global.asax. If you do need to use the App_Code folder then you could use WDP or aspnet_merge.exe to combine mutiple assemblies into a single assembly.

When you create the User Control (say MyTestUC.ascx), VS creates it with the a @control directive that looks like this:
<%@ Control Language="C#" ClassName="MyTestUC" %>

This is fine, except for one thing: we want the class to live within a namespace of our choice (instead of 'ASP', which is what's used by default). To do this, we simply modify the ClassName attribute to include the namespace (this is a new feature in 2.0). e.g.

<%@ Control Language="C#" ClassName="Acme.MyTestUC" %>

2. Publish the website to compile the user control into a assembly.
Note you need to "uncheck" 'Allow this precompiled site to be updatable' option within "Publish Website", or you can use aspnet_compiler along with -u switch to create a binary deployment of the user controls.

3. Add reference to the generated assembly in step 2 from within the consuming web application.
First, add a Register directive to your page. It should look something like this:

<%@ Register TagPrefix="Acme" Namespace="Acme" Assembly="App_Web_mytestuc.ascx.cdcab7d2" %>
Note here that the assembly name is "App_web_mytestuc.ascx.cdcab7d2"
This assembly was generated using the "use fixed naming and single page assemblies"

the reference the user control within the page of the consuming application like this:
<Acme:MyTestUC id="MyUC" runat="server" />

If you had multiple user controls within that single assembly you could then reference the second control from that assembly likewise:
<Acme:MyTestUC2 id="MyUC2" runat="server" />

That is all that is there to it.

kick it on DotNetKicks.com

No comments: