Visual Studio ‘Attach to w3wp process’ macro

In Visual Studio, choose Tools | Macro, Macros IDE, create a new module and drop this in. I bind it to Ctrl-Alt-1 for quick access.

    Sub AttachToW3WP()
        Dim attached As Boolean = False
        Dim proc As EnvDTE.Process

        For Each proc In DTE.Debugger.LocalProcesses
            If (Right(proc.Name, 8 ) = "w3wp.exe") Then
                proc.Attach()
                attached = True
            End If
        Next

        If attached = False Then
            MsgBox("w3wp.exe is not running")
        End If

    End Sub

Update: 12/March/2014 If you’re using Visual Studio 2012 or newer, you will need to use the AttachTo extension.

Fiddler tips for HTTP Debugging

Fiddler is a Web Debugging Proxy which logs all HTTP(S) traffic between your computer and the Internet. Fiddler allows you to inspect all HTTP(S) traffic, set breakpoints, and “fiddle” with incoming or outgoing data.

Download Fiddler from http://www.fiddler2.com/, it’s freeware! It runs on Windows, but can debug traffic originating in any operating system (by making that OS point to Fiddler on Windows as a proxy). Before reading this you should read these articles which provide an overview of Fiddler.

Stubbing network responses

During development with a third party it’s often handy to insulate yourself from any downtime/network problems that might affect your testing. Quite often this involves writing a piece of code to simulate network responses and pointing your app to that. Instead of doing this, turn to Fiddler.

Record and replay

Configure your application to use Fiddler as a proxy (see this for .NET apps, use localhost:8888), then hit your third party endpoint with your application. Fiddler will capture the traffic in the session list. Now, click on the Auto Responder tab and enable Automatic Responses. Drag each row from the session list into the Auto Responder list. Now re-run your app, and instead of connecting to the remote machine, Fiddler will auto-respond for you. (If you are using SSL, read how to decrypt SSL traffic and also in .NET you’ll need to suppress the invalid man-in-the-middle cert that Fiddler uses by returning true in the ServerCertificateValidationCallback

From an interface spec

If you have an interface spec but no endpoint to hit, create a file matching the content you expect to be returned, define a match for the URI, and use your sample file as the response content. See AutoResponder reference for more information.

You can use regex pattern matching for the URI, and you can either respond with a local file, or captured session. With a regex to match the entire host you can make all calls to your network resource respond with a HTTP 403 Denied and ensure your app behaves as expected.

Custom rules to show Akamai cached pages

I’ve used Akamai edge caching on a number of sites over the past few years to improve site performance, and it’s always useful to see which pages are being served from cache, and which aren’t. The easiest way I’ve found to do this is to add a custom rule to Fiddler to highlight requests for me. From Fiddler, choose Rules, Customize Rules. In the Javascript that opens, enter the following code:

With the other field definitions…

	public static RulesOption("Highlight Akamai cache Hits")
	var m_HighlightAkamaiHits: boolean = false;

In the “OnBeforeRequest” method…

	if (m_HighlightAkamaiHits) {	
		oSession.oRequest.headers.Add("Pragma", "akamai-x-get-cache-key");
		oSession.oRequest.headers.Add("Pragma", "akamai-x-cache-on");
		oSession.oRequest.headers.Add("Pragma", "akamai-x-cache-remote-on");
		oSession.oRequest.headers.Add("Pragma", "akamai-x-get-true-cache-key");
		oSession.oRequest.headers.Add("Pragma", "akamai-x-check-cacheable");
		oSession.oRequest.headers.Add("Pragma", "akamai-x-get-extracted-values");
		oSession.oRequest.headers.Add("Pragma", "akamai-x-get-nonces");
		oSession.oRequest.headers.Add("Pragma", "akamai-x-get-ssl-client-session-id");
		oSession.oRequest.headers.Add("Pragma", "akamai-x-serial-no");
	}

In the “OnBeforeResponse” method…

	if (m_HighlightAkamaiHits) {
		if (oSession.oResponse.headers.ExistsAndContains("X-Cache","TCP_MEM_HIT")) {
			oSession["ui-customcolumn"] = "HIT";
		} else if (oSession.oResponse.headers.ExistsAndContains("X-Cache","TCP_IMS_HIT")) {
			oSession["ui-customcolumn"] = "HIT";
		}
	}

Now close the Javascript file, and go back to Fiddler. If you made any mistakes in the Javascript, Fiddler will tell you immediately. From the Rules menu you now have a new option – “Highlight Akamai cache Hits”. Enable this, and visit http://www.facebook.com/ in your browser. In Fiddler, you should see the word “HIT” for several of the requests in the “custom” column. You can rearrange the column order to move the custom column if you like.

Add request time

This is a simple new rule but surprisingly handy.

With the other field definitions…

	public static RulesOption("Show response time")
	var m_ShowResponseTime: boolean = false;

Add to either “OnBeforeRequest” or “OnBeforeResponse” method…

	if (m_ShowResponseTime) {
		oSession["ui-customcolumn"] = DateTime.Now.ToString();
	}

Remember when using these rules that when you save the Javascript file, the Rules menu will be reset so any previously enabled rules will need re-enabling.

Fiddler also has a nice set of C# APIs which allow you to embed the fiddler engine directly into your test suite, which makes for a really nice set of integration tests (using the AutoResponder) with only a few lines of code. I’ll go into this in a future post.

Deserialising to IList

Having upgraded the website I work on to .net 2.0, one of our console apps failed whilst talking to a webservice on the site. We’d not changed anything on either the console app, or the website other than upgrading the website to 2.0.

The error message was “global:System.Collections.IList cannot be deserialized because it does not have a default public constructor”. This makes a lot of sense and it turns out that the class being serialised contains a public IList property. Changing this to a concrete type solved the problem.

So the question is… what was the deserialiser in 1.1 doing? how did it know which concrete type to deserialise to?

Horizontal Partitioning

We’ve got a moderately large database here – 80gb, 5 tables and 500m rows – and we had problems updating it. Following a bout of Horizontal Partitioning we’ve now got 130 tables and those rows distributed evenly across them. However when a check constraint was updated today SQL Server 2000 wouldn’t allow data to import and we got the error message:

UNION ALL view ‘Classifier_z’ is not updatable because a partitioning column was not found.

In the back of my mind i’d remembered about trusted and untrusted check constraints and after a bit of Googling (I did use Google so I can use it as a verb ;)) I found this page which displays all the currently untrusted constraints in your table, and further allows you to set them to trusted. Here’s the code too, just in case that target page disappears.

