Tag Archives: asp.net

Enabling Web Transforms when debugging ASP.NET apps

Web Transformations is a great feature. When a web application is packaged or published, the Web.config file is transformed dependent on which Visual Studio / MSBuild configuration you are running, enabling environment-specific settings to change accordingly.

However, to my mind there is a shortcoming. Since the transformation happens during packaging or publishing of the application, transformation rules do not take effect when debugging a web application (typically by hitting F5 in Visual Studio) because the application is served from the project directory. Here’s how to solve this: essentially, we can change the the project setup so that the transformation happens right after the project build step. Here’s how:

Step 1: Unload the project in Visual Studio

In the Solution Explorer in Visual Studio, right-click on the project and select Unload project from the context menu:

Step 2: Rename Web.config on the file system

In the Windows Explorer, browse to the project directory, and rename Web.config to Web.template.config:

Step 3: Rename Web.config in the project file

What we will do here, is to rename the existing Web.config to Web.template.config in the project file (.csproj or .vbproj). This will be the file that we keep in the version control system, and the final Web.config will instead be generated for us when building the application.

In the Solutuion Explorer in Visual Studio, right-click on the project and select Edit <project name>:

Search for “web.config” in the project file to locate where the Web.config and transformation files definitions. It looks something like so:

<Content Include="Web.config" />
<Content Include="Web.Debug.config">
   <DependentUpon>Web.config</DependentUpon>
</Content>
<Content Include="Web.Release.config">
   <DependentUpon>Web.config</DependentUpon>
</Content>

In the project file, for instance on the line after the one with Web.config, add the following:

<None Include="Web.template.config" />

Then, change the text of the DependentUpon element to read Web.template.config instead of Web.config. Finally, change the Content elements for for Web.Debug.config and Web.Release.config to None elements. This prevents these files from being included in the deployment package. They don’t need to be, as the transformations have already been run. All in all, the snippet from above should now read:

<Content Include="Web.config" />
<None Include="Web.template.config" />
<None Include="Web.Debug.config">
   <DependentUpon>Web.template.config</DependentUpon>
</None>
<None Include="Web.Release.config">
   <DependentUpon>Web.template.config</DependentUpon>
</None>

Step 4: Running transformation when building

Now that we have a reference to Web.template.config in the project file, the next step is to run the transformation during the build step. Add a custom target that runs the transformation and then include it at the begining of the build task using the {{BuildDependsOn}} property. The resulting XML snippet looks like so:

<PropertyGroup>
  <BuildDependsOn>
    CustomWebConfigTransform;
    $(BuildDependsOn);
  </BuildDependsOn>
</PropertyGroup>
<Target Name="CustomWebConfigTransform">
   <TransformXml> source="Web.template.config"
      transform="Web.$(Configuration).config"
      destination="Web.config" />
</Target>

Save the file and reload the project into the Visual Studio solution. Then, in the Solution Explorer, observe that the Web.config file now is denoted as missing, and that the Web.template.config is present with the two transformation files beneath it in the file tree:

Step 5: Test running transformations during build

In this step, we will test that the transformations will be run when launching the application by hitting F5 in Visual Studio. First, we need to create a configuration example in Web.Debug.config. Remove all the gunk that Microsoft so helpfully has filled the file with during project creation, and insert one simple appSettings entry, making the Web.Debug.config look like this:

<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <appSettings>
    <add key="Configuration" value="Debug" xdt:Transform="Insert"/>
  </appSettings>
</configuration>

Take care to include the xdt XML namespace definition. Without it, the transformations will not be run.

Open up an ASPX page, for instance Default.aspx, and enter a label that will display the value of our confiugration setting:

<

pre class=”xml” name=”code”>
<p>
Configuration: <asp:Label ID=”Configuration” runat=”server” />
</p>

Next, enter this in the code behind:

protected void Page_Load(object sender, EventArgs e)
{
   Configuration.Text = ConfigurationManager.AppSettings["Configuration"];
}

Hit F5 to run the application and verify that it in fact is able to read from the transformed Web.config:

Step 6: Disable transformations during packaging and publishing

Since msbuild by default runs the transformations, we need to disable this to prevent the transformations to be applied twice. To do this, unload the project from the solution as we did in step 1, and then edit the project file in Visual Studio. For each of the configurations that you have in your solution, disable the built-in transformation runs by adding the TransformWebConfigEnabled element and setting it to false. Like so:

<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
   <TransformWebConfigEnabled>False</TransformWebConfigEnabled>
   ...
</PropertyGroup>

Summary / other tweaks

