But it works on my PC!

The random thoughts of Richard Fennell on technology and software development

Problems with uplink on an 8 port Netgear Gigabit switch

All the ports on the Netgear GS608 I think are meant to be auto speed and uplink sensing, I have found this not to be true. I had the 1Gb uplink to our central switches in Port 8 and a 100Mb Ethernet workstation in port 2 could not get an IP address via DHCP. When I moved the uplink to Port 1 it all leapt into life. Interestingly other 1Gb PCs in other ports had no problem with the uplink in either port 1 or 8.

So my tip is put you uplink in port 1 on a Netgear switch to avoid problems with auto sensing.

.NET Framework 3.5 SP1 issue on Windows SharePoint Services v2.0

If you apply the TFS2008 SP1 to a system that has been upgraded from TFS 2005, but the WSS was not upgraded from 2.0 to 3.0 you can get a problem that you cannot access the SharePoint portal sites due to WebPart load errors (you get an Event ID: 1000 error in the Windows event logs). This is because the TFS 2008 SP1 installs .NET framework 3.5 SP1 which causes some problems for WSS 2.0. Note this is not usually a problem for new installs of TFS 2008 as these use WSS 3.0 by default, but the upgrade of TFS from 2005 to 2008 does not force the upgrade of WSS 2.0 to 3.0 so sites that upgraded are susceptible.

Most of the blog posts suggest a removal of .NET 3.5 and reinstall of 2.0 with service packs, this is not an option for a TFS 2008 installation. Luckily there is a solution, the .NET framework family update. Once these patches are installed for the historic versions of .NET all seems OK

Thanks to Wes MacDonald for pointing me at this fix, saved me no end of headaches

0x800106ba Windows Defender error in Windows Vista

I was installing a new PC for a friend yesterday; after using the Easy Transfer Wizard (first time I used this and I can heartily recommend) to move their settings from their old XP system to their new Vista one I got the 0x800106ba Windows Defender error on start-up. Now there is a lot of frankly useless comments on this error on various forums, strange as the solution is simple. I suspect this is down to this issue being predominantly a problem that hits home user who are not a familiar with the internal workings of services etc. in Windows.

Anyway the solution is make sure the Defender service is set to auto-start. You get the error if it has not been started when Windows check to see if it is running, I assume as part of the security centre checks.

It is not that the forums are really wrong, they usually suggest a reinstall of Defender (which will reset the service start-up), but it is just that this is not easy to achieve on Vista where Defender is backed into the operating system not as separate install as it was in Vista.

29109 error when installing the quiescence GDR patch for TFS 2005

Whilst upgrading a single server TFS 2005 to a dual server 2008 install I hit a problem. I had installed the new 2005 Data Tier (DT) and patched it without issue. However then I tried to apply the patch VS80-KB19156-v2-x86, the Quiescence GDR patch, on the Application Tier (AT) I got the 29109 error: SQL Reporting Services configuration encountered an unknown problem. A search on the web found this is a common issue usually fixed by repeated retries! This did not work for me.

After much fiddling, I started again and cleaned down both the DT and AT. This time I made one change from the process detailed in the TFS dual server installation walkthrough – I DID NOT patch the SQL 2005 instance of Reporting Services on the AT prior to installing TFS. This time the TFS patches applied OK, I then patched SQL at the end of the installation process to bring it in line with the DT SQL patch level.

This would suggest the problem is that the TFS 2005 patches are checking for something that was set in a default SQL 2005 install but not present in one that is patched to SP3.

Anyway hope my experience saves you some time.

TFS Sharepoint Extensions on a Load Balanced Sharepoint farm

I posted yesterday about problem creating a new team project if you had missing templates on your Sharepoint server. This problem could of course be avoided if you had installed the TFS Sharepoint Extensions onto your Sharepoint server as your are meant to. However, as I have discovered it is not that easy to do if your chosen  Sharepoint system has network load balanced front ends.

The problem is that Sharepoint will replicate your MSFAGILE30.STP template between the various servers, but it will not move other TFS artefacts such as the TFSREDIRECT.ASPX in the 12 hive or setting to point to the reporting service instance in the registry. To add these other items you need to install the extensions an then run the TFSConfigwss.exe tool to edit the registry. The problem is the Extensions MSI will not complete if it detects the STP already in place (which as I said will that have been replicated by Sharepoint). The only solution I found was to cheat a bit:

  1. Run the Extensions MSI until you get the warning dialog it cannot complete
  2. In c:\program files copy the 'Team Foundation Server 2008 Sharepoint Extensions x64 Power Tool' directory
  3. Let the MSI finish, it will remove the directory, but you have a copy with the TFSconfigwss.exe tool which is probably the only thing you need.
  4. Run TFSConfigwss.exe to setup the registry.

