BM-Bloggers

The blogs of Black Marble staff

Site Policies and FBA in SharePoint: Update

My apologies to Craig, who posted a comment to my earlier post about our FBA problems and I didn't notice until today.

To update you all on the situation, the fault is still with Microsoft and I have not yet received a hotfix.

However, for anybody considering FBA in their deployment, I would not let this issue stop you. There are two reasons I say that:

  1. Normally with FBA you would extend the web application in question, having both FBA and Windows authentication available on the same content via different URLs. This makes your life easier with things like indexing and management.
  2. The workaround I detailed is a good temporary solution to the problem with only minimal impact on the user experience (in that certain options are offered which may not work too well in Office when using FBA).

Hopefully this answer's Craig's question and assuages any doubts about the wisdom of deploying FBA in your SharePoint solution.

WPF Performance

When I was at DDS a nice chap asked me if I knew about WPF performance and the answer was no but I did do some digging and just for the record this is what I found , comments welcome.

Perf in WPF

http://msdn.microsoft.com/en-us/library/aa970683.aspx

Perf tools for WPF

http://msdn.microsoft.com/en-us/library/aa969767.aspx

the most important bit could be .NET 3.5 SP1

http://blogs.msdn.com/jgoldb/default.aspx

you need to make sure that the problem is not poor code performance ( your code )

http://blogs.msdn.com/timothyc/archive/2006/02/28/540291.aspx

 

b.

'Unable to find control' when programmatically adding ASP.NET validation controls

I have been building a webpart that needs client side validation. I kept getting the error:

"Unable to find control id txtNotes referenced by the 'ControlToValidate' property"

Now most of the posts say just use the command to get the 'real' ID at runtime

this.rfvNotes.ControlToValidate = this.txtNotes.ClientID;

But this did not work, in the end the form I found worked was:

protected override void OnInit(EventArgs e)
    {
        base.OnInit(e);
        this.txtNotes.ID = "txtNotes";
        this.rfvNotes.ControlToValidate = this.txtNotes.ID;
        this.rfvNotes.Enabled = true;
        this.rfvNotes.Text = "* Required";
    }

The key step was to set the textbox ID manually, it seems that if this is not done it is the root of the error.

Life with a Diamond: nearly two weeks on

I said I'd post again once I'd had the Diamond a little while. It's now been two weeks and I can honestly say I'm completely happy with it. Battery life for me is fine - I charge it about every three days and it chugs along with exchange push pretty much constantly. I am quite comfortable with the soft keyboard and I can honestly say I haven't noticed any issues with the speed of the device either.

I don't usually go for silly little apps on my phone, but I couldn't resist this one. It shows just what you can do with the accelerometer. The force is strong in this one!

Running Fitnesse.NET tests using MSTest

Update 29 Mar 2010 - See this post for some updated usage notes 

I have been looking at Fitnesse.NET for a while; if you have not come across this testing tool I cannot recommend Gojko Adzic book highly enough; an excellent real world introduction to Fitnesse.NET.

For me, the problem with Fitnesse is that it's WIKI architecture does not lend itself to working within our Team Foundation Server based development model. However, as I am not really looking for a tool to allow Business Analysts to edit a central repository of tests the WIKI was not that important; so I have been looking at a way to store the Fitnesse tests inside a Visual Studio solution, so they are managed like a unit test.

The first step was to get my head round using Fitnesse without a WIKI. This is achieved using FolderRunner,exe that ships as part of Fitnesse.NET. This allows you to define a test as a HTML file as opposed to a WIKI page. Firstly I thought you could just copy the relevant contents.txt page out of the WIKI structure, but this does not work as this file holds the test not as a HTML table, as required, but in the WIKIs own format using | characters to define the table cells. So you have to create the test file containing the Fitnesse tables using your HTML editor of choice. Once you have done this you run the test using the following command line.

..\fitnesse\dotnet2\FolderRunner.exe -i userstory1.htm -a MyAssembly.dll -o results

A HTML results file ends up in the results directory and you get a simple results test count on the console.

All this is very good but how can you bolt this into Visual Studio? After a bit of thought I decided that the easiest option was to put the Fitnesse calls within a wrapper unit test. I chose MSTest as I was aiming to run the final solution within TFS Build (but any type if unit testing framework such as nUnit or mbUnit would have done).

Next I decided to make the required calls to run the tests in C#, calling the methods in the Fitnesse DLLs. This was as opposed to trying to shell out and run the FolderRunner.exe.