What we have achieved, is that the transformations are applied when building the application, making the transformed file available when running the application locally from Visual Studio. Another tip with regards to Web Transformations is to use the SlowCheetah Visual Studio Add-in that Scott Hanselman has described very well here. It will give you a nice transformation preview on the context menu in Visual Studio which is extremely helpful.

Getting user information programmatically from Windows Identity Foundation

You can use the Windows Identity Foundation SDK to replace the authentication scheme of your ASP.NET web application. Most notably, this is useful for making your application claims-aware, which allows it to seamlessly play together with solutions like Active Directory Federation Services or the Windows Azure AppFabric Access Service. This is useful for a various number of SSO and federated authentication scenarios.

Basically, what you do is that you switch off the built-in authentication in ASP.NET like forms-based authentication, and let WIF act as a proxy in front of your application. WIF uses the authorization settings in web.config (/configuration/system.web/authorization and /configuration/location/system.web/authorization elements) and authenticates the user before the ASP.NET application receives the request. See WS-Federated Authentication Module Overview for details

So, when the application receives the request, the user is already authenticated, which is fine. However, there are times when the application needs to know who the user is, or getting access to the other claims that were provided from the identity service. Luckily, this is available on the HTTP context. Say, for instance, if you wish to find the email address of the logged-in user, you can do it like so:

protected void Page_Load(object sender, EventArgs e)
{
    var claimsIdentity = Context.User.Identity as IClaimsIdentity;
    foreach (var claim in claimsIdentity.Claims)
    {
        if (claim.ClaimType == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress")
        {
            var email = claim.Value;
        }
    }
}

If the user was authenticated using claims, Context.User.Identity will be an IClaimsIdentity which will contain a number of claims about the user. We can then iterate over these claims to find the one that we want.

The claim types are denoted using XML namespaces, which are a little bit cumbersome to work with. So, to make it easier to access, we iterate over the list of claims, and make all the claims available on a common object:

public static class IdentityExtension
{
    public static DynamicUser GetUserFromClaims(this HttpContext context)
    {
        var claimsIdentity = context.User.Identity as IClaimsIdentity;
        if (claimsIdentity == null) throw new FailedAuthenticationFaultException();
        return new DynamicUser(claimsIdentity.Claims);
    }
}
public class DynamicUser : DynamicObject
{
    private readonly ClaimCollection _claims;
    public DynamicUser(ClaimCollection claims)
    {
        _claims = claims;
        Id = ClaimsValue("nameidentifier")[0];
    }
    public string Id { get; private set; }
    public bool IsInRole(string role)
    {
        return ClaimsValue("role").Any(c => c.Equals(role, StringComparison.OrdinalIgnoreCase));
    }
    private string[] ClaimsValue(string claimSuffix)
    {
        return _claims.Where(c => c.ClaimType.EndsWith(claimSuffix)).Select(c => c.Value).ToArray();
    }
    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        var claimValue = ClaimsValue(binder.Name.ToLowerInvariant());
        if (claimValue.Length == 0)
        {
            return base.TryGetMember(binder, out result);
        }
        if (claimValue.Length == 1)
        {
            result = claimValue[0];
        }
        else
        {
            result = claimValue;
        }
        return true;
    }
}

Then, we can access the claim values using a prefix of the actual XML namespace of the claim type:

protected void Page_Load(object sender, EventArgs e)
{
    var user = Context.GetUserFromClaims();
    var id = user.Id;
    var username = user.Name; // "John Doe"
}

When hooking up the application to Windows Azure AppFabric Access Control Service (ACS), which claims that the application will receive depends on your rule group configuration. Here are some examples:

Claim type Shorthand Example value
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier user.Id NHsTR1UXFI9xYk1xIRUNfucZ4/a5OWiILHlNyNEXozP=
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name user.Name John Doe
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress user.Emailaddress john.doe@hotmail.com

If you set up role claim rules in ACS, you can even get information about the user’s roles so that you can do authorization in the code:

protected void Page_Load(object sender, EventArgs e)
{
    var user = Context.GetUserFromClaims();
    var isAdmin = user.IsInRole("administrator"):
}

Adding WCF REST services to existing ASP.NET web application

If you want to create a new WCF services application with REST support, the WCF REST Templates are brilliant. However, if you have an existing ASP.NET application from which you want to expose REST services, there are a few manual steps you need to take to get it up and running:

Add assembly references

Add references to the following assemblies in your existing web project:

  • System.ServiceModel
  • System.ServiceModel.Activation
  • System.ServiceModel.Web

Create service class

