Visual Studio Gallery


That is just a quick post to share 2 extensions for Visual Studio that I just discovered and already know I won’t be able to live without.

First, I looked at the Visual Studio Gallery before but kind of forgot about it until I read an article (categorized as Vendor-Sponsored Content so not available online) in the October issue of the MSDN Magazine. This article was about a top 10 list of free extensions for Visual Studio.

Anyway, the first extension is called GhostDoc and allows auto-generation of XML comments. I can already hear you say “yeah, but if I put 3 quotes in VB or 3 slashes in C# it already does that for me”. Nope, this extension not only creates the structure of the comment section but also writes the comments depending on what you are trying to comment. Here is an example of comment generated by GhostHost:

   1: /// <summary>
   2: /// 
   3: /// </summary>
   4: public class Person
   5: {
   6:     /// <summary>
   7:     /// Initializes a new instance of the <see cref="Person"/> class.
   8:     /// </summary>
   9:     /// <param name="name">The name.</param>
  10:     /// <param name="age">The age.</param>
  11:     public Person(string name, int age)
  12:     {
  13:     }
  14: }

Of course this is a very simple example but I didn’t type a single line of comment. It was all generated by the tool. It does so much more than that so imagine the potential time saving. It supports C# and claims to be only experimental for VB but so far it seems to be working fine in both cases.

The extension can be downloaded at http://visualstudiogallery.com/ExtensionDetails.aspx?ExtensionID=46a20578-f0d5-4b1e-b55d-f001a6345748

The second extension is called Power Command. This extension adds many function to the context menu within Visual Studio. Some of the new functions are shown in the screenshot below. I think one of the most useful for me right of the bat is the “Collapse Project” one. We have a few solutions with many projects and for some reason, VS always opens the solution with all projects expanded. Just with 2 clicks, you can collapse all projects.

image

The extension can be downloaded at http://visualstudiogallery.com/ExtensionDetails.aspx?ExtensionID=df3f0c30-3d37-4e06-9ef8-3bff3508be31

Update 11/7: Found out that this extension crashes VS when trying to add items to the toolbox or opening Xaml files. I experiences the toolbox issue myself. Still a great extension developed by MSFT so let’s hope this issue will be resolved soon and a new version published.

I may post more of those later if I find any more useful ones (I tend to be a sucker for plug-ins, add-ons and extensions in general…)

Advertisements

Flattening the WSDL for WCF services


Windows Communication Foundation is Microsoft’s latest implementation for distributed computing including web-services. One of the key features of SOAP based web services is the WSDL (Web Service Definition Standard) that allows client applications written in any language and running on any platform to discover how to communicate with the services.

In WCF, the WSDL generated for each service uses a feature that is part of the WSDL standard but is not yet widely supported – Import statements. This feature allows to have external files to define sub-sections of the WSDL. This becomes a problem when you are trying to consume a WCF service from systems that have web service implementations that do not support those statements.

This can be fixed by forcing WCF to flatten the WSDL. Christian Weyer wrote a very good article about this so I won’t try to rewrite it because I wouldn’t be able to do it better. Instead, just go and take a look at it for yourself: http://blogs.thinktecture.com/cweyer/archive/2007/05/10/414840.aspx#.

This helped me a lot when trying to make one of my WCF services consumable from Mercator. I hope this can save you some time too.

CryptographicException: The handle is invalid


The Problem

I was recently working on a method to load a X509 certificate from the server’s certificates store. While my code worked fine on my local machine, I kept getting a System.Security.Cryptography.CryptographicException saying that the handle was not valid after deploying to our test server. I made sure that the certificate was present in the store.

The code I was using to read the certificate looked something like this:

   1: using System.Security.Cryptography.X509Certificates;
   2: ...
   3:     private X509Certificate2 GetCertFromStore(StoreName name, StoreLocation location, X509FindType findType, Object value)
   4:     {
   5:         X509Store store = new X509Store(name, location);
   6:         X509Certificate2 cert = null;
   7:         try
   8:         {
   9:             store.Open(OpenFlags.ReadOnly);
  10:             cert = store.Certificates.Find(findType, value, False)[0];
  11:         }
  12:         finally
  13:         {
  14:             if (store != null)
  15:                 store.Close();
  16:         }
  17:         return cert;
  18:     }
  19: }

Why is it happening?

It came down to a permissions issue. On my local machine, I am an administrator and I had the rights to read the certificate. However, the account my application was running under on the test server did not have the necessary permissions to read the certificate or the Private Key File to be exact.

