Compile a Web User Control (.ascx) w/HTML and Code Behind into a Single Assembly


This is a demo I did during my SharePoint 2007 presentation at the Ottawa Federal User’s Group June 17th.  If you are looking for the slide deck you will find it here.

There are a few things you’re going to need to get started:

Once you have all that configured (be patient)…

Open Visual Studio 2008 and select File | New | Project…

Select Visual C# | Web | ASP.NET Web Application

Make sure you select the .NET 3.0 Framework as your target unless you have configured your SharePoint Server for .NET 3.5.

image

Enter a name for the Project “WebControls” and the Solution “WebPartDemo”, select the option to create a directory for the solution and click Ok.

After your Web Application Project has been created right click the Project and select Properties | Signing

Select the “Sign the assembly” checkbox and create a new strong name key with the same name as the Project and with no password.

Close the Project properties and add a new Web User Control Named “WebUserControlSample” to the root of your project.

image

Double click on the .ascx file to open it for edit and add the following:

<%@ Control Language="C#" AutoEventWireup="true" 
CodeBehind="WebUserControlSample.ascx.cs" 
Inherits="WebControls.WebUserControlSample" 
ClassName="WebControls.Markup.WebUserControlSample"%>
<asp:Button ID="butDoWork" runat="server" Text="Say Hello" onclick="butDoWork_Click" />
<asp:TextBox ID="txtName" runat="server"></asp:TextBox><br />
<asp:Label ID="lblDisplay" runat="server" Font-Italic="true" Font-Size="Large" Text=""></asp:Label>   

The important portion of the code above is the ClassName entry, this is the namespace that will be used to reference your html markup.  The code hehind for your Web User Control (.ascx.cs) can be something like this:

using System;

namespace WebControls
{
    public partial class WebUserControlSample : System.Web.UI.UserControl
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }

        protected void butDoWork_Click(object sender, EventArgs e)
        {
            lblDisplay.Text = "Hello there " + txtName.Text;
            txtName.Text = string.Empty;
        }
    }
}

You can delete the default.aspx page from your web site as we do not need that for this example.

Now what you want to do is right click the Project in the Solution Explorer and select Unload Project, now right click the Project again and select Edit WebControls.csproj

Immediately after the following lines:

<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
  <Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v9.0\WebApplications\Microsoft.WebApplication.targets" />
  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
       Other similar extension points exist, see Microsoft.Common.targets.
  <Target Name="BeforeBuild">
  </Target>
  <Target Name="AfterBuild">
  </Target>
  -->

You want to paste the following build commands.

Pay close attention to the following highlighted entries as they may differ depending on your Windows installation and the version of the SDK you have installed:

image

Save the file and then Right Click the Project and select “Reload Project”

Right click the Project and select Build and you should see the following output:

—— Build started: Project: WebControls, Configuration: Debug Any CPU ——
C:\Windows\Microsoft.NET\Framework\v3.5\Csc.exe /noconfig /nowarn:1701,1702 /errorreport:prompt /warn:4 /define:DEBUG;TRACE /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Configuration.dll /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Data.dll /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.dll /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Drawing.dll /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.EnterpriseServices.dll /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Web.dll /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Web.Mobile.dll /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Web.Services.dll /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Xml.dll /debug+ /debug:full /keyfile:WebControls.snk /optimize- /out:obj\Debug\WebControls.dll /target:library Properties\AssemblyInfo.cs WebUserControlSample.ascx.cs WebUserControlSample.ascx.designer.cs

Compile complete — 0 errors, 0 warnings
WebControls -> C:\Users\Wes\TFS\ws08srv03.like10.local\LIKE10\dev\Source\FederalSharePointUsersGroup\source\WebControls\bin\WebControls.dll
C:\Windows\Microsoft.NET\Framework\v2.0.50727\aspnet_compiler.exe -v / -p C:\Users\Wes\TFS\ws08srv03.like10.local\LIKE10\dev\Source\FederalSharePointUsersGroup\source\WebControls\ -f -d -fixednames C:\Users\Wes\TFS\ws08srv03.like10.local\LIKE10\dev\Source\FederalSharePointUsersGroup\Precompiled
Running aspnet_merge.exe.
C:\Program Files\Microsoft SDKs\Windows\v6.1\Bin\aspnet_merge.exe C:\Users\Wes\TFS\ws08srv03.like10.local\LIKE10\dev\Source\FederalSharePointUsersGroup\Precompiled -o WebControls.Markup -a  -debug -copyattrs
Successfully merged ‘C:\Users\Wes\TFS\ws08srv03.like10.local\LIKE10\dev\Source\FederalSharePointUsersGroup\Precompiled’.
"C:\Program Files (x86)\Microsoft\ILMerge\ILMerge.exe" "C:\Users\Wes\TFS\ws08srv03.like10.local\LIKE10\dev\Source\FederalSharePointUsersGroup\Precompiled\Bin\WebControls.Markup.dll"  "C:\Users\Wes\TFS\ws08srv03.like10.local\LIKE10\dev\Source\FederalSharePointUsersGroup\Precompiled\Bin\WebControls.dll" /keyfile:"C:\Users\Wes\TFS\ws08srv03.like10.local\LIKE10\dev\Source\FederalSharePointUsersGroup\source\WebControls\WebControls.snk" /target:library /out:"C:\Users\Wes\TFS\ws08srv03.like10.local\LIKE10\dev\Source\FederalSharePointUsersGroup\Precompiled\Final\WebControls.dll"
========== Build: 1 succeeded or up-to-date, 0 failed, 0 skipped ==========

If all has gone well then you should see the namespace WebControls.Markup in your assembly using Reflector for .NET:

image

You’ll also notice that your version number for the assembly is 0.0.0.0 which is not great, you can fix this by manually creating an App_Code folder in the WebControl project and moving your AssemblyInfo.cs file from the Properties folder into it (Make sure the build action on the file is set to compile) and you will have a version number stamped into your assembly on your next compile:

image

Now if I add another Web Application to my solution, add a reference to my WebControls Project and edit the Default.aspx page to add a PlaceHolder control then go to the code behind and add the following code on the Page_Load:

namespace WebControlTest
{
    public partial class _Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            Control myControl = Page.LoadControl(typeof (WebControls.Markup.WebUserControlSample), null);
            plhWebPart.Controls.Add(myControl);
        }
    }
}

It will load my .ascx right out of the assembly!

image

My next post will be to deploy this as a SharePoint Feature…stay tuned.

I have posted the sample application outlined above here if you just want to jump right in.

 

About wesmacdonald

Wes MacDonald is a Visual Studio ALM MVP, PSD, MCT and a Principal Consultant for LIKE 10 INC., a SharePoint Server, Visual Studio and Team Foundation Server Consulting Firm providing premium support and guidance services.

No comments yet... Be the first to leave a reply!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: