Dennis Burton's Develop Using .NET

Change is optional. Survival is not required.
Tags: fundamentals | tdd | VS tricks

In the previous post, I walk through creating a web site project where C# and Visual Basic code live happily in the same project file. The call to action from that post is to ask "What this could be used for?" If you recall from that post, some of the distinguishing features of VB9 over C#3 are XML Literals and expanded support for LINQ query expressions, but where would I use these features? I can't think of a good reason to use these features in the code-behind of a web site project (user interface layer); places where I would use LINQ expressions, for instance, would be in a business logic layer.

The Process
When creating business logic functionality, under TDD we would first create a test to ensure that this functionality does what it is supposed to. Using a web site project under this process, things start to fall apart. A website project does not create an explicit assembly that you can reference inside of a unit test library project. I created a test assembly in the same solution as the MultiLanguage project. When I tried to add a reference, the project was not available either. Because we can't reference the web project assembly, we can't test it, which means there is no test coverage of the components inside App_Code. This is a deal breaker for me; I sure hope that I have missed something along the way.

The Feature Request
What I really want is a class library project that acts like the website project when it comes to adding files in multiple languages. I want to be able to add a partial class implementation in the primary language of my choice. I also want to be able to add a partial class implementation that will allow me to implement methods on that class in a secondary language if that language is better suited for a particular task. The compiler that works with the website project is clearly able to handle this scenario. How about letting Visual Studio do this for me in class libraries?

Looking Forward
As of right now, the benefits of using both VB and C# do not seem to be worth the cost of the extra steps required to build a testable assembly. C# and VB are not that far apart; there are relatively few differences that make one more effective than the other, and that effectiveness is marginal. That said, there is a lot of language work going on top of the CLR. There are significantly different approaches to problems that are enabled by using a functional languages like F#. There is a totally different set of solutions in the dynamic language world enabled by the DLR in languages like IronRuby and IronPython. I want to be enabled to use the best fit language for a given problem and package up that solution in a way that makes sense. I don't want to have to create a new class library and package that into the deployment process every time I want to use a feature from a different language.

If you are only building web solutions and test coverage is not important to you, than the technique described would meet that need. There is still a hole for non-web solutions. There are still plenty of apps written in WinForms, Console apps, or even just a single library. It would be handy if Visual Studio would provide for the use of this technique in environments other than web site projects.

 

Using C# and VB in the same project file! That is bound to get under the skin of the C# zealots. I prefer to code in C#, but these days it feels much more like I am coding to the framework, other libraries, or CodeRush (if you are addicted like myself). There are times when VB provides some real advantages over C#. Like XML Literals and specific cases of query expressions (like Take and Distinct).

The goal of the sample site
This post will demonstrate how to leverage multiple languages within a website project. The website will contain pages written with both C# and VB as the code behind languages. These pages will contain user controls that have been written in both languages as well as reference classes that have been coded in both languages. All of the pages,user controls, and classes will be contained in a single project file.

Make a website project
From the file menu select New Website... then select ASP.NET Web Site
In the sample I have named the site MultiLanguage. There are several differences between a web site project and a web forms project. An advantage of web site projects that we will take advantage of is the language selection on the web site creation dialog. What I find interesting is that the only effect of this option is to select the code-behind for the default page that is created. In an web forms application, the project file is set up to be bound to the language compiler before the first page is created. Since the goal here is to include different languages in a project, the web site project is the choice for us.

Add web forms
Add two new web forms: one with C# code behind the other with VB code behind. For the sample I chose the names of csPage.aspx and vbPage.aspx, respectively. This is really easy at this point since the new web form dialog has a language drop down that allows the selection of your preferred language. For the sake of feedback, drop a label on the page. In the page load event handler, populate the label with the language used in the code-behind.

<asp:Label ID="languageTag" runat="server" />languageTag.Text="CSharp PageLoad Handler";

Try it out
At this point you should be able to bring up both pages. Already this is quite different than the usual web site. Two pages that are peers in the same project have been created with different languages.

Add user controls
Add two new web user controls: one with C# code-behind the other with VB code-behind. The sample uses the names csUserControl.ascx and vbUserControl.ascx. Just like with the forms, the language can be selected right on the add User Control dialog. Just like in the forms, add a label to the control. Just like in the forms populate the page load event handler for the control with code to update the label with the language used in the code-behind of the control.

<asp:Label ID="languageTag" runat="server" />languageTag.Text = "CSharp UserControl PageLoad Handler";

Include the controls
Drag both controls onto each of the language-specific pages. No additional work is required to wire up events on the controls, as they are self contained for this example.

<uc1:vbUserControl ID="vbUserControl1" runat="server" />
<uc2:csUserControl ID="csUserControl1" runat="server" />

Try it out
Bring up both pages again. Now for any given page multiple languages are being used to render it!

Add classes
So far, the steps involved in adding multiple languages to pages and user controls have been discoverable using Visual Studio directly. Adding classes is slightly different. The App_Code folder will enable us to pull off multipule-language classes. Add an App_Code folder if you do not have one already: right-click the project, select Add ASP.NET folder, there will be an App_Code selection. In the App_Code folder, add a new class for both VB and C#. Here again, the language selection still lets you choose a language. As a quick way to get some feedback from each class, provide an override of ToString that will say what language the class is written in.

public override string ToString()
{
  return "CSharp class text";
}
Public Overrides Function ToString() As String
  Return "VisualBasic class text"
End Function

Add the classes to the forms

Add labels to the language specific pages, one for each language specific class. In the page load event handler for the page, instantiate one instance of each class and populate the new labels on the page with the ToString call from each language specific class

csClass mycsClass = new csClass();
vbClass myvbClass = new vbClass();
csClassText.Text = mycsClass.ToString();
vbClassText.Text = myvbClass.ToString();

However, if you bring up one of the pages you will be greeted with a compiler error that the two classes use a different language.

Adding multiple language support to App_Code
In order to use multiple languages inside App_Code you will need to add sub folders to App_Code. I'll name these folders csharp and visualbasic in the sample. Now, notify the compiler that these subfolders should be compiled separately. This can be done by adding a codeSubDirectories section under the compilation area of the web.config.

<codeSubDirectories>
    <add directoryName="csharp"/>
    <add directoryName="visualbasic"/>
</codeSubDirectories>

Move the VB class from App_Code to this visualbasic folder, and the C# class to the csharp folder, then try to view one of the pages.

Try it out
That is it! Now we have forms, user controls, and classes all using both VB and C# included in the same project file.

 

Now what
The first thing to ask when seeing a new technique, is "What would I use this for?" Being a fan of TDD, I have issues with this approach, but I will leave that for the next post. If you don't care much about test coverage, this technique is useful for leveraging features specific to a language to get the job done as efficiently as possible.

Sample Project

MultiLanguage.zip (7.61 KB)

Dennis Burton

View Dennis Burton's profile on LinkedIn
Follow me on twitter
Rate my presentations
Google Code repository

Community Events

Windows Azure Boot Camp Lansing GiveCamp