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
13
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.

Asp.Net User Secrets

So I’ve been playing around with Asp.Net 5 beta 5 trying to figure out how to use some of the new configuration stuff.  Especially the user secrets stuff.

The idea of user secrets is that you need to have some settings on you dev machine which you don’t want in source control.  Things like passwords etc.

I’ve found the documentation some what lacking so hopefully this overview will help.

Firstly you need to install the user-secret command. The installation instructions aren’t too bad and can be found here DNX-Secret-Configuration.

To add the user secrets

Once I had that installed I added the userSecrestsId to my project.json, but that didn’t seem to be picked up.

{  
    "webroot": "wwwroot",  
    "userSecretsId": "aspnet5-4c570577-d4ba-491c-a56c-3f267e3d5211",  
    "version": "1.0.0-*",

I found that I need to add this to the startup.js when I loaded the user secrets.

public class Startup  
    {  
        public Startup(IHostingEnvironment env)  
        {  
            var builder = new ConfigurationBuilder();  
            if (env.IsDevelopment())  
            {  
                builder.AddUserSecrets("aspnet5-4c570577-d4ba-491c-a56c-3f267e3d5211");  
            }  
            else  
            {  
                builder.AddEnvironmentVariables();  
            }  
            Configuration = builder.Build();  
        }

The next problem was figuring out how to inject these values into the controller.  What I found is you need to AddOptions in the ConfigureServices method and they Configure the class you want the values put in.

public void ConfigureServices(IServiceCollection services)  
       {  
           services.AddMvc();  
           services.AddOptions();  
           services.ConfigureAwsOptions>(Configuration);

My AwsOptions class just has two string fields with the name of the secret properties I want to use.

namespace Config  
{  
    public class AwsOptions  
    {  
        public string awsAccessKey { getset; }  
        public string awsSecret { getset; }          
    }  
}

The ASP.NET configuration system will look for values in the Configuration object that match these name and load them into that class.  Then to get them in the controller you do the following

[Route("api/[controller]")]  
public class AController : Controller  
{  
    private readonly IOptionsAwsOptions> _awsOptions;  
    private readonly ILoggerSeverController> _logger;  

    public AController(IOptionsAwsOptions> awsOptions, ILoggerAController> logger)  
    {  
        _awsOptions = awsOptions;  
        _logger = logger;  
    }  

    // POST api/values  
    [HttpPost]  
    public async TaskIActionResult> Post(Guid Id)  
    {  

        AmazonSimpleNotificationServiceClient snsclient =  new AmazonSimpleNotificationServiceClient(_awsOptions.Options.awsAccessKey,  
                 _awsOptions.Options.awsSecret, RegionEndpoint.USWest2);

That’s it.  Then you will get your user secret values injected into you class.

Full Startup.cs (because I hate it when the snippets miss something I need)

using Microsoft.AspNet.Builder;  
using Microsoft.AspNet.Hosting;  
using Microsoft.Framework.Configuration;  
using Microsoft.Framework.DependencyInjection;  
using Microsoft.Framework.Logging;  
using Severing.Service.Config;  

namespace Service  
{  
    public class Startup  
    {  
        public Startup(IHostingEnvironment env)  
        {  
            var builder = new ConfigurationBuilder();  
            if (env.IsDevelopment())  
            {  
                builder.AddUserSecrets("aspnet5-4c570577-d4ba-491c-a56c-3f267e3d5211");  
            }  
            else  
            {  
                builder.AddEnvironmentVariables();  
            }  
            Configuration = builder.Build();  
        }  

        public IConfiguration Configuration { getset; }  

        // This method gets called by a runtime.  
        // Use this method to add services to the container  
        public void ConfigureServices(IServiceCollection services)  
        {  
            services.AddMvc();  
            services.AddOptions();  
            services.ConfigureAwsOptions>(Configuration);  
            services.AddLogging();  
            // Uncomment the following line to add Web API services which makes it easier to port Web API 2 controllers.  
            // You will also need to add the Microsoft.AspNet.Mvc.WebApiCompatShim package to the 'dependencies' section of project.json.  
            // services.AddWebApiConventions();  
        }  

        // Configure is called after ConfigureServices is called.  
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)  
        {  

            loggerFactory.AddConsole();  
            // Configure the HTTP request pipeline.  
            app.UseStaticFiles();  

            // Add MVC to the request pipeline.  
            app.UseMvc();  
            // Add the following route for porting Web API 2 controllers.  
            // routes.MapWebApiRoute("DefaultApi", "api/{controller}/{id?}");  
        }  
    }  
}

Fix for NServiceBus Testing.

Looks like the issue I had with NSB testing may not have been the Unobtrusive messages.

What I’ve ended up having to do is this.

1
2
3
MessageConventionExtensions.IsMessageTypeAction =
t => t.Namespace != null && t.Namespace.EndsWith(“Messages”) && !t.Namespace.StartsWith(“NServiceBus”);
Test.Initialize();