個人檔案LiveMike部落格清單 工具 說明

LiveMike

Ping Mike... Request timed out.
4 December

Extension method to randomize the order of an IEnumerable<T>

I’ve needed this a couple of times recently, so maybe it’ll help someone else out:

public static IEnumerable<T> Randomize<T>(this IEnumerable<T> items)
{
    Random random = new Random();
    T[] itemArray = items.ToArray();
    int length = itemArray.Length;
    for (int i = 0; i < length; i++)
    {
        // Yield a random element in the array between i and length
        int nextItemIndex = random.Next(i, length);
        yield return itemArray[nextItemIndex];
        // Swap the item at index i with the yielded item 
        // this ensures it can't be yielded again
        T temp = itemArray[i];
        itemArray[i] = itemArray[nextItemIndex];
        itemArray[nextItemIndex] = temp;
    }
}

Note that the original enumerable has to be evaluated and stored in a local array, so it may not meet everyone’s needs.

Let me know if you have a better solution!

9 March

How to determine the version of IIS

It took me far too long to work this out; I needed to know whether or not it was safe to try and set the ManagedPipelineMode property on an AppPool, and I figured the best way to do it would be to check the current IIS version and if it was 7.0 or above. The code to get the current version is straightforward, once you know the names of the properties to read:

DirectoryEntry iisVersionCheck = new DirectoryEntry("IIS://localhost/W3SVC/Info");
int majorVersion = (int)iisVersionCheck.InvokeGet("MajorIIsVersionNumber");
int minorVersion = (int)iisVersionCheck.InvokeGet("MinorIIsVersionNumber");
15 December

Visual Studio 2008 SP1 Macro Recording

Recording a macro in Visual Studio 2008 become completely unusable since I installed SP1 – has anyone else noticed this? I’ll often use a temporary macro to perform some repetitive action to some code, and the only workaround I have at the moment is to use copy and paste it into Notepad++ (the best notepad replacement I’ve used) and use the macro recording facility there.

If you’ve been affected by this, I would encourage you to vote on the Microsoft Connect feedback I’ve logged: Feedback: Recording macros in Visual Studio 2008 SP1 is unusably slow.

Update: Looks like it's just my machine - I still haven't got to the bottom of this...

8 December

Creating MSBuild XSD schemas for your custom tasks

I’ve just uploaded a little utility onto our website here that should help those developers that write their own MSBuild tasks.

One of the nice features that’s a little hidden in Visual Studio is its ability to provide IntelliSense and auto-completion for XML files based on the schemas that they reference, as long as the reference XSDs are included in {ProgramFiles}\{MicrosoftVisualStudioFolder}\Xml\Schemas\1033. MSBuild scripts are XML, and as such it’s possible to provide information about custom tasks that you’ve written – the only problem is that whilst writing XSD schemas isn’t exactly difficult, it can be quite involved if there are a lot of tasks that you want to expose, and keeping them in sync with your code as it changes over time can be a pain.

Enter the LSS MSBuild Schema Generator, or MSBuildSchemaGen for short. This takes one or more assemblies that contain MSBuild tasks and generates the XSD and tasks reference file (i.e. the file that contains all the UsingTasks declarations) for them. If you’ve documented your tasks in code and compiled your DLL with XML documentation, MSBuildSchemaGen will even annotate the schema with your documentation, enabling even richer IntelliSense.

MSBuildSchemaGen can be used from a simple command line utility, or integrated into your build process with the provided MSBuild task. (yes, the XSD and tasks files are generated by MSBuildSchemagen itself!)

What’s really nice about all of this is that MSBuildSchemaGen is free for you to use right now, so get it from here and let me know how you get on.

4 June

ISA Server 2006 - Redirecting HTTP requests to HTTPS

For the past year or so we've had a problem with our web site that has meant that our secure areas are, well, not really that secure. The reason for this is that we had some code on the site that automatically redirected HTTP requests for secure pages to their HTTPS equivalent and HTTPS requests for non-secure pages to HTTP; under ISA Server 2006 these requests were just getting swallowed. (ISA Server 2004 was fine...)

Originally we found a couple of articles on the net that pointed us towards this MS support article: Link translation causes an endless loop when you use Web servers that redirect HTTP requests as HTTPS requests in ISA Server (catchy title...) On the surface this seemed to match exactly what we were seeing, unfortunately none of the solutions provided fixed our dilemma.

After spending too much time trying to fix it we gave up, but I'm happy to report that after years (literally) of not knowing what's going on, I can explain (mostly) what's actually happening, and how to fix it.

It turns out that the second approach in the article is very close to the actual solution – the key problem I was (unknowingly) facing was that the web site that ISA server was publishing was running on non-standard ports and in a different virtual directory to that which was being publicly exposed. This actually caused some very, very strange ISA server link translations when an HTTP redirect was returned.

Consider the following setup: ISA Server is listening on the standard HTTP and HTTPS ports (80 and 443) for the site www.lss.co.uk. Internally the site is hosted on the server internalserver, on a virtual directory called LssWeb in a web site listening on ports 8088 and 8089 for HTTP and HTTPS respectively. (e.g. http://www.lss.co.uk/Something.aspx maps logically to http://internalserver:8088/LssWeb/Something.aspx).

Now consider the following flow of information:

· Client makes a request to the page http://www.lss.co.uk/Secure/Default.aspx (port 80)

· ISA Server accepts the request and forwards it onto http://internalserver:8088/LssWeb/Secure/Default.aspx (port 8088). Note that as far as internalserver is concerned, the request is still for http://www.lss.co.uk/Secure/Default.aspx because the “Forward the original host header..” and “Requests appear to come from the original client” options are specified.

· The code in the page determines that the request should be operating over a secure channel, so performs a response redirect to https://www.lss.co.uk/Secure/Default.aspx

· Now the strange behaviour kicks in: before the response is sent to the client, ISA Server performs a link translation on it, converting https://www.lss.co.uk/Secure/Default.aspx to https://www.lss.co.uk:8088/LssWeb/Secure/Default.aspx. This is very odd for two reasons – firstly there is no need for it to add the :8088/LssWeb part and secondly the 8088 port is for the published server’s HTTP channel, not its HTTPS channel…

So, the resolution…

Instead of adding “do nothing” link translations for: (i.e. the solution I have seen elsewhere and, in part, in the article)

· http://www.lss.co.uk to http://www.lss.co.uk

· https://www.lss.co.uk to https://www.lss.co.uk

I have had to add link translation for:

· http://www.lss.co.uk:8089/LSSWeb to http://www.lss.co.uk

· https://www.lss.co.uk:8088/LSSWeb to https://www.lss.co.uk

Hopefully this will save someone else some pain - for what it's worth Fiddler came in very, very useful during the process of working out what was happening.

 
Pro C# 2008 and the .NET 3.5 Platform, Fourth Edition
C# 3.0 in a Nutshell: A Desktop Quick Reference (In a Nutshell (O'Reilly))