Virtual Developer Workshop: Containerized Development with Docker
Yesterday, while working on some Web clients, I caught myself thinking if it were only a Windows Form application... The natural follow-up to that is whatever you happen to be doing would be easier to do in a Windows Forms application. However, because it was a Web application, I knew I had reached a small crossroad. The natural next step might be to use a Windows Forms control in a Web page. We called this embedding ActiveX controls pre-.NET, and it is something that technically can be done in ASP.NET.
In this article, you will learn the basics of embedding a Windows Forms control in ASP.NET, and then you will learn why you don't want to do it. By the time you have finished reading, I hope you will understand that the problem is really Microsoft's to solve. Microsoft has an obligation and it makes good sense to merge the two technologies—ASP.NET and Windows forms—and completely hide whether one is programming for a network or not. From a user's perspective, it shouldn't matter anyway.
Adding a Windows Forms Control to an ASP.NET Page
Suppose you have a Windows Forms control that is difficult or too expensive to reproduce for Web Forms. You can use the actual Windows Forms control in a Web Form (ASP.NET) application by adding the Windows Forms control to a Windows Control Library, copying the Windows Control Library to the Web Application's root folder, and adding an <OBJECT> tag to the ASP for the page in which you want to include the Windows Forms Control Library.
Building the Windows Control Library
A Windows Forms Control Library creates a .DLL project with references to the System.Windows.Forms assembly. This is an approximation to an ActiveX control library that you may be more familiar with from VB6.
Suppose, for argument's sake, you'd like to use the Windows Forms calendar control in a Web page. You can add a Windows Control Library to an existing project by selecting Add|New Project from the Solution Explorer context menu and picking the Windows Control Library applet from the Add New Project dialog (see Figure 1).
Figure 1: Add a Windows Control Library project to a Web Application.
For our purposes, it is sufficient to drag and drop a DateTimePicker control to the UserControl (defined as System.Windows.Forms.UserControl) added to the Windows Control Library project by the project template. I renamed the UserControl class DateTimeUserControl. (It doesn't matter what we call the UserControl namespace and class, but we do need to know this information later in the process.) When you are finished, your desktop might look something like Figure 2.
Figure 2: The Windows Forms UserControl with the DateTimePicker.
Embedding the Windows Control in a Web Page
The next step is to compile the Windows Control Library and copy the DLL assembly to the root folder of the Web Project (or Projects) that will embed this control. My ASP.NET project is named UseWinControl. As shown in Figure 3 (if you click Show All Files), the Windows Control Library will be positioned at a higher folder level than the bin folder.
Figure 3: Place the Windows Control Library in the ASP.NET application's root folder, as shown.
Adding a project reference to the Windows Control Library won't work because .NET will copy the output of the Windows Control Library to the bin folder, and we want it in the ASP.NET root folder.
The final step is to add an <OBJECT> tag to the Web Forms ASP. Add an <OBJECT> tag in each place and on each ASP.NET Web Form on which you want to use the control. The format of the <OBJECT> tag is shown in Listing 1.
Listing 1: The <OBJECT> tag for our Windows Control.
<OBJECT id=DateTimeUserControl1 height=50 width=200 classid=http:EmbedWinControl.dll#EmbedWinControl.DateTimeUserControl VIEWASTEXT> <PARAM NAME="SelectedDateTime" VALUE="<%=DateTime.Now %>"> </OBJECT>
In the listing, we provide an ID for the control and its size. We need to provide a class ID, which can be a URN or GUID. We used a URN (or URL) that includes the HTTP moniker and the relative path of the DLL followed by a pound sign (#) and the namespace and class of the control. VIEWASTEXT is used by the designer to figure out how to show the text. Next, we provide any parameter values using the PARAM tag and close the <OBJECT> tag with </OBJECT>. The parameter is a public property I added to the UserControl; it simply surfaces the DateTimePicker's Value property. (See surfacing constituent controls and properties in the VS.NET help for more information.) The result as coded is shown in Figure 4.
Figure 4: The DateTimePicker in a Web Form running in Internet Explorer.
There are real limitations to using Windows Forms controls in a Web application. The first is that the <OBJECT> tag does not support the runat="server" attribute. This means no code-behind, which is a compelling reason to use ASP.NET in the first place. Consequently, we must manufacture dynamic interaction with our embedded UserControl using script. In practice, this means that you can set the date in the control but will find it very difficult to know a client has changed the date or get what that date is.
Another real limitation is that, for a client to run this page, they must have the .NET Framework installed. There is no way to ensure that someone on the World Wide Web will or even can download and install the .NET Framework. This means this solution is limited to intranet applications where you can control the clients and ensure they have the .NET Framework. Collectively, the practical uses for embedded Windows Forms controls are very narrow and require a lot of work.
Introducing Smart Clients as a Better Alternative
When you find yourself desiring the flexibility of Windows Forms and the ease of deployment of a Web application, what you really want are smart clients. For all intents and purposes, a smart client is a Windows Form application that dynamically updates client assemblies using the Assembly class to download assemblies over HTTP. The result is a Windows Form application (that can talk to your server through Web Services, for example), and it can be deployed and updated over HTTP just like a Web application.
The ingredients you will likely need for a smart client application are XML Web Services to transport data to and from clients to server, an HTTP updater that automatically looks for assembly updates on your server and downloads them to clients, and at least a Windows Forms application kernel that downloads the assemblies initially and requests updates at some prescribed interval. Finally, clients will need to modify their security policy to support running downloaded assemblies, but the results are fantastic. Your customers will get a Windows Form application with all of the expressivity they will have come to expect but ease of deployment just like the Web provides.
Some things can be done but really represent a bastardization or severe programmatic distortions of good practices. You can create a Windows Control Library to use your favorite Windows Forms control in a Web application, but dynamic use of the Windows Forms control in a Web page will be difficult and require a lot of programmatic acrobatics. It really isn't the right approach.
If you find yourself needing Windows Forms controls, you probably need a Windows application. Build a smart client and download updates using HTTP and Web Services to go back and forth between client and server. Internet clients will still have to download and install the .NET Framework soon, however; this will be a moot point. The .NET Framework will be as ubiquitous as any other framework (like Borland's VCL or Sun's Java).
You will need several skills to write smart clients, but they are not as hard to do as you might think. An excellent example of a smart client is the sample program IssueVision, written by Susan Warren and distributed at events such as TechEd this year. If you couldn't make TechEd or need a copy of IssueVision, contact Susan Warren (formerly of Microsoft) at Vertigo Software (http://www.vertigosoftware.com).
Copyright © 2004 by Paul Kimmel. All Rights Reserved.
Paul Kimmel is the founder and chief architect for Software Conceptions, Inc. and a co-founder and President of the Greater Lansing Area .NET Users Group (glugnet.org). He has written several books on .NET and object-oriented programming and is available to build software for your company. You may contact him at firstname.lastname@example.org.