Git Hooks

Recently I started having a poke around with Git Hook. The main reason for looking in to this is becuase I have a bad memory and I am always forgetting to run the unit tests before creating pushing to Github and creating a PR.

It turned out to be really easy to set up. All I needed to do was place a pre-push file into the projects .git/hooks folder.

1
dotnet test ./src/project.sln

So now when a do a push from the shell

I also use the git client built in to Visual Stuido. This also seems to respect the hooks although it doesn’t give feed back on progress.

CloudFront and SSL

With Chrome starting to flag sites that don’t support TLS I thought i was about time I set my blog up to be served over TLS.

Since this site is hosted in S3 it was pretty much a matter of following the AWS documentation. The only issue I had was configuring Route53 where the documentation is a little lacking.

In Route53 when you set up the Alias record you set the target to the DNS name of your CloudFront distribution. The appears to only be need is you already have your S3 bucket set up for static site hosting.

SSH on Windows 10

As I’ve been doing my AWS training I’ve needed to SSH in Linux machines quite often for tutorials. Every time the videos for these tutorials have said to use PUTTY when using Windows which I hate.

Windows 10 has had a bash shell for a while now, which I have been using for SSH and which works very well. What some people may not be aware of is that Microsoft added a full native OpenSSH client to the Windows 10 2018 spring update.

To use it you need to enable the Windows feature. You do this bu going into settings and searching for features and selecting “Manage Optional Features”.
Windows 10 Optional Features
Click the + button at the top and find OpenSSH Client in the list and click install. That’s it you now have a ssh client that you can run from Powershell or CMD.
Windows 10 SSH

The last thing you might need to do is if your private key is password protected and you want to add it to the ssh-agent.

1
2
3
4
5
6
7
8
9
10
11
12
13
Get-Service ssh-agent

Status Name DisplayName
------ ---- -----------
Stopped ssh-agent OpenSSH Authentication Agent

Start-Service ssh-agent

Status Name DisplayName
------ ---- -----------
Running ssh-agent OpenSSH Authentication Agent

ssh-add id_rsa

All done, you can now use OpenSSH for you Git client as well as logging into Linux machines.

Exams

I’ve passed my last AWS associate exam this week. Next year in on to one of the professional exam. Hopefully now I’ll have a bit more time for the blog.

The last part of my Alexa blog as been posted.

AWShine

I just wanted to say a big thank you to AWS for the AWShine event they held in Auckland last week. It was a lot of fun.

Thanks for the Echo I just have to figure out how to program it now.

Dapper With .Net Core

I’ve been looking at converting one of our existing WebApi site to ASP.Net core. One issue that I found is that we us Table Value Parameters (TVP) in our sql server stored procedures.

In .Net 4.6 Dapper uses DataTables and the .AsTableValuedParameter helper method. DataTables don’t exist in .Net core which means that we have an issue.

What I found is that you can go back to what appears to be the original way that Dapper supported TVPs and create a class that implements IDaynamicParameters.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public class EmailAddressesParameter : SqlMapper.IDynamicParameters
{
private readonly IEnumerable<string> _emailAddresses;

/// <summary>Initializes a new instance of the
/// <see cref="T:System.Object" /> class.</summary>
public EmailAddressesParameter(IEnumerable<string> emailAddresses)
{
_emailAddresses = emailAddresses;
}

/// <summary>
/// Add all the parameters needed to the command just before it executes
/// </summary>
/// <param name="command">The raw command prior to execution</param>
/// <param name="identity">Information about the query</param>
public void AddParameters(IDbCommand command, SqlMapper.Identity identity)
{
var sqlCommand = (SqlCommand) command;
sqlCommand.CommandType = CommandType.StoredProcedure;
var items = new List<SqlDataRecord>();

foreach (var emailAddress in _emailAddresses)
{
var rec = new SqlDataRecord(new SqlMetaData("EmailAddress",
SqlDbType.NVarChar, 100));
rec.SetString(0, emailAddress);
items.Add(rec);
}

var p = sqlCommand.Parameters.Add("@emailAddress", SqlDbType.Structured);
p.Direction = ParameterDirection.Input;
p.TypeName = "EmailTableType";
p.Value = items;
}
}

Then you call it like this.

1
2
3
4
5
using (var connection = new SqlConnection(connectionString))
{
var parameters = new EmailAddressesParameter(new List<string>() { "test@test.com" });
connection.Execute("test", parameters);
}

It has a slight downside that you need to create a new class for each TVP you use. I don’t think that is too big of a deal as it would be a one time set up.

Odd Error Redirecting on Linux

We have automatic tests that run over our website using Selenium.

For some reason these tests stated failing on from our build server where they where working locally. The issue was where we had a post back from an external site, when the request hit our site it was getting a 404 error.

So I started looking at what was different between our local machines and what the build server was using. On our local machines we run a Selenium hub locally, but the build server users a server which turned out to be running Linux.