Create a new service class where you will implement the service:

[ServiceContract]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
public class LetterService
{
    [WebGet(UriTemplate = "")]
    public List<string> GetList()
    {
        return new List<string>{"a", "b", "c"};
    }
}

Register service route

In Global.asax.cs, define a route to the service:

void Application_Start(object sender, EventArgs e)
{
    RouteTable.Routes.Add(new ServiceRoute("letter", new WebServiceHostFactory(), typeof(LetterService)));
}

Enable ASP.NET compatability

Add the following to web.config:

<configuration>
   <system.serviceModel>
      <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
   </system.serviceModel>
</configuration>

…and you are good to go! The service will be available on http://<server>/letter

Optional: enable help

In order to get a nice help page for clients connecting to the service, add the following under the system.serviceModel element in web.config:

<standardEndpoints>
   <webHttpEndpoint>
      <standardEndpoint name="" helpEnabled="true" automaticFormatSelectionEnabled="true" />
   </webHttpEndpoint>
</standardEndpoints>

Then, help will be available on http://<server>/letter/help

Testability with System.Web.Abstractions and no mock framework

As a follow-up to my previous post ASP.NET 3.5: improving testability with System.Web.Abstractions, I would like to show how the same testability can be achieved without using any mock framework like Rhino.Mocks. The C# 3.0 featuires ‘object initializers’ and ‘automatic properties’ makes our code sufficiently non-verbose to make it easy and readable.

So, given the same examples as in my previous post, here is what the test code will look like:

Example #1: Testing a page codebehind file

[TestMethod]
public void ShouldSetNoCacheabilityOnDefaultPage()
{
    _Default page = new _Default();
    HttpCachePolicyMock httpCachePolicyMock = new HttpCachePolicyMock();
    page.SetCacheablityOfResponse(new HttpResponseStub
    {
        TheCache = httpCachePolicyMock
    });
    httpCachePolicyMock.ShouldHaveSetCacheabilityTo(HttpCacheability.NoCache);
}
class HttpResponseStub : HttpResponseBase
{
    public override HttpCachePolicyBase Cache { get { return TheCache; } }
    public HttpCachePolicyBase TheCache { get; set; }
}
class HttpCachePolicyMock : HttpCachePolicyBase
{
    private HttpCacheability _cacheability;
    public override void SetCacheability(HttpCacheability cacheability)
    {
        _cacheability = cacheability;
    }
    public void ShouldHaveSetCacheabilityTo(HttpCacheability expectedCacheability)
    {
        Assert.AreEqual(expectedCacheability, _cacheability);
    }
}

I have created two helper classes, one with the suffix -Stub and one with the suffix -Mock. The convention here is that a stub is a type of class used to provide a context to the class under test. Mocks also do that, but additionally a mock can make expectation about what should happen to it during the test.

Example #2: Testing an HTTP handler

[TestMethod]
public void ShouldRedirectAuthenticatedUser()
{
    HttpServerUtilityMock httpServerUtilityMock = new HttpServerUtilityMock();
    HttpContextStub httpContextStub = new HttpContextStub
    {
        TheRequest = new HttpRequestStub { IsItAuthenticated = true },
        TheServer = httpServerUtilityMock
    };
    new RedirectAuthenticatedUsersHandler().TransferUserIfAuthenticated(httpContextStub);
    httpServerUtilityMock.ShouldHaveTransferredTo("/farfaraway");
}
class HttpContextStub : HttpContextBase
{
    public override HttpRequestBase Request { get { return TheRequest; } }
    public override HttpServerUtilityBase Server { get { return TheServer; } }
    public HttpRequestBase TheRequest { get; set; }
    public HttpServerUtilityBase TheServer { get; set; }
}
class HttpRequestStub : HttpRequestBase
{
    public override bool IsAuthenticated { get { return IsItAuthenticated; } }
    public bool IsItAuthenticated { get; set; }
}
class HttpServerUtilityMock : HttpServerUtilityBase
{
    private string _path;
    public override void TransferRequest(string path)
    {
        _path = path;
    }
    public void ShouldHaveTransferredTo(string expectedPath)
    {
        Assert.AreEqual(expectedPath, _path);
    }
}

ASP.NET 3.5: improving testability with System.Web.Abstractions

The testability of ASP.NET code has long been a challenge; creating unit tests for your ASP.NET code has been difficult. One of the main points of the new ASP.NET MVC framework has been to make code written for it easily testable. However, not many people know that in ASP.NET 3.5, Microsoft has added a few features to make any ASP.NET applications, not only ASP.NET MVC applications, more easy to test. The System.Web.Abstractions assembly adds a few classes to the System.Web namespace that will help the situation. For instance, looking at the documentation for System.Web.HttpRequestBase, it states that

