Showing posts with label Quickies. Show all posts
Showing posts with label Quickies. Show all posts

Thursday, June 11, 2020

Thursday Quickie: Fixing NCrunch for Azure Functions

So I'm a big fan of NCrunch - Remco Mulder's continuous testing plug-in for Visual Studio.

I'm not a true adherent to TDD, so I find it really helps in ensuring that you've got proper coverage of my code, particularly of conditionals, and pushes me to write more tests generally. All good.

But it doesn't (yet) support Azure Functions projects properly - the post-build oddities of Functions project just don't play well with NCrunch.

However, there's a pretty easy fix that seems to work the majority of the time.

Just add the following to the Azure Function project .csproj file:

<PropertyGroup Condition="'$(NCrunch)' == '1'">  
    <ExcludeRestorePackageImports>true</ExcludeRestorePackageImports>
</PropertyGroup>

Pretty simple. 

Thanks have to go to Clement on the NCrunch Forums for this fix.





Tuesday, October 22, 2019

Tuesday Quickie: ILogger in Azure Functions done right

So we had a discussion at work yesterday about how to use ILogger from Microsoft.Extensions.Logging in our Azure Functions v2 projects.

All the samples have a hang-over from the v1 days where the function method takes an ILogger as a method dependency. I asserted that a cleaner way would be to have ILogger as a class-level dependency, injected via the constructor.

The only problem was that it didn't work - the MSDI wasn't resolving ILogger when constructing our functions class.

namespace MyFunctionApp
{
    public class MyFunctionClass
    {
        private readonly ILogger logger;

        // DOESN'T WORK!
        public MyFunctionClass(ILogger logger)
        {
              this.logger = logger;
        }

        [FunctionName("MyFunctionName")]
        public async Task<IActionResult> MyFunctionMethod(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)]
            HttpRequest req,
            ILogger log) // WORKS!
       {
           ...
       }
    }
}

A bit of a proof-of-concept later and I found the trick - use ILogger<T> as the constructor dependency - where T is the class that owns the method.!

    public class MyFunctionClass
    {
        private readonly ILogger logger;

        // WORKS!
        public MyFunctionClass(ILogger<MyFunctionClass> logger)
        {
              this.logger = logger;
        }
        ...
    }

But why? 

What's going on is that the Azure Functions v2 runtime sets up the DI to serve an ILogger when method-injection is used, but not for constructor injection. For constructor injection the runtime has set the DI to serve up only ILogger<T>.

Looking at the differences between the loggers that the two DI methods return, we can actually make sense of why the behaviours are different.

The ILogger returned for method injection is configured with the category "Function.MyFunctionName.User".

The ILogger<T> returned for constructor injection, however, gets a category of "MyFunctionApp.MyFunctionClass" instead. 

The Azure Functions v2 runtime is building a logger based on the FunctionName attribute for method injection - it's a special case hangover from v1!

So to get hold of an ILogger in your function class using constructor injection, you just need to ask for an ILogger<MyClass> instead! 

Seemples!

Update - 2019-11-05:

So I missed out a rather important part of this post... the pattern above is lovely, but it doesn't work

None of the logging to ILogger<MyClass> instances appear in Application Insights - but logging from the Azure Functions v2 runtime itself does.

Actually the problem isn't the pattern above at all, but another nasty little Azure Functions v1 hangover that Microsoft hasn't fixed yet.

By default, the Azure Functions v2 runtime filters out any logging that's not from the runtime itself, or from ILogger instances that the runtime provides (with the "Function.MyFunctionName.User" style category).

The fix is easy - but irritating. Add logging configuration to your
host.json file, thus:


{
  "version": "2.0",
  "logging": {
 "logLevel": {
   "MyFunctionApp": "Trace"
 }
  }
}
There's an issue that was openned on GitHub in April 2019 about this ( https://github.com/Azure/azure-functions-host/issues/4345 ), so I assume Microsoft will get around to removing the filtering at some point.



Thursday, May 16, 2019

Thursday Quickie: IoC Registrations done wrong broke my DbContext


TLDR: Using InjectionConstructors in Unity can give you singletons. Beware! (and TEST!)


So our tester at work spotted some InvalidOperationExceptions being logged from our data access library recently indicative of a DbContext being re-used across requests... 

Digging into the registration showed quite a few instance of this sort of code:

container.RegisterType<IService, ServiceImplementation>(
    new TransientLifetimeManager(),
    new InjectionConstructor(new Dependency()));

Spot the mistake?

