Moving WordPress uploads to AWS S3

There are 2 plugins that make the magic work.

https://wordpress.org/plugins/amazon-s3-and-cloudfront/

Connects your install to the bucket of your choice and all future uploads will go to S3

https://wordpress.org/plugins/regenerate-thumbnails/installation/

This plugin will run on the existing uploads (if you have any) and regenerate them on S3 whilst updating your URLs in the posts/pages.

There is a pretty handy walk through here too if you are new to AWS permissions and buckets.

https://premium.wpmudev.org/blog/moving-wordpress-media-to-amazon-s3/

Installing WordPress in a subdirectory in a .NET application

When you install WordPress as a root web app using Web Platform Installer, everything just works.  However, adding a WordPress blog to a subdirectory (e.g. /blog) needs quite a few extra steps beyond the base install to get everything ‘working’.

Installing PHP

I used the PHP 7 32 bit. Before installing it you will need the Visual C++ Redistributable (again 32 bit)!

https://www.microsoft.com/en-gb/download/details.aspx?id=48145

Web.config in sub directory

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <system.webServer>
    <rewrite>
      <rules>
      <clear/>
      <rule name="wordpress" patternSyntax="Wildcard">
        <match url=".*"/>
          <conditions>
            <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true"/>
            <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true"/>
          </conditions>
        <action type="Rewrite" url="index.php"/>
      </rule></rules>
    </rewrite>
  </system.webServer>
</configuration>

Web.config in root

No changes required

Permissions

The web.config in the root must have a few permissions added to it before things will work. Add IUSR(Should already by on) and IIS_IUSRS. This will allow the subdirectory to access the parent.

Virtual Application and App Pool

  • Remove the default application and app pool that the wordpress install created.
  • Create a new app pool (unmanaged code) and set the Identity (advanced settings) to LocalSystem
  • Re-add the virtual application and ensure you use the new app pool created above.

Uploads and Imports

To enable uploads to work I had to make a few changes

  • Php uploads to C:\Windows\Temp and then copies to the uploads directory. The problem is that the permissions get inherited. Create a new directory, add IIS_IUSRS permissions and update PHPini.php to point to this as the temp uploads folder.
  • Also in the wp-admin directory I found I needed to add a new phpini.php to allow for better memory management, as a relatively small data import would cause it to tank. Not sure if this is a required step but it seemed to help!
<?php

 phpinfo()

?>

memory_limit = 128M

Summary

So there you have it. There is definitely a learning curve to this if you’re not from PHP land, but overall the installation seems to be working!

Resources

A selection of resource that came in very handy to making this all happen!

http://serverfault.com/questions/613927/500-error-on-fresh-install-of-iis-and-php

http://www.mbrauchler.com/wordpress-image-upload-problem-using-iis-on-windows-server-2008/

https://wordpress.org/support/topic/iis-image-upload-view-issues

http://stackoverflow.com/questions/14966871/second-wordpress-installation-on-iis-server

https://wordpress.org/support/topic/wordpress-installation-on-root-folder-sub-folder-on-iis-server-url-conflict?replies=5

Good location services

Location lookups are a part of pretty much every app these days, but I constantly find myself searching for good data providers or services to give me what I need. Here is a list of some good ones, some of which I have used first hand. Hopefully this will help someone hours of Googling!

https://www.townslist.co.uk – UK town list service, updated regularly, Paid

http://www.sqldumpster.com/databases/geographic/ – Many geo databases, infrequent updates, Free

http://dev.maxmind.com/geoip/geoip2/geolite2/ – The daddy of location services, not cheap, but fast and pretty accurate. Their CSVs are massive and can be a nightmare to tailor to your app.

https://www.freemaptools.com/download-uk-postcode-lat-lng.htm – UK postcode database, last updated 2015, Free

 

Web deploy and TLS V1.0

Recently I have been using the excellent IISCrypto tool to lock down some servers for PCI compliance. One of the main steps in this process was to close off TLS V1.0.  In the past on Windows 2008R2, this was a problem as disabling it used to kill RDP services too. However on Windows 2012 boxes, the default is TLS V1.2 so you can safely do this.

The gotcha came when using web deploy to push my applications to this server, connections failed to the server. This was a client issue. By default, my Windows 10 install seems to be defaulting to TLS V1.0.

To fix the issue, a registry edit is required.  Simply create a .reg file with the exact content below, run it, happy days again.

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v4.0.30319]
"SchUseStrongCrypto"=dword:00000001

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\.NETFramework\v4.0.30319]
"SchUseStrongCrypto"=dword:00000001

Mailchimp inline post hack

Mailchimp is my go-to signup service, but I do hate their default double opt in system and their landing pages which are basically really awkward to bypass unless you build your own forms using their API.

There is a way to ‘hijack’ their standard embed form by changing the form action to GET and send the data using JSON P. This returns you an inline response which you can handle without all their pesky screens and redirects.

<form action="http://yourlist.us6.list-manage.com/subscribe/post-json?u=bbbaafd1d12345c57b712345&id=123456789e">
$("#subscribe-form").submit(function(e){
    e.preventDefault();
    submitSubscribeForm($("#subscribe-form"));
});

Credit: http://pocketproduct.com/2014/a-better-mailchimp-signup/

CallerMemberName attribute

Recently I created a WebApi where the client wanted to know what the original method name was when getting a response back.

I found a cool way to do it which .NET 4.5 offers.

The [CallerMemberName] attribute can be added as an optional parameter to any method and give you access to the calling methods name.

public class SomeClass
{
    public void SomeMethod([CallerMemberName]string memberName = "")
    {
        Console.WriteLine(memberName); //output will me name of calling method
    }
}

You can access some other useful properties too such as line number and even file path

public void TraceMessage(string message,
        [System.Runtime.CompilerServices.CallerMemberName] string memberName = "",
        [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "",
        [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0)
{
    System.Diagnostics.Trace.WriteLine("message: " + message);
    System.Diagnostics.Trace.WriteLine("member name: " + memberName);
    System.Diagnostics.Trace.WriteLine("source file path: " + sourceFilePath);
    System.Diagnostics.Trace.WriteLine("source line number: " + sourceLineNumber);
}

Inheritance from derived classes with AutoMapper

Simple scenario.  Base class is super simple and we have a derived class which adds some additional properties to it.

The problem is if you try to do a Mapper.CreateMap from your source to the DERIVED class, the properties of the base class are not include by default.

To achieve this:

Mapper.CreateMap<SourceClass, ExtendedClass>().IncludeBase<EventBase, EventExtended>();

 

Credit: https://github.com/AutoMapper/AutoMapper/wiki/Mapping-inheritance