The Solution

The solution is to give the account read rights to the certificate and this can be achieved using the Certificates Tool from WSE 3.0. WSE 3.0 is the latest version of Web Service Enhancements for .NET and can be downloaded here.

After you open the tool, you will be presented with a window like this one:

image

Choose the location of the certificate for which you want to alter permissions (in my case it is on the Local Computer in the Personal store) and click on Open Certificate. This will open another dialog allowing you to pick which certificate you want to work with in case you have more than one in the store.

To update the permissions, you need to click on the View Private Key File Properties… button. The dialog that opens is the usual file properties dialog so it should look familiar and updating the security settings should be straight forward. You only need to allow Read & Execute and Read permissions for the account running your app.

cert_permisssions

Processing extension-less files with IIS 6.0 and ASP.NET


The problem

As part of a Single Sign-On implementation with a 3rd party system using SAML 2.0, the user was being redirected to a URL looking like https://mydomain.com/Profile/SAML2/Redirect/SSO?SAMLRequest=&#8230; which is the standard for a Shibboleth implementation of SAML 2.0.

This is all good if you are using a web server such as Apache which doesn’t really care if files have an extension or not and for which URL rewriting is common and easy to implement. The problem with IIS 6, is that the file will not be served by IIS and even if it was, it couldn’t be processed by the ASP.Net ISAPI filter because it doesn’t have an extension registered with this filter.

Solutions

In both cases, IIS needs to be configured to process extension-less files. However, on the ASP.NET side, there are 2 solutions that can be implemented to solve this problem. The first one uses the URL redirect feature of IIS and the second one uses URL Rewriting in ASP.NET. For the end user, both approaches will have the same result but depending on your situation you may want to pick one or the other depending on the implementation and maintenance constraints.

Security and performance warning

The settings described below have both security and performance implications. Therefore, it is important to apply these changes only on the directories or virtual directories at the lowest level possible and not at the website level (unless really necessary).

Solution 1 – Configuring URL redirect in IIS

If a redirection is not an issue, this is the easiest solution to implement. There are several drawbacks to consider:

  • The URL the end user will end on will be different than the original target URL. This is usually just a cosmetic thing and shouldn’t matter much.
  • Some search engines do not like redirects.
  • If there are a lot of extension-less files that need to be accessible through IIS, this will become a cumbersome process because each individual file needs to be configured in IIS. In our particular case, this wasn’t an issue because we had a single file to handle.