To display untrusted constraints:
[sql]
SELECT ctu.TABLE_SCHEMA, ctu.TABLE_NAME, cc.CONSTRAINT_NAME, cc.CHECK_CLAUSE
FROM INFORMATION_SCHEMA.CHECK_CONSTRAINTS AS cc
JOIN INFORMATION_SCHEMA.CONSTRAINT_TABLE_USAGE AS ctu
ON ctu.CONSTRAINT_NAME = cc.CONSTRAINT_NAME
WHERE objectproperty( object_id(quotename(cc.CONSTRAINT_NAME)), ‘CnstIsNotTrusted’ ) = 1
[/sql]

To make all constraints trusted:
[sql]
DECLARE @tablename nvarchar(300), @constraint nvarchar(300)
DECLARE @constraints cursor
SET @constraints = cursor fast_forward FOR
SELECT quotename(ctu.TABLE_SCHEMA) + N’.’ + quotename(ctu.TABLE_NAME), quotename(cc.CONSTRAINT_NAME)
FROM INFORMATION_SCHEMA.CHECK_CONSTRAINTS AS cc
JOIN INFORMATION_SCHEMA.CONSTRAINT_TABLE_USAGE AS ctu
ON ctu.CONSTRAINT_NAME = cc.CONSTRAINT_NAME
WHERE objectproperty( object_id(quotename(cc.CONSTRAINT_NAME)), ‘CnstIsNotTrusted’ ) = 1
OPEN @constraints
WHILE (1=1)
BEGIN
FETCH @constraints INTO @tablename, @constraint
IF @@fetch_status < 0 BREAK
EXEC('ALTER TABLE ' + @tablename + ' WITH CHECK CHECK constraint ' + @constraint)
END
[/sql]

Visual Studio, SSL and projects

