Tuesday, 2 December 2014

Use of "await" with WCF-lifetime dependency injection (SimpleInjector)

Found an issue where SimpleInjector WCF-lifetime dependency-injection is broken by asynchronous methods.  The code in question is as follows.  (The deferred construction is performed because the legacy repository is not required by any of the other methods on the class)

        public async Task<UnitQueryResult[]> GetUnitsByVinAsync(string vin)
        {
            return await ExecuteFaultHandledOperation(async () => {
                var result = (await _factory
                    .Build<ISalesForceRepository>()
                    .GetUnitWithReferencesByVin(vin)) ?? new UnitQueryResult[0];

                if (_settings.IsLegacyUnitLookupEnabledForSalesForce)
                {
                    result = result.Concat(
                        (await _factory.Build<ISvrLegacyRepository>()
                            .GetUnitWithReferencesByVin(vin)) ??
                                new UnitQueryResult[0]).ToArray();
                }
                return result;
            });
        }

The exception raised by the yellow code when called from a WCF method is:

The registered delegate for type ISvrLegacyRepository threw an exception.
The ISvrLegacyRepository is registered as 'WCF Operation' lifestyle, but
the instance is requested outside the context of a WCF Operation.

The reason is clear but worrying … by the time the method on the legacy repository is called, the original thread (with its context) has been lost due to the prior await a method on the other repository … so a workaround would be to instantiate the legacy repository before the first await – for example:

        public async Task<UnitQueryResult[]> GetUnitsByVinAsync(string vin)
        {
            return await ExecuteFaultHandledOperation(async () => {
                var legacyRepository = _settings.IsLegacyUnitLookupEnabledForSalesForce?
                    _factory.Build<ISvrLegacyRepository>():
                    null;

                var result = (await _factory
                    .Build<ISalesForceRepository>()
                    .GetUnitWithReferencesByVin(vin)) ?? new UnitQueryResult[0];

                if (legacyRepository != null)
                {
                    result = result.Concat(
                        (await legacyRepository.GetUnitWithReferencesByVin(vin)) ??
                        new UnitQueryResult[0]).ToArray();
                }
                return result;
            });
        }

However, that makes for fragile code, because it depends on the whole call-chain before the use of the factory: if any method in the call-stack prior to a use of the factory to instantiate a WCF-lifetime object has already performed an await, the WCF context is unavailable (we’re now running on a different thread, even though the WCF context is still alive) and instantiation via the factory will fail.  And that obviously won’t be picked up at unit-test L

So, another clear reason to strongly prefer all dependencies to be resolved by the constructor wherever possible.

Sunday, 3 March 2013

TypeScript with Visual Studio 2010 (VS2010) on Windows XP

I've been watching TypeScript for a while and would desperately love to use it, but whilst my home machine is Windows 7 with VS2012, my client-supplied work laptop is Windows XP with VS2010 (for reasons related to supporting legacy software).

TypeScript is open-source so there's no reason that I shouldn't be able to integrate it with VS2010 but Microsoft wish to compel their users to move to VS2012 so don't support VS2010 with their installer for it.

The Obvious Hacks Don't Work ...

The first thing I tried was to run the MSI for VS2012 on XP anyway - that didn't work because the MSI required a version of the installer not present on XP - dead end there as I can't upgrade the installer on my client's laptop even if a later version for XP is available.

The next avenue was to unpack the files in the MSI using 7zip ... in there I find the VSIX and the other installable components: the VSIX installed fine into VS2010 but didn't work well when it came to adding in .ts files even if I installed the TypeScript compiler manually. Worse, though: the license explicitly says that we're not permitted to work around technical limitations of the software - and using unlicenced software would not go down well with my client.

... So Let's Do It Cleanly (and Legally).

First install the TypeScript compiler standalone:
  • Go to NodeJS and click Install, following the very brief process to install it.
  • Open a normal command-prompt in XP and run:  npm install -g typescript 
A quick test verified that the compiler (tsc) runs up fine on Windows XP.
Now to integrate with VS2010 so that saving a .ts file automatically compiles it to a dependent .js file.
  • Ensure the VS2010 SP1 SDK is installed on VS2010.
  • Take a look at the Microsoft Single-File-Generator sample & docs.
  • Create an Extensibility project to generate a Visual Studio package.
  • Add a class which implements
    Microsoft.VisualStudio.Shell.Interop.IVsSingleFileGenerator.
  • Make the DefaultExtension method return .js.
  • Make the Generate method call out to tsc.cmd to get the compiled content.
  • Add attributes to make the class show as a custom tool.
  • Add registry entry to ensure .ts is associated with the custom tool.
That's pretty straightforward and I had it working quickly.  Current limitations:

  • Performance: it takes 2-3 seconds to save a file.
  • Productivity: no intellisense yet - need to research how to add that in.
  • Packaging: currently an extension with manual install - must create a VSIX.
  • Presentation: the icon for the .ts file type is currently the vanilla file icon.
And I suspect it probably works in VS2008 too - though I no-longer have a copy :)

There's probably a better way, but at least I have something ... will upload the project here when I've sorted out the intellisense and packaging - and maybe the performance as I believe I should be able to get it down to 1 second.



Monday, 6 February 2012

CSS Specificity Quiz

Did this quiz on CSS specificy ... and the Gnome scored 100%, so is very pleased.
If you don't get 100%, try reading this tutorial ... simple and straightforward.

SQL Server distributed transactions

SQL Server distributed transactions are a little more restrictive than you might think.  Moved an app from 2 database on the same server to the live environment where the two databases were on separate servers.  First had to configure DTS on both machines (setting the security correctly for network distribution).  Then had to remove the explicit nested transaction from the stored procedure which was doing the distributed work.  Then had to change the remote table to have a timestamp field else the cursor wouldn't compile any more.  Its a lot more straightforward in Oracle!

Friday, 3 February 2012

Dynamic in-line scripts in IE8

If you add an in-line JavaScript script to an HTML page in IE8 using document.write() during initial load, it doesn't execute: if such script isn't in-line (i.e. has a src element) then everything behaves fine.  As IE (various versions) have odd behaviour with dynamic scripts (whether or not written using document.write) this isn't a complete surprise - but it is inconvenient!

Thursday, 2 February 2012

Refreshing LINQ

Today I learned that you can force an update of a record from the database using LINQ, where it has been changed by another user.  Just use the Refresh method of the DataContext.

Wednesday, 1 February 2012

NLog - auto-reconfiguration and bundling logs for email.

Today I learned that NLog normally needs to be told to reload its configuration file when it changes (thought automatic reloading was the default).  To enable automatic reloading, add autoReload="true" to the <nlog> tag.  Documentation here.


Also learned that NLog buffering is implemented using the BufferingWrapper target which means I don't need to spam logs any more.