You can accomplish this solution with a few steps:

  1. Create an empty file with the name of the target (e.g. SSO)
  2. Upload the ASP.NET version of the file which will be the one processed by IIS (e.g. SSO.aspx)
  3. Right-click on the file from the IIS management console and open the Properties window
  4. Select the A redirection to a URL radio button
  5. Enter the new URL (https://mydomain.com/Profile/SAML2/Redirect/SSO.aspx$Q) in the Redirect to text box. The $Q part of the URL is explained below in the “Dealing with query strings” section
  6. make sure that The exact URL entered above and A permanent redirection for this resource radio buttons are selected

redirect

Dealing with query strings

In our particular case, the URL our users are being sent to contains a query string. If you just enter the URL of the new page to go to, the query string will be lost. To solve this problem, you just append $Q (dollar sign and capital letter Q) at the end of the URL and IIS will substitute it with the actual query string when doing the redirect.

Solution 2 – URL Rewriting

URL rewriting is a little cleaner from the user’s point of view because there is no redirection or URL change on the browser side. In addition to this, it also allows us to create a catch-all solution to be able to process all extension-less files in a directory with a single configuration change. If we add new files, they will automatically be processed in the same way.

Configuring IIS to serve extension-less files

By default, IIS 6 does not process files that do not have an extension. The first step will be to change this behavior by creating a new MIME type. MIME types are created in the HTTP Headers tab of the directory’s or website’s Properties window:

1. click on the MIME Types… button to view the existing MIME Types
http_header

2. Click on the Add… button to create a new MIME type
mime_types

3. Enter the Extension and MIME Type as shown on the screenshot below
image

4. Click OK to close all the MIME windows

Wildcard Mapping

Now that IIS will process extension-less files, we need to make sure that those files are processed by the asp.net ISAPI filter. To do this, we need to create a wildcard mapping.

  1. On the WebSite or Virtual Directory Properties window, go to the Home Directory tab and click on the Configuration… button.
    image
  2. On the Application Configuration window, make sure you are on the Mappings tab and click on the Insert… button in the Wildcard application maps section
    image
  3. Browse to the aspnet_isapi.dll file for the .Net Framework 2.0. Also make sure that the Verify that file exists checkbox is unchecked
    image
  4. Click OK and we are done with this step

URL Rewriting using an HTTPModule

After setting up the extension mapping, all files in that directory will be passed through the ASP.NET processor before being served by IIS but they will not be treated as ASP.NET files because of their lack of extension. If we were to stop here, the actual inline C# or VB.NET code would be served by IIS instead of being processed by ASP.NET.

To resolve this issue, we are going to use a trick called URL rewriting using an ASP.NET feature called HTTP Modules. For this, we need to create the module and then modify our web.config to add the module to the page lifecycle.

The HTTP Module:

   1: using System.Web;
   2:
   3: public class aspneturlModule : System.Web.IHttpModule
   4: {
   5:     public void Init( System.Web.HttpApplication context )
   6:     {
   7:         context.BeginRequest += new System.EventHandler(this.BaseModuleRewriter_BeginRequest);
   8:     }
   9:
  10:     private void BaseModuleRewriter_BeginRequest(object sender, System.EventArgs e)
  11:     {
  12:         HttpApplication app = (HttpApplication)sender;
  13:         string requestedPage = app.Request.RawUrl;
  14:         string appVirtualPath = app.Request.ApplicationPath;
  15:
  16:         if (requestedPage.Length >= appVirtualPath.Length)
  17:         {
  18:             if (requestedPage.Substring(0, appVirtualPath.Length - 1).ToLower() == appVirtualPath.ToLower())
  19:                 requestedPage = requestedPage.Substring(appVirtualPath.Length);
  20:             else
  21:                 requestedPage = string.Format("{0}.aspx?{1}", app.Request.FilePath, app.Request.QueryString.ToString());
  22:         }
  23:
  24:         HttpContext.Current.RewritePath(requestedPage);
  25:     }
  26:
  27:     public void Dispose()
  28:     {}
  29: }

The code presented above is a very simple version of an HTTP Module doing the URL rewriting for our case. This is just to illustrate how such a module would be created but there are a lot of different scenarios that may need to be handled differently.

After building the module, place the resulting library file (e.g. HTTPModule.dll) in the bin folder of the Website or Virtual Directory. If there is no bin folder, create it.

The web.config

We now need to reference this module in the web.config. Open the web.config file and locate the section about httpModules. Then, add our new module like this:

   1: <httpModules>
   2:     […] (other httpModules if any)
   3:     <add type="HttpModule.aspneturlModule" name="HttpModule" />
   4: </httpModules>

We are all set. As opposed to the first solution presented, there is no need to create an empty file without extension and the user will not be redirected to a .aspx file. It all happens behind the scenes.

const vs. static readonly


The problem
I was recently working on an application that relied on a common library stored in the server’s GAC. The application is using constants that are defined in the common library and have different values depending on the environment the application is being deployed to (Dev, Test or Prod). Everything worked fine in our Dev environment but while debugging our code in Test, we found out that it was using the Dev values of the constants instead of the Test values even though the common library stored in the GAC was correct.

Why is it happening?
The cause of this problem is due to the way constants are treated at compile time. Let’s look at the following code:

common.dll
const string MY_CONSTANT = “My Dev value”;

app.exe
if (common.MY_CONSTANT == “My Dev value”) {…}

The .Net compiler substitutes the constant name with its actual value in app so this would actually be equivalent to writing:

if (“My Dev value” == “My Dev value”) {…}

which is the code that will be converted to IL. As a result, it doesn’t matter what the value of the constant is in the dll that has been placed in the GAC because this value will not be read at run-time.

The solution
One of the ways to solve this would be to change the constants values each time the application is being built for a certain environment. This approach creates a build management nightmare and adds complexity when there is no need for it.

A second approach would be to remove the const keyword so the variable is not being substituted for its value at compile time but this would break the design and make for very bad coding practice.

The right way to handle this is to use the static readonly keywords. A static readonly variable can be initialized at declaration time or in a static constructor so the compiler does not know its value at compile time. As a result, there is no substitution and the value will be read at run-time. The fact that the variable is read-only allows to make sure that it has a similar behavior to a constant once initialized.
Besides the added flexibility for initialization, another benefit of a static readonly variable is that it can hold reference types other than string or null as const only can.