Or you could just copy the files you need from your original Sharepoint server where you managed to install the Extensions correctly

TF30227 error when creating team projects on TFS 2008

Historically we have used the eScrum process template for our TFS team projects. However, with a view to the TFS 2010 future we have decided to moved back to the MSF Agile template. We used eScrum to provide an easy to use web based project dashboard; we now think that we can achieve the same or better in TFS 2010 using Excel’s enhanced links to TFS and Excel Services in Sharepoint.

So when I had to create a new team project today I decided to use the TFS 2008 "MSF for Agile Software Development - v4.2" template, to hopefully ease any upgrade issues. The problem was when I tried to create the team project I got the error TF30227, if I looked in the detailed log I saw:

Event Description: TF30162: Task "SharePointPortal" from Group "Portal" failed
Exception Type: Microsoft.TeamFoundation.Client.PcwException
Exception Message: TF30272: Template not found on the server

(Note that as is common with TFS the main error reported hides another error code.)

The problem was exactly as the error says, the template was missing on our central Sharepoint farm. We have been through a number of Sharepoint upgrades and relocation of our portal sites. This had meant that the TFS templates had to be reinstalled manually, this was done correctly for the eScrum template but a mistake was made for the MSF Agile one. We had installed the template with the command

Stsadm -o addtemplate -filename MSFAgile30.stp -title VSTS_MSFAgile30

when it should have been

Stsadm -o addtemplate -filename MSFAgile30.stp -title VSTS_MSFAgile

as TFS looks for a template call VSTS_MSFAgile not one called VSTS_MSFAgile30. Once this was correct the new project could be created.

TF255048 Error when installing TFS 2010 beta 1

When you setup a dual or multi server TFS installation you need to specify the location of the OLAP Analysis service instance that will be used for the reporting warehouse. As with much of the TFS installation and configuration process there is a test button to confirm your setting will work, these are always worth pressing. If there is a problem you could get a TF255048 error, as the text says this hints the server cannot be found or you have no rights to access it, which may well be the case.

image

Well there is another thing to consider, the firewall on the SQL server. On my default 2008 SQL install the firewall was not opened to allow incoming connections to the OLAP service. Once the TCP Port 2383 was opened to incoming traffic the test passed and I could move onto the next stage of the configuration

Getting "failed to start" with a SharePoint workflow

I have been playing around with some workflow code for a demo I am doing. This has meant creating and deleting a workflow project as I refine the demo. Whilst going through the process of a delete and recreate of the workflow (using the same name for the project/workflow but creating a new project from the VS file menu) I hit the problem that when the new version of the workflow was run I got a “failed to start” error.

After checking the SharePoint log in the 12 hive I found that workflow runtime was trying to load the code beside assembly using the old assembly name name/public key, which obviously it could not fine as the new version was in the GAC. Once I correct and redeployed the workflow.xml file (with the old PublicKeyToken for the CodeBesideAssembly) all was OK

Misleading error message adding a user on Windows 2008

Today I was setting up a new development VPC for SharePoint. When I tried to add a new user via the AD tools wizard I got the error

"Windows cannot set the password for [new user], network path was not found"

Forums suggest the issue is DNS resolution related, but for me it turned out to be the simple fact the password I was using did not meet the domains minimum requirements.

Not the most helpful message in the world.

Testing access attributes on the Microsoft MVC framework

The MVC framework provides an excellent way to create a testable web site. In fact when you create a new MVC project you are given the option to create an associated test project that contains MSTEST unit tests for all the sample methods in the MVC Controller class; which you can add to as you go along.

Recently whilst working on an MVC project I noticed that the one area that this model does not let you test is that of access control. MVC uses attributes on Controller methods to limit who can access what e.g.

[Authorize]
public ActionResult ChangePassword()
{

ViewData["PasswordLength"] = MembershipService.MinPasswordLength;

return View();
}

These attributes are used by the MVC routing engine to decide if a method can be called or not. The problem is these attributes are not honoured by the unit tests as they call the controller methods directly not via the routing engine.

This raised a concern for me, if I am setting access controller via attributes how can I make sure I set the right attribute on the right methods? This is important for regression testing. This issue has also been discussed on StackOverflow. An alternative is to not use this attribute security model, but to make the security checks within the controller methods programmatically. For some this might be the correct solution, but did not see right for me. If you are going to use a framework, try to use it as it was intended.

I therefore needed a way to honour the attributes whilst testing. One option would be to write code on the unit tests to check the attributes, but this was more reflection than I wanted to do at this time. So I thought of using Ivonna the Typemock add-in. This allows you to load a web page and process it via a mocked web delivery framework.