Having found that I set up a Linux VM so I could see Chrome running. So watching the test what I saw was this

This was very odd as the route did exist and it worked fine when running on Windows.

Digging into the code one thing I did notice was that we weren’t defining the scheme on the URL when constructing the call back URL. I added the scheme to the url and it started working.

So it appears while Chrome on Windows was able to infer the scheme, Chrome on Linux needed it explicitly defined.

WebApi - Binding to Header Values

We have a WebApi project at work where we need to get a value from the header and use it as input to a query.

One way to do this is

1
2
3
4
5
public IActionResult DoSomething()
{
var headerValues = request.Headers.GetValues("MyHeader");
var header = headerValues.FirstOrDefault();
}

YUCK.

I wasn’t very keen on this and starting think it must be possible to use WebApi’s model binding. After a bit of searching I found https://blog.bennymichielsen.be/2013/11/17/modelbinding-with-headers-in-asp-net-webapi/ which gave me most of
the details. This left me with model binding working, but not quite in the way I wanted.

1
2
3
4
public IActionResult DoSomething([ValueProvider(typeof(HeaderValue))] int custId)
{
//Do something with custId
}

Better, but not quite what I wanted.

In trying to fill in a few of the missing pieces I had a look at the WebApi code on GitHub and found that in one of their Integration tests Microsoft had pretty much exactly what I was after.

So between the two I was able to put together something I was happy with.

1
2
3
4
5
6
7
8
9
10
11
12
public class HeaderValueProviderFactory : ValueProviderFactory
{
/// <summary>
/// Gets the value provider.
/// </summary>
/// <param name="actionContext">The action context.</param>
/// <returns></returns>
public override IValueProvider GetValueProvider(HttpActionContext actionContext)
{
return new HeaderValueProvider(actionContext.Request);
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
/// <summary>
/// Returns the tenant id from the request header.
/// http://blog.bennymichielsen.be/2013/11/17/modelbinding-with-headers-in-asp-net-webapi/
/// also some ideas from the ASP.NET unit tests
/// https://github.com/ASP-NET-MVC/aspnetwebstack/blob/4e40cdef9c8a8226685f95ef03b746bc8322aa92/test/System.Web.Http.Integration.Test/ModelBinding/ModelBindingController.cs#L271
/// </summary>
public class HeaderValueProvider : IValueProvider
{
private readonly HttpRequestMessage _requestMessage;

/// <summary>
/// Initializes a new instance of the <see cref="HeaderValueProvider"/> class.
/// </summary>
/// <param name="requestMessage">The request message.</param>
public HeaderValueProvider(HttpRequestMessage requestMessage)
{
_requestMessage = requestMessage;
}

/// <summary>
/// Determines whether the specified prefix contains prefix.
/// </summary>
/// <param name="prefix">The prefix.</param>
/// <returns></returns>
public bool ContainsPrefix(string prefix)
{
return _requestMessage.Headers.Contains(prefix);
}

/// <summary>
/// Gets the value.
/// </summary>
/// <param name="key">The key.</param>
/// <returns></returns>
public ValueProviderResult GetValue(string key)
{
IEnumerable<string> headerValue;
ValueProviderResult result = null;
if (_requestMessage.Headers.TryGetValues(key, out headerValue))
{
var header = headerValue as IList<string> ?? headerValue.ToList();
if (header.Any())
{
var value = header.First();
result = new ValueProviderResult(value, value, CultureInfo.InvariantCulture);
}
}
return result;

}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Parameter, Inherited = true, AllowMultiple = false)]
public class FromHeaderAttribute : ModelBinderAttribute
{
/// <summary>
/// Gets the value providers that will be fed to the model binder.
/// </summary>
/// <returns>
/// A collection of <see cref="T:System.Web.Http.ValueProviders.ValueProviderFactory"/> instances.
/// </returns>
/// <param name="configuration">The <see cref="T:System.Web.Http.HttpConfiguration"/> configuration object.</param>
public override IEnumerable<ValueProviderFactory> GetValueProviderFactories(HttpConfiguration configuration)
{
return base.GetValueProviderFactories(configuration).OfType<HeaderValueProviderFactory>();
}
}
1
2
3
4
5
6
7
8
 public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
config.Services.Add(typeof(ValueProviderFactory), new HeaderValueProviderFactory());
}
}

So finally I can just do

1
2
3
4
public IActionResult DoSomething([FromHeader(Name="CustId")] int custId)
{
// Do something with custId
}

Much nicer.

Moving Blog

Since I’m doing AWS certification and need to get some more experiance with AWS I thought it would be a good idea to move my blog.

So I’ve moved it to Hexo because I wanted a static site generator that wasn’t written in Ruby and would run on Windows. Hexo is pretty good, but I’ve some some of the plug ins need Python 2 and then need to try an compile C code which works about as bladly as it does for Ruby.

I event tried it under the new Windows 10 bash support, but I seems that node isn’t node, but is nodejs. I need to do some more research on that.