The HttpRequestBase class is an abstract class that contains the same members as the HttpRequest class. The HttpRequestBase class enables you to create derived classes that are like the HttpRequest class, but that you can customize and that work outside the ASP.NET pipeline. When you perform unit testing, you typically use a derived class to implement members that have customized behavior that fulfills the scenario that you are testing.

Very well. Looking at the documentation for HttpRequest, we see that HttpRequest is not a decendent of HttpRequestBase as one might expect from the name. The reason for this is probably that that would break backwards compatability with older versions of ASP.NET. So, how can we exploit the HttpRequestBase then? The answer is the HttpRequestWrapper class which is a decendant of HttpRequestBase and has a constructor that takes an HttpRequest object as a parameter. Then, we can take the HttpRequest object passed to our code from the framework, wrap it inside an HttpRequestWrapper object and pass it on to our code as a HttpRequestBase object. As I will show you in the examples below, this will enable us to create unit tests of our code by creating fake implementations of ASP.NET framework clases (using Rhino.Mocks).

Example #1: Testing a page codebehind file

Take, for instance, this simple page codebehind code that we would like to test:

using System;
using System.Web;

public partial class _Default : System.Web.UI.Page
{
    protected void Page_Init(object sender, EventArgs e)
    {
        Response.Cache.SetCacheability(HttpCacheability.NoCache);
    }
}

The first step to take here, is to extract a method which take the request object as a parameter instead of fetching it from a method in a superclass. In general, this is a variation of the dependency injection pattern which in many situations will help us make our code testable (also, see my earlier related post). Like so:

using System.Web;
using System;

public partial class _Default : System.Web.UI.Page
{
    protected void Page_Init(object sender, EventArgs e)
    {
        SetCacheablityOfResponse(Response);
    }

    public void SetCacheablityOfResponse(HttpResponse response)
    {
        response.Cache.SetCacheability(HttpCacheability.NoCache);
    }
}

So, then having extracted our code in a separate method, the next step is to change the parameter type of this method from HttpRequest to HttpRequestBase. Furthermore, when calling this method, we need to wrap the HttpRequest object by creating an instance of HttpRequestWrapper. The code, then, looks like this:

<

pre class=”c-sharp” name=”code””>using System.Web;
using System;

public partial class _Default : System.Web.UI.Page
{
protected void Page_Init(object sender, EventArgs e)
{
SetCacheablityOfResponse(new HttpResponseWrapper(Response));
}

public void SetCacheablityOfResponse(HttpResponseBase response)
{
    response.Cache.SetCacheability(HttpCacheability.NoCache);
}

}
Having now prepared our code for testing, we can create a unit test where we test the SetCacheabilityOfResponse method:

[TestMethod]
public void ShouldSetNoCacheabilityOnDefaultPage()
{
    _Default page = new _Default();
    MockRepository mocks = new MockRepository();
    HttpResponseBase responseStub = mocks.Stub<HttpResponseBase>();
    HttpCachePolicyBase cachePolicyMock = mocks.CreateMock<HttpCachePolicyBase>();
    With.Mocks(mocks).Expecting(delegate
    {
        SetupResult.For(responseStub.Cache).Return(cachePolicyMock);
        cachePolicyMock.SetCacheability(HttpCacheability.NoCache);
        LastCall.On(cachePolicyMock).Repeat.AtLeastOnce();
    }).Verify(delegate
    {
        page.SetCacheablityOfResponse(responseStub);
    });
}

If you are not familiar with Rhino.Mocks or any other mocking framework, there appears to be a lot going on in that test. The basic idea is that we create derivatives of the -Base classes and pass these to the code that we are going to test, mimicking the behavior of the “real” objects that the framework would pass our code at runtime. Also note that in this particular test we test the side effect of our code, namely that the code should call a the SetCacheability method with a specific parameter. This is achieved using a mock object.

Example #2: Testing an HTTP Handler

Given the following HTTP handler code:

using System;
using System.Web;

public class RedirectAuthenticatedUsersHandler : IHttpHandler
{
    public void ProcessRequest(HttpContext context)
    {
        if (context.Request.IsAuthenticated)
        {
            context.Server.TransferRequest("/farfaraway");
        }
    }
}

Again, we extract the code we want to test into a separate method, passing it a -Base object and wrap the object passed to us from the framework in a -Wrapper object:

using System;
using System.Web;