Now this plan seemed simple but as soon as I started I found it was more complex than expected. I hit some problem as I will detail as I go along. I must say thanks to Artem Smirnov who wrote Ivonna for all his help in sorting out the issues I was having, both in my usage/understanding and fixing bugs. I could not have written this post without his help.

Preparation- My Assumptions

So for this post lets assume the following

  • You create a new MVC project so you have the basic sample MVC web site.
  • You allow Visual Studio to also create a new Test Project for the MVC project
  • You have Typemock Isolator 5.3.0
  • You have Ivonna 1.2.7 what includes Artem’s “experimental support for MVC". (1.2.6.is OK for all bar the form submission example, see comments below)

GOTT’A 1: If you are writing tests using MSTEST with Ivonna you have to set the Test Project output directory to the bin directory of the MVC project (via Test Project’s properties, build tab)  e.g. ..\MvcApplication1\bin. This is needed so that Ivonna can find the page classes to load.

image .

Submitting a Form

 

The basic way MVC works is that forms get POSTed to the controller. So this was where I started, I think the comments in the code explain what is being done

[TestMethod, RunOnWeb(true)]
public void LogOn_FormContainingValidLoggedDetails_RedirectedToChangePasswordView()
{

// Arrange
// Fake out the membership service using Typemock, allow call through to the original
// class so that we don't need to fake out all the methods that will be called
var fakeMembershipService = Isolate.Fake.Instance<AccountMembershipService>(Members.CallOriginal);
// set that the Validate method will return true with the correct UID and password
Isolate.WhenCalled(() => fakeMembershipService.ValidateUser("testid", "goodpass")).WillReturn(true);

// Intercept the next call to the AccountController and slip in the faked service
Isolate.Swap.NextInstance<AccountMembershipService>().With(fakeMembershipService);

// Create the Ivonna test session
var session = new TestSession();

// Create the POST request, setting the AutoRedirect flag so that it does not
// actually do the redirect at the end of processing. We just check where it would
// redirect if we let it, this avoids an extra round trip
WebRequest request = new WebRequest(@"/Account/LogOn", "POST", null, null) { AutoRedirect = false };

// Fill in the form values with all the fields that would be sent on the Logon view submission
request.FormValues.Add("username", "testid");
request.FormValues.Add("password", "goodPass");
request.FormValues.Add("rememberMe", false.ToString());
request.FormValues.Add("returnUrl", @"/Account/ChangePassword");

// Act
// Process the request
WebResponse response = session.ProcessRequest(request);

// Assert
// Check that we have been redirected to the correct page
Assert.AreEqual(@"/Account/ChangePassword", response.RedirectLocation);
}

GOTT’A 2: If you are using the current shipping version of Ivonna (1.2.6 at the time of writing) this test will fail. There is a problem with form handling code so you need Artem’s “experimental support for MVC" release this addresses a problem with the form handling code (Updated 23 May 2009 - now shipped in 1.2.7). However as you will see from my comments below this problem might not as critical as I first thought.

This test is all well and good, but is it useful? All it proves is that Microsoft wrote their logon code correctly. They provide unit tests for this in the MVC source if you are interested. In my opinion if you are using a framework like you need to take it on trust and assume it’s core functions are tested prior to its publication (OK there will be bugs, but as a general point I think this holds true)

So I would say it is good you can do this test, but in practice I don’t think I would bother. If I want to test the functionality of methods in my controller class I should just use standard unit tests as in the MVC samples. I should test the functionality from separately from the security.

Checking for page differences between an anonymous user and an authenticated one

What I do want to test that a page is rendering correctly depending if I am logged in or not. The following two tests show how to do this with the home page of the default MVC sample.

I would draw your attention to how ‘clean’ the test is. Ivonna (and hence Typemock) is doing all the heavy lifting behind the scenes.

[TestMethod, RunOnWeb]
public void Home_IsNotLoggedOn_SeeLogonButton()
{
// Arrange
// create the Ivonna test session
var session = new TestSession();
// create the request for the page we want
WebRequest request = new WebRequest(@"/");
// set no user

// Act
WebResponse response = session.ProcessRequest(request);

// Assert
Assert.AreEqual(@"/", response.Url);
// we can check some html items on the form
Assert.IsTrue(response.BodyAsString.Contains("<h2>Welcome to ASP.NET MVC!</h2>"));
Assert.IsTrue(response.BodyAsString.Contains("[ <a href=\"/Account/LogOn\">Log On</a> ]"));
}