Spent a while trying to get sub-projects opening within Visual Studio today where the root project has SSL security setup. Every time VS tried to open the sub-projects it would error with the message “Secure channel failed”.

Figured it out eventually – you need to add a location element to the web.config for the get_aspx_ver.aspx to allow anonymous access in the sub-projects.

E.g. your webroot is ~/ and you have the authorization element set to deny anonymous users:

[xml]

[/xml]

Then your subproject is within the folder ~/ProjectA. When you open ProjectA .NET will redirect to the login page for the web root. If that login page is under SSL, then VS.NET will fail. So add this to your web.config:

[xml]

[/xml]

Custom Validator Example

[csharp]
using System;
using System.Text;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;

namespace SocialAnimal.Web.UserControls
{
/// <summary>
/// If ControlToValidate has a value then DependantControl
/// must also have a value
/// </summary>
public class DependantFieldValidator : CustomValidator
{
private string _dependantControl = null;
private bool _showAlertBox = false;

[Description(@”If true, will show an alert box if the control validates false, otherwise will display an inline message”),
Category(“Behavior”)]
public bool ShowAlertBox
{
get { return _showAlertBox; }
set { _showAlertBox = value; }
}

[Description(@”The name of the dependant control which must have
a value if ControlToValidate has a value”),
Category(“Behavior”)]
public string DependantControl
{
get { return _dependantControl; }
set { _dependantControl = value; }
}

/// <summary>
/// Generate the client side code to validate the Controls
/// </summary>
/// <param name=”e”></param>
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
string controlToValidateId = Page.FindControl(ControlToValidate).ID;
string dependantControlId = Page.FindControl(_dependantControl).ID;

StringBuilder js = new StringBuilder();

//Generate the Validation Event to Validate control
js.Append(@”<script language=””JavaScript””>”);
js.Append(@”function DependantFieldValidateControl(val, args) {var msg=”;args.IsValid = true;”);

js.Append(@”if (document.all[‘” + controlToValidateId + “‘].value != ”){“);
js.Append(@” if (document.all[‘” + dependantControlId + “‘].value == ”){“);

// If AlertType is set to Alert else build the error message string to be displayed
js.Append(@” msg=msg+'” + ErrorMessage + “‘;}if(msg!=”){“);

if (ShowAlertBox)
{
js.Append(@”alert(msg);”);
}
else
{
js.Append(@”args.IsValid = false;”);
}

js.Append(@”}}}</script>”);

Page.RegisterClientScriptBlock(“funcValidate”, js.ToString());
}

protected override void OnInit(EventArgs e)
{
base.OnInit(e);

this.ClientValidationFunction = “DependantFieldValidateControl”;
}

protected override bool EvaluateIsValid()
{
bool retVal = true;

// Get the control value; return true if it is not found.
string controlValue = GetControlValidationValue(ControlToValidate);
if (controlValue != string.Empty)
{
string dependantValue = GetControlValidationValue(DependantControl);
if (dependantValue == string.Empty)
{
retVal = false;
Control c = Page.FindControl(DependantControl);
if (c != null)
{
if (c is TextBox)
{
TextBox tb = (TextBox)c;
tb.Enabled = true;
}
}
}
}

return retVal;
}
}
}
[/csharp]

Programming through interfaces

Here’s a quick example of how we do layer seperation through interfaces to make each layer testable. Although the tests run, the UI section is untested. Download file.

[csharp]
using System;
using System.Web;
using System.Web.UI;
using NMock;
using NUnit.Framework;
using Socialanimal.Example.Business;
using Socialanimal.Example.Business.Implementation;
using Socialanimal.Example.Core.Entities;
using Socialanimal.Example.Core.Interfaces;
using Socialanimal.Example.SqlDatabase;

namespace Socialanimal.Example.Core.Entities
{
public class Employee
{
public string Forename;
public string Surname;

public Employee(string forename, string surname)
{
this.Forename = forename;
this.Surname = surname;
}
}
}

namespace Socialanimal.Example.Core.Interfaces
{
public interface IFacade
{
Employee GetEmployee(string surname);
}

public interface IBusinessManager
{
Employee GetEmployee(string surname);
}

public interface IDatabaseProvider
{
Employee GetEmployee(string forename, string surname);
}
}