The easiest way to find the correct calls was to use Reflector to have a look at the code in the FolderRunner.exe (and the other Fit assemblies). After a brief splunk around I found the calls were fairly simple, so this is the process I ended up with to run the tests via MSTest:

  • I started with a solution that contains an application assembly and an second assembly that had all the methods required for the Fit tests (and made sure it all worked via the WIKI and/or command line FolderRunner)
  • Next I added a test project to the solution
  • In the test project I add a reference to the assembly that contains fit test methods and also the fit.dll. I had some problems here that when I ran the test, I got a The location of the file or directory '(path omitted)\fit.dll' is not trusted. error. If you get this error follow the process on Don Felker's blog to fix it This blog post seems to have been removed, in summary the post said:
    • If you download a DLL from the Internet, or get it in an email or where ever and you saved it to your disk (including a DLL in a zip too) it has some extra info attached to it called an "AES" file.
    • To fix this annoying issue, go to the DLL in Windows Explorer, right click to view the properties and then click the "Unblock" button at the bottom of the General panel

  • Add an HTML file to the Test Project and in it create the Fit test tables.
  • Set the HTML file properties so it is copied to the output directory.
  • Create a new Test Method to run all the tests in a the HTML file as shown below (obviously you will need to make sure the paths are right to the HTML files and assemblies for your project).

[TestMethod]
public void RunFitnessTests()
{
   fit.Runner.FolderRunner runner = new    fit.Runner.FolderRunner(new fit.Runner.ConsoleReporter());
   var errorCount = runner.Run(new string[] {
       "-i",@"userstory1.htm",
       "-a",@"MyAssembly.dll",
       "-o",@"results"
});
    Assert.AreEqual(0, errorCount,runner.Results);
}

  • So now you can make sure this test works using TestDriven.NET to run this test, this checks the test works when the application is built to the standard bin\debug directory.
  • However this does not mean it will work with MSTest under the Visual Studio test runner. This is because, by default, the HTML file that holds the test will not be deployed to the TestResults directory (also the actual application assembly under test will not be copied). This is critical, as you have to be careful here, as if the HTML file is missing you get a false success. The Runner.Run method will return 0 as no test failed (as there were none defined) so the assert passes. To get round this you need to add the HTML file (and any other files required) to the list of files to deploy prior to testing. This is done by editing the deployment file list via the menu option Test | Edit Test Run Configuration | Deployment tab. An option to guard against this issue is to add an extra assert to make sure at least some tests were run and we don't have four zeros in the results string, a bit of RegEx will do (this line is not in the sample project by the way)
           Assert.AreEqual(false,Regex.IsMatch(runner.Results, "^0.+?0.+?0.+?0.+?$"),"No tests appear to have been run");

  • Once this is all done you can run the test via the Visual Studio Test menu option and you should see the test run and get a simple pass or fail result with a count of any failures in the error message. (Another possible option would be a make better use of the detailed HTML results file, at present we just use the simple result string for test results details)

So where do we end up?  I think we have a workable solution. We can run Fitnesse tests as easily as any unit test, and as with unit tests the Fitnesse test files are under TFS source control and kept in sync with the application they test. All without the need for the WIKI.

I have packaged up a sample of this solution and posted to this server.

Workflow and SQL Error: Update

I posted last week about a couple of issues we were experiencing with SharePoint. I made some traction on the Workflow History issue at the end of last week and the revelation was pretty far-reaching, so I'm posting again.

It turns out that the stuff I said about systemupdate was wrong... up to a point.

There is a bug with systemupdate and triggering events, but it's not the one we thought it was! It turns out that the behaviour we are seeing is correct - systemupdate is supposed to trigger events, just not update things like the modified by and last updated columns. It's actually the behaviour within a workflow which is at fault, in that events aren't being triggered when they should be.

I had a chat with our developers about this and they told me that there are plenty of articles on the web suggesting that systemupdate is the way to update an item in a list without triggering events. Don't do it! I was told by Microsoft that whilst the fault is not high on the list because there is a workaround (which I will list in a moment), it will be fixed. At that point, anybody who is using systemupdate expecting events not to fire will get a shock.

The MSDN documentation for system update is pretty clear:

When you implement the SystemUpdate method, events are triggered and the modifications are reported in the Change and Audit logs, but alerts are not sent and properties are not demoted into documents.

The explanation as to why events don't fire is:

When you used in other places such as windows/console app, another workflow or webparts, you are not seeing the event trigger the workflow, this is due to the Workflow runs on separate threads from the main thread, so we cannot fire up the workflow and simply quit. Quitting an app before the async worker threads are finished causes those threads to simply abort, and in the case of workflow, nothing will appear to have happened.

And the fix:

Currently, all standalone applications must call spsite.workflowmanager.Dispose(). This call waits for the threads to complete and causes workflow to go into an orderly shutdown.

And the solution to the problem of wanting to not trigger events? Well, it looks like the method I described in my earlier post is the way to go.