[TestMethod, RunOnWeb]
public void Home_IsLoggedOn_SeeLogOffButton()
{
// Arrange
// create the Ivonna test session
var session = new TestSession();
// create the request for the page we want
WebRequest request = new WebRequest(@"/");
// Pass in a user and the frame does the rest
request.User = new System.Security.Principal.GenericPrincipal(new System.Security.Principal.GenericIdentity("testid"), null);

// Act
WebResponse response = session.ProcessRequest(request);

// Assert
Assert.AreEqual(@"/", response.Url);
// we can check some html items on the form
Assert.IsTrue(response.BodyAsString.Contains("<h2>Welcome to ASP.NET MVC!</h2>"));
Assert.IsTrue(response.BodyAsString.Contains("Welcome <b>testid</b>!"));
Assert.IsTrue(response.BodyAsString.Contains("[ <a href=\"/Account/LogOff\">Log Off</a> ]"));
}

GOTT’A 3: When using classic ASP.NET Ivonna treats the returned page as an object and you have a collection of extension methods to help navigate the page checking control values etc. As MVC just returns HTML to the browser at this time you have to check for values by string matching in the response.BodyAsString (or you could use some xPath or Regular Expression)

TIP: As I am sure you will be looking at HTML from response.BodyAsString property in the debugger at some point, using the HTML visualizer in the Visual Studio Auto/Local Window is a great help. Select the HTML visualizer (as opposed to the default string one) by using the drop down selector in the window or tool trip debug prompt, and you can see the page as if in a browser for a quick manual visual test.

Checking who can see a page

Where I started with this project was wanting to test page access i.e. can user A get to Page B? We are now in a position to achieve this. The following two tests check that an authenticated user can reach a secured page, and that a non authenticated one is redirected to the logon page. Again note the clean easy to read syntax.

[TestMethod, RunOnWeb]
public void ShowChangePassword_NotAuthenticated_RedirectToLogonView()
{
// Arrange
var session = new TestSession();
var request = new WebRequest(@"/Account/ChangePassword");
// we set no value for the request.User property

// Act
var response = session.ProcessRequest(request);

// Assert
// redirected to the logon page
Assert.AreEqual(@"Account/LogOn?ReturnUrl=%2fAccount%2fChangePassword", response.Url);
}

[TestMethod, RunOnWeb]
public void ShowChangePassword_Authenticated_ShowChangePasswordView()
{
// Arrange
var session = new TestSession();
var request = new WebRequest(@"/Account/ChangePassword");
// just pass in a user, using the fact that Ivonna has a built-in authentication faking
request.User = new System.Security.Principal.GenericPrincipal(new System.Security.Principal.GenericIdentity("testid"), null);

// Act
var response = session.ProcessRequest(request);

// Assert
Assert.AreEqual(@"/Account/ChangePassword", response.Url);
// we can also check the page content, but probably don't need to in this case
Assert.IsTrue(response.BodyAsString.Contains("Use the form below to change your password."));
Assert.IsTrue(response.BodyAsString.Contains("Welcome <b>testid</b>!"));
Assert.IsTrue(response.BodyAsString.Contains("[ <a href=\"/Account/LogOff\">Log Off</a> ]"));

}

The above tests assume that the ChangePassword page is just protected with a simple [Authorize] attribute, so a user is authenticated or not. However, it is easy to modify the test so that it handles roles. If the same page was protected with the attribute [Authorize(Roles= "Staff")], the test simply becomes

[TestMethod, RunOnWeb]
public void ShowStaffOnlyChangePassword_Authenticated_ShowChangePasswordView()
{
// Arrange
var session = new TestSession();
var request = new WebRequest(@"/Account/ChangePassword");
// just pass in a user, using the fact that Ivonna has a built-in authentication faking
request.User = new System.Security.Principal.GenericPrincipal(new System.Security.Principal.GenericIdentity("testid") , new string[] {"Staff"});

// Act
var response = session.ProcessRequest(request);

// Assert
Assert.AreEqual(@"/Account/ChangePassword", response.Url);
// we can also check the page content, but probably don't need to in this case
Assert.IsTrue(response.BodyAsString.Contains("Use the form below to change your password."));
Assert.IsTrue(response.BodyAsString.Contains("Welcome <b>testid</b>!"));
Assert.IsTrue(response.BodyAsString.Contains("[ <a href=\"/Account/LogOff\">Log Off</a> ]"));

}

Should I use this way to test MVC?

If you are worried that developers are not applying (or are refactoring away) the security attributes on your MVC controllers this technique for testing is well worth a look.It provides a way of writing simple, readable tests for the MVC security model.

It is fair to say that these tests are not fast, the basic setup of a single test run takes about 30 seconds (but subsequent test in a batch are far faster) so you are not going to run them all the time in a TDD style. I think you should consider them as integration tests and run them as part of you continuous integration process. I think it is a more robust means of testing security than recorder based Web Tests. All thanks to Artem from producing such a useful Typemock add-in.