namespace Socialanimal.Example.Business
{
public class FacadeFactory
{
public IFacade CreateFacade()
{
IDatabaseProvider databaseProvider = new SqlDatabaseProvider(“server=localhost;database=test”);
IBusinessManager businessManager = new BusinessManager(databaseProvider);
IFacade facade = new Facade(businessManager);
return facade;
}
}

public class Facade : IFacade
{
private IBusinessManager businessManager;

public Facade(IBusinessManager businessManager)
{
this.businessManager = businessManager;
}

#region IFacade Members

public Employee GetEmployee(string surname)
{
return businessManager.GetEmployee(surname);
}

#endregion
}
}

namespace Socialanimal.Example.Business.Implementation
{
public class BusinessManager : IBusinessManager
{
private IDatabaseProvider databaseProvider;

public BusinessManager(IDatabaseProvider databaseProvider)
{
this.databaseProvider = databaseProvider;
}

#region IBusinessManager Members

public Employee GetEmployee(string surname)
{
if (surname == null)
{
throw new ArgumentNullException(“surname”);
}
return databaseProvider.GetEmployee(null, surname);
}

#endregion
}
}

namespace Socialanimal.Example.SqlDatabase
{
public class SqlDatabaseProvider : IDatabaseProvider
{
public SqlDatabaseProvider(string connectionString)
{
}

#region IDatabaseProvider Members

public Employee GetEmployee(string forename, string surname)
{
// Get from database
return new Employee(“john”, “doe”);
}

#endregion
}
}

namespace Socialanimal.Example.ClientWebSite
{
public class BasePage : Page
{
private IFacade Facade
{
get { return HttpContext.Current.Items[“Facade”] as IFacade; }
}

protected override void OnLoad(EventArgs e)
{
Employee employee = this.Facade.GetEmployee(“john”);
Response.Write(employee.Forename + employee.Surname);
base.OnLoad(e);
}
}

// global_asax
public class Global : HttpApplication
{
protected void Application_BeginRequest(Object sender, EventArgs e)
{
HttpContext.Current.Items[“Facade”] = new FacadeFactory().CreateFacade();
}
}
}

namespace Socialanimal.Example.Business.Tests
{
[TestFixture]
public class FacadeTest
{
[Test]
public void TestFacade()
{
// Create a mock IBusinessManager
DynamicMock mock = new DynamicMock(typeof (IBusinessManager)); // Create a proper Facade
Facade f = new Facade((IBusinessManager) mock.MockInstance); // Set expectations for this request
Employee expectedResult = new Employee(“john”, “smith”);
mock.ExpectAndReturn(“GetEmployee”, expectedResult, null, “smith”);
Employee actualResult = f.GetEmployee(“smith”);
Assert.AreEqual(expectedResult.Forename, actualResult.Forename);
Assert.AreEqual(expectedResult.Surname, actualResult.Surname);
mock.Verify();
}
}

[TestFixture]
public class BusinessManagerTest
{
[Test]
public void TestBusinessManager()
{
// Create a mock IDatabaseProvider
DynamicMock mock = new DynamicMock(typeof (IDatabaseProvider));
// Create a proper BusinessManager
BusinessManager bm = new BusinessManager((IDatabaseProvider) mock.MockInstance);
// Set expectations for this request
Employee expectedResult = new Employee(“john”, “smith”);
mock.ExpectAndReturn(“GetEmployee”, expectedResult, null, null, “smith”);
Employee actualResult = bm.GetEmployee(“smith”);
Assert.AreEqual(expectedResult.Forename, actualResult.Forename);
Assert.AreEqual(expectedResult.Surname, actualResult.Surname);
mock.Verify();
}

[Test]
public void TestGetEmployeeWithNullSurname()
{
// Create a mock IDatabaseProvider
DynamicMock mock = new DynamicMock(typeof (IDatabaseProvider));
try
{
// Create a proper BusinessManager
BusinessManager bm = new BusinessManager((IDatabaseProvider) mock.MockInstance);
bm.GetEmployee(null);
}
catch (ArgumentNullException ex)
{
Assert.AreEqual(“surname”, ex.ParamName);
}
finally
{
mock.Verify();
}
}
}
}
[/csharp]