Passing an InjectionConstructor into RegisterType to specify which constructor on the ServiceImplementation class to use is fine... 

Except that passing new Dependency() to the InjectionConstructor does not indicate that a new instance of the Dependency type should be created for each resolution of IService... instead it creates a singleton instance there and then that's subsequently shared across all instances of the IService. Which is bad.

Of course, for DBContext dependencies this is particularly bad - and is the source of the InvalidOperationException that was detected. It's an easy mistake to make, but one that's really hard to spot until you see those exceptions being logged.

The solution - use InjectionConstructor as it's intended:

container.RegisterType<IService, ServiceImplementation>(
    new TransientLifetimeManager(),
    new InjectionConstructor(
        new ResolvedParameter<Dependency>()));

The ResolvedParameter clause says clearly that you're letting the container decide on the lifetime of Dependency.

For bonus points - and to prevent regressions - write tests that verify both that your composition root / container bootstrapper registers types with the correct lifetimes, and that where you've got DBContexts involved that you get a separate DBContext instance when you resolve two instances of IService.

Whilst the above is specific to the Unity IoC framework, you can be sure that all IoC frameworks will have a similar gotcha - so watch out for your registrations!

Tuesday, April 09, 2019

Tuesday Quickie: When closure bites (or how not to configure Newtonsoft.Json)


TLDR: Be very careful using captured closures and anonymous methods - they can leak memory when you don't expect. Also copy-and-paste code is bad.


So yesterday we had an issue where a long-running service within our platform suddenly started throwing StackOverflowExceptions with a new version. It was a blocker to the next release, so inevitably I got tasked with fixing the issue.

A quick profile of a locally running copy replicated the error (phew!) and pointed to one of our HTTP based service clients being at fault. This was confusing, as those components hadn't changed. 

But what had changed was how those clients were being used - previously, they had accidentally been injected from the IoC container as singletons - now they were being injected as transients.

So why would the stack overflow?

It turns out that the service clients all had copy-and-paste code used to ensure that a custom JSON converter was added to the default JSONSerializerSettings used by the Newtonsoft JSON library, and that code was leaking memory and ultimately causing the StackOverflowException

But how? Here's the old code:



Pretty straightforward - and a static method in a static class shouldn't leak?


WRONG!


On lines 8 and 9 we're capturing a closure (defaultSettings) and then using that within an anonymous method that we're assigning back to JsonConvert.DefaultSettings

Because of the captured closure, the compiler couldn't make the anonymous method truly static - so you get a new instance every time the helper method is called - and those instances are pinned (again because of the captured closure) so that they can't be garbage collected.

Since this helper was being called every time a service client was being instantiated, and the clients were no longer singletons, the profile was showing tens of thousands of instances in memory of Func<JsonSerializerSettings>. Not good.

The solution is to be rather more defensive in adding the converter. Here's the corrected version:


We create our own default JsonSerializerSettings instance and a genuinely static Func<JsonSerializerSettings> helper method on lines 7 & 8.

If JsonConvert.DefaultSettings is null, we assign that helper (within a double-checked lock for safety) on line 18.

Finally, we use whatever helper factory was assigned to get the default JsonSerializerSettings instance (line 23) and add our converter if needed - again within a double-checked lock (line 32).

Re-running the repro resulted in exactly 1 instance of Func<JsonSerializerSettings> being created - and our bug is fixed.

The moral of the story? Watch out for anonymous methods and captured closures - they can bite! 

Friday, March 22, 2019

Friday Quickie: Fixing Kubernetes connectivity with Docker for Windows

Another aide-memoire - when using kubectl on Windows against Docker for Windows you get the following error:

Unable to connect to the server: dial tcp [::1]:8080: connectex: No connection could be made because the target machine actively refused it.

This might well just just be that the tool can't find it's config... and the fix is easy - just set an environment variable:
KUBECONFIG=c:\users\joel\.kube\config
Restart your powershell instance and try again... Simple. (see also this issue in github)

Thursday, February 14, 2019

Thursday Quickie: When AssemblyBinding redirect doesn't... and how I fixed it


TLDR: If your csproj file has AutoGenerateBindingRedirects set to true, then you MUST include the xmlns on the assemblyBinding node for any custom binding redirects in app.config.


So I've been banging my head against the wall trying to get a piece of code delivered over the last few days, and kept hitting an issue where code runs perfectly locally, but when deployed to the target server was failing with the dreaded error
Could not load file or assembly 'System.Net.Http, Version=4.1.1.2, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)