public class RedirectAuthenticatedUsersHandler : IHttpHandler
{
    public void ProcessRequest(HttpContext context)
    {
        TransferUserIfAuthenticated(new HttpContextWrapper(context));
    }

    public void TransferUserIfAuthenticated(HttpContextBase context)
    {
        if (context.Request.IsAuthenticated)
        {
            context.Server.TransferRequest("/farfaraway");
        }
    }
}

This allows us to create unit tests for the TransferUserIfAuthenticated method, for instance:

[TestMethod]
public void ShouldRedirectAuthenticatedUser()
{
    RedirectAuthenticatedUsersHandler handler = new RedirectAuthenticatedUsersHandler();
    MockRepository mocks = new MockRepository();
    HttpContextBase httpContextStub = mocks.Stub<HttpContextBase>();
    HttpRequestBase httpRequestBaseStub = mocks.Stub<HttpRequestBase>();
    HttpServerUtilityBase httpServerUtilityMock = mocks.CreateMock<HttpServerUtilityBase>();
    With.Mocks(mocks).Expecting(delegate
    {
        SetupResult.For(httpContextStub.Request).Return(httpRequestBaseStub);
        SetupResult.For(httpContextStub.Server).Return(httpServerUtilityMock);
        SetupResult.For(httpRequestBaseStub.IsAuthenticated).Return(true);
        httpServerUtilityMock.TransferRequest("/farfaraway");
        LastCall.On(httpServerUtilityMock).Repeat.AtLeastOnce();
    }).Verify(delegate
    {
        handler.TransferUserIfAuthenticated(httpContextStub);
    });
}

Summary

I have shown two very simple examples on how some of the classes in the System.Web.Abstractions assembly can help us test our ASP.NET code. I have used HttpResponseBase, HttpServerUtilityBase, HttpContextBase, HttpRequestBase, and HttpCachePolicyBase. Note that there are a number of classes available, so if you are faced with not being able to test your ASP.NET code because of dependencies to classes in the framework, take a look in the System.Web namespace and see if there are -Base classes that can help you out.

Testability is a large topic, and there is much to be said about it. I have shown a couple of very simple examples on how to improve testability. Testability has a lot to do with code design as well; in a real world I would write the test before writing the code and I would move my code out of codebehinds. Those topics are discussed a lot elsewere, hopefully this post will bring you a small step further in writing testable code.

ASP.NET: Delegate identity from a web application to a back end web application

One of the things that seem very simple on a Powerpoint presentation, but are not that simple in practice, is having a web user’s identity forwarded from a calling web application to another web application when using Kerberos.

The case is as follows: I have an intranet application A which uses Integrated Windows Authentication to authenticate the user. During processing of a request from a web users, application A then makes an HTTP request to intranet application B. Application B requires the web user to be authenticated to process the request. The often most attractive solution for solving this is what Microsoft refers to as identity delegation. Simple in a Powerpoint presentation, but alas, not so simple in practice.

First of all, there are a number of preconditions in the computing environment configuration that need to be fulfilled. I found a very good summary of gotchas in this respect here. In my case, the points 2 and 6 was  missing (I knew about the other once beforehand). So, when all configuration stuff set up, then the only thing left is the code and configuration in the application A.

Basically, you need to make the application impersonate the web user (meaning that it will run with the credentials of the web user). There are two ways to do this. If you wish the entire request to run as the web user, you can insert an <identity impersonate=”true” /> element under <system.web> in the application’s web.config. Or, if you wish only the request to application B to run as the web user, you can do this programmatically:

using System.Security.Principal;
...
WindowsIdentity identity = (WindowsIdentity)HttpContext.Current.User.Identity();
using (identity.Impersonate())
{
    // ... code to call application B goes here ...
}

Then, the next task is to call application B itself. You can do this by creating a web request:

HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://www.somethingcompletelydifferent.com");
request.ImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Delegation;
request.UseDefaultCredentials = true;
...
HttpWebResponse response = request.GetResponse();
...

The important things to notice here is that we set the ImpersonationLevel property to “Delegation” and that we set the UseDefaultCredentials property to “true”. So, it together, we get:

using System.Security.Principal;
...
WindowsIdentity identity = (WindowsIdentity)HttpContext.Current.User.Identity();
using (identity.Impersonate())
{
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://www.somethingcompletelydifferent.com");
    request.ImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Delegation;
    request.UseDefaultCredentials = true;
    ...
    HttpWebResponse response = request.GetResponse();
    ...
}

You can then test that it works in application B by checking the name in HttpContext.Current.User.Identity.Name.