I'd used Gertjan van Montfoort's excellent article as a guide, but whatever version of the NuGet package I installed, and whatever version I referenced in my binding redirects in app.config, it just would not fire up.

Looking at the Fusion logs (helped by Scott Hanselman's article) I could see that my app was initially loading System.Net.Http from the GAC for a 4.0.0.0 reference, then successfully loaded 4.1.1.3 from the app directory (the one from the NuGet package I referenced).

But when it was trying to load 4.1.1.2 because of other dependencies Fusion was not honouring the binding redirect, and so the app was failing on startup.

Finally I found a comment on the net that hinted about case sensitivity within the app config, so I went looking for differences between my custom redirects and those generated on build into MyApp.exe.config.

And I found one - the generated redirects all have an xmlns attribute on the assemblyBinding node - and my custom one did not

The solution - add one in your app.config


<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-4.2.0.0" newVersion="4.1.1.2" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
</configuration>

Now your binding redirects get merged with the generated ones and it all works.

My interpretation is that Fusion appears to honour the redirects in assemblyBinding nodes only if all have xmlns attributes or none have them - but not if mixed. 

Hopefully others will find this useful - now I can get on and do some actual work!

Friday, August 19, 2016

Friday Quickie - Setting up Powershell as an App on MacOs

So yesterday, Microsoft announced that Powershell was open source and runs on MacOS. Cool!

But the default installer doesn't make it available as an App within MacOS - you have to open a terminal first. :(

It's actually pretty easy to set this up tho'... 

TLDR

Create an Automator script and save it to Applications.

Step by Step:


Open Automator and File -> New. 

In the New Script dialog, select Application.

Add an AppleScript task from the Utilities section to the script by dragging it onto the design surface.



Then add the following in the script.

 

Finally, save the script to the Applications folder and you're done - Powershell is available as an app through finder. 

For bonus points, find an icon you like on the web, copy the image to your clipboard, GetInfo on the script you just created, select the icon at the top left (it'll get a blue outline), and you can paste the new icon for extra shininess.

Job done.

Monday, July 04, 2016

Monday Quickie: Git Aliases for Proxy Settings

If, like me, you find yourself working from home occasionally flipping the proxy setting on and off for GIT becomes tiresome.

So here's a snippet to give you two new GIT commands for setting and resetting the http.proxy setting that GIT uses.

git config --global alias.noproxy 'config --global --unset http.proxy'
git config --global alias.setproxy 'config --global http.proxy http://<proxyUrl>:<proxyPath>'


Now you can just use 'git noproxy' when at home to turn the proxy off and 'git setproxy' when you're back in the office.

Friday, October 30, 2015

Friday Quickie - Search, Filter and Copy matching files in Powershell

Another little aide-memoire - I want to find all files in a directory containing a specific string that were created on a specific date and copy them to another directory.

Using Powershell it's quite easy, with just a little wrinkle in the copy-item syntax:

PS C:\SourceFolder> get-childitem | where-object { $_.CreationTime -ge "10/29/2015" -and $_.CreationTime -le "10/30/2015" } | select-string -pattern "80029" | group path | select name | % { $_.Name | copy-item -destination C:\temp\TargetFolder }


Tuesday, June 02, 2015

Tuesday Quickie - Transaction Manager Errors are not always what they seem

This one bit me today for the second time, so I thought I'd blog about the problem - more than as a reminder to myself than for any other reason.

On one of our environments, database changes weren't being saved with the following cryptic error message:
Communication with the underlying transaction manager has failed.-- COMException - The MSDTC transaction manager was unable to pull the transaction from the source transaction manager due to communication problems. Possible causes are: a firewall is present and it doesn't have an exception for the MSDTC process, the two machines cannot find each         other by their NetBIOS names, or the support for network transactions is not enabled for one of the two transaction managers.
The actual cause?

A single rogue space in the connection string.

Go figure!

Wednesday, May 20, 2015

Tuesday Quickie - Suppressing SignalR in the Developer Console

This quickie came from a conversation Bart Read and I had on Twitter about how hard all the traffic SignalR generates makes using the Network tab in the Chrome Developer Tools.

In the end, I had a brainwave and found a simple solution - with a little digging and experimentation.

All you need to do is click on the filter icon on the Network tab's toolbar and enter the following magic incantation

-transport -negotiate

This pretty much kills all the SignalR traffic and lets you get back to debugging your own code.





Friday, February 27, 2015

Friday Quickie - dumping parameters from a TFS build definition

So here's the scenario - Ops have changed the TFS build infrastructure underneath you and the build definitions for an "older" project aren't working.

You open the build definition in Visual Explorer, and lo and behold, there's a warning triangle on the Process tab. 

Opening that, and you find that the one of the properties (in this case a deployment script) is now empty and showing an error circle.

The problem is that because it's invalid, the editor has cleared the property - even opening the dialog doesn't help - it's all gone.

So how do you find out what the property WAS so you can fix it?

Well, first, close the build definition WITHOUT SAVING IT!

Next, fire up a Visual Studio Command Prompt and CD to the folder that's mapped to the root of the source code in TFS.

What you need is command line tfpt.exe tool from TF Power Tools (you had that installed already, didn't you?). This has a handy BuildDefinition /dump option that will show you what's in the build definition - regardless that it's invalid.


You can now open the text file in notepad and see what the property WAS - job done.

Tuesday, July 01, 2014

Tuesday Quickie - Transforming App.Config

Another aide-memoire...

By default, app.config files are NOT transformed in the same way as web.config files.

But there's a fix... involving editing the project file (sigh).

Gunnar Peipmann covers the process in detail here: 

http://gunnarpeipman.com/2013/11/using-web-config-transforms-with-app-config-files/

Thursday, June 27, 2013

Thursday Quickie: Installing Windows Drivers for Apple Keyboard, Magic Mouse & Magic Trackpad

Well that was easy!

Unlike previous methods, with the latest release of the BootCamp software, installing drivers for the Apple Keyboard, Wireless Magic Mouse, and Wireless Magic Trackpad couldn't be easier, as all the driver installers are nicely placed in a folder and are ready to go.
  1. Download the BootCamp 5.0.5033 software (http://support.apple.com/kb/DL1638)
  2. Extract the ZIP file somewhere (e.g. c:\temp)
  3. Drill into the following folder
    • c:\temp\BootCamp5.0.5033\BootCamp\Drivers\Apple
  4. Install the drivers
    • AppleKeyboardInstaller64.exe
    • AppleMultiTouchTrackPadInstaller64.exe
    • AppleWirelessMouse64.exe
    • AppleWirelessTrackpad64.exe
  5. Reboot.
The down side (if you consider it as such!) is that Boot Camp 5 only support 64-bit windows. For 32-bit Windows installations you'll need to revert to an older Boot Camp version and a more complex installation process.

The OTHER downside is that the "stuttering mouse" bug still appears to be there for me at least. :(

Thursday, May 03, 2012

Thursday Quickie - Lightswitch Build Issues #2 - XAP Signing

Update: 2015-05-20 - No idea why I never published this Quickie! Three years is way too long for a blog post to languish in the Drafts folder!

Wednesday, May 02, 2012

Wednesday Quickie - Getting rid of those darned connection string parameters

This quickie relates to the parameters used by MSDeploy to transform your web.config when a web application or site is deployed.

By default the deployment targets (Microsoft.Web.Publishing.targets) used when building a deployment package for a web app will automatically generate entries for connection strings. The problem is that it chooses really awful tag names for the parameters - for example:






This gave me a problem as the configuration system we use at Landmark to deploy our web apps can't have any spaces in its parameter tags. Fortunately, there's a quick solution.


It's easy enough to add a Parameters.xml file to your project to provide custom parameters - and in that file it's trivial to include a duplicate connection string parameter definition (that doesn't have spaces in the name).


The final part of the puzzle is to prevent the deployment targets from creating the default connection string entries on build. This is achieved by passing in the following (memorably-named) MSBuild parameter:
/parameter:AutoParameterizationWebConfigConnectionStrings=False
The deployment targets no longer add the connection string parameters by default, so you have to do so explicitly in your Parameters.xml file - but now YOU control the parameter name. Done.



Wednesday, April 25, 2012

Wednesday Quickie - Building Lightswitch Projects in TFS

So I've been fighting with getting my Lightswitch application to build under TFS as part of our (slow) move towards Continuous Build / Continuous Deployment at work... and for weeks I've been banging my head against the wall with the deaded "UnpackExtensionsToProjectDir" error.

And then came the revelation... looking a couple of lines down I found that the real error was being masked - looking at the detailed logs we can see the real culprit:


C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\LightSwitch\v1.0\Microsoft.LightSwitch.targets(1257,9): error MSB4018: The "UnpackExtensionsToProjectDir" task failed unexpectedly.
<SNIP>
[C:\Builds\4\MyApp\Trunk\Sources\Authentication\MyApp.LightswitchApp\MyApp.LightswitchApp.lsproj]C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\LightSwitch\v1.0\Microsoft.LightSwitch.targets(1257,9): error MSB4018:    at Microsoft.LightSwitch.ExtensionsReader.ExtensionInformationService.ExtensionInformation.LSPKGPackage.ExtensionDirectoryDeletionFailedAction(IServiceProvider serviceProvider, String directory) [C:\Builds\4\MyApp\Trunk\Sources\Authentication\MyApp.LightswitchApp\MyApp.LightswitchApp.lsproj]
<SNIP> 
[C:\Builds\4\MyApp\Trunk\Sources\Authentication\MyApp.LightswitchApp\MyApp.LightswitchApp.lsproj]Done Building Project "C:\Builds\4\MyApp\Trunk\Sources\Authentication\MyApp.LightswitchApp\MyApp.LightswitchApp.lsproj" (default targets) -- FAILED.Done Building Project "C:\Builds\4\MyApp\Trunk\Sources\Authentication\MyApp.LightswitchApp\MyApp.LightswitchApp.lsproj.metaproj" (default targets) -- FAILED.
By looking at the Microsoft.Lightswitch.targets file, I found that the actual error was that the build process couldn't delete the _Pvt_Extensions directory.


A quick check showed that that particular directory had been added to TFS source control - removing it and the deaded "UnpackExtensionsToProjectDir" error was finally vanquished. (OK - there were a couple of other build errors, but they were easily fixed).

So now I have a green tick beside my Lightswitch application in TFS Build Explorer - WIN!

Tomorrow, my next challenge - getting the thing packaged for MSDeploy deployment.

Friday, November 13, 2009

Friday Quickie: The *other* TemplateBinding syntax

Setting up the template for a new custom control in Silverlight is fraught at the best of times – the Silverlight runtime invariably swallows any error in the template and gives just a cryptic exception.

But stranger still is a limitation on how the {TemplateBinding ...} syntax can be used and the exception that is thrown when in error.

The {TemplateBinding ...} syntax provides a quick and simple way to bind properties within a control’s template to the properties of the control itself. According to the MSDN documentation, it’s a shortcut to the more full-featured {Binding ...} syntax. But what’s not clear from the documentation is that {TemplateBinding ...} can only bind a control property to a DependencyProperty on the control class.

If you try and use {TemplateBinding ...} against a normal property on the control, you get the strange exception shown right – confusing because the target control (WizardActionButton in the example) absolutely does have a State property.

The solution is to use the {Binding ...} syntax where the source property isn’t a DependencyProperty, and to use the {RelativeSource ...} syntax to specify that you’re actually binding to the control within its template.

Wrong:

<i4tControls:WizardActionButton x:Name="RetreatButtonPart"

Style="{StaticResource ActionButtonStyle}"

State="{TemplateBinding CanRetreat}"

Content="{TemplateBinding RetreatButtonContent}"

ContentTemplate="{TemplateBinding RetreatButtonContentTemplate}"

/>

Correct:

<i4tControls:WizardActionButton x:Name="RetreatButtonPart"

Style="{StaticResource ActionButtonStyle}"

State="{Binding Path=CanRetreat,RelativeSource={RelativeSource TemplatedParent}}"

Content="{TemplateBinding RetreatButtonContent}"

ContentTemplate="{TemplateBinding RetreatButtonContentTemplate}"

/>

Wednesday, September 09, 2009

Wednesday Quickie: Forcing event un-subscription

This is another really simple and obvious code snippet, but one well worth remembering – posted this morning by Fabrice MARGUERIE.

The crux is that event subscriptions can cause memory leaks – so ensuring they are un-subscribed is essential. The code snippet is designed to be used in the Dispose or Cleanup method on the publishing object, and forcibly disconnects any subscribers just before the publishing object is disposed.

if (SomeEvent != null)
{
foreach (EventHandler handler in SomeEvent.GetInvocationList())
SomeEvent -= handler;
}

Simple. Clean. Elegant. Use it!

Force your subscribers away: http://weblogs.asp.net/fmarguerie/archive/2009/09/09/forcing-event-unsubscription.aspx

Wednesday, August 05, 2009

Wednesday Quickie: Why Rounded Corners Work...

Came across this little article this afternoon via a tweet from @DaveSussman giving some background and justification for using rounded corners in your UI design. Well worth a read - I particularly like the examination of Apple hardware from a rounded corner point of view.

Round your rectangles: http://www.uiandus.com/2009/07/27/theories/realizations-of-rounded-rectangles/