Redirect azurewebsites.net to your custom domain

This post assumes that you’ve already configured your custom domain, and here we are adding a step to ensure that the azurewebsites.net domain redirects there.

We achieve this by way of a URL rewrite, configured in the web.config:

<system.webServer>
    <rewrite>  
        <rules>  
            <rule name="Redirect azurewebsites.net to Custom Domain" stopProcessing="true">
                <match url=".*" />
                <conditions>
                    <add input="{HTTP_HOST}" pattern="^(.*?)\.azurewebsites\.net$" />
                </conditions>
                <action type="Redirect" url="mycustomdomain.com/{R:0}" appendQueryString="true" redirectType="Permanent" />
            </rule>
        </rules>
    </rewrite>  
</system.webServer>

This will intercept any azurewebsites.net URL (^(.*?).azurewebsites.net$) and redirect it to your custom domain.

Adding Octopus Deploy to the mix

You most likely have multiple environments, and may need to redirect more than one to it’s own custom domain. Perhaps something like test.myapp.com and production.myapp.com etc.

This means that we’d want to specify a different target domain for the rewrite depending on the environment. We can achieve this my making use of the variable substitution feature in Octopus Deploy.

First, we define the variable in the config file:

<action type="Redirect" url="#{azureRedirectTarget}/{R:0}" appendQueryString="true" redirectType="Permanent" />

The #{azureRedirectTarget} variable now needs to be replaced by Octopus Deploy during deployment, based on the target environment.

First we turn the feature on:

Then we specify values for the new variable, like we normally would:

And now Octopus will replace the variable during deployment and our rewrite will be correct for each environment.

CSS Font Size

The golden rule here is that anything that is not a relative size is a mistake. So you need to go with relative sizing, and the best for fonts is: em and rem

rem: relative to the font size of the root element
em: relative to the font size of it’s direct or nearest parent

So, by setting a baseline font size at the root html element, you can then use rem throughout your app to take control of font sizing. One more bit of magic is to use a root font size that will equate to something you can easily do the maths from. 62.5% equates to 10px in normal conditions:

html {
  font-size: 62.5%     <--- this is 10px
}

With your root element under your control, you can now use rem with confidence throughout:

body (or whatever) {
  font-size: 2.1rem;   <--- this is 21px
}

Domain Modeling – Modeling Milk

From: https://ayende.com/blog/183619-A/modeling-milk-a-discussion-on-domain-modeling

I recently had a discussion at work about the complexity of modeling data in real world systems. I used the example of a bottle of milk in the discussion, and I really like it, so I thought it would make for a good blog post.

Consider a supermarket that sells milk. In most scenarios, this is not exactly a controversial statement. How would you expect the system to model the concept of milk? The answer turns out to be quite complex, in practice.

To start with, there is no one system here. A supermarket is composed of many different departments that work together to achieve the end goal. Let’s try to list some of the most prominent ones:

  • Cashier
  • Stock
  • Warehouse
  • Product catalog
  • Online

Let’s see how each of these think about milk, shall we?

The cashier rings up a specific bottle of milk, but aside from that, they don’t actually care. Milk is fungible (assuming the same expiry date). The cashier doesn’t care which particular milk cartoon was sold, only that the milk was sold.

The stock clerks care somewhat about the specific milk cartoons, but mostly because they need to make sure that the store doesn’t sell any expired milk. They might also need to remove milk cartoons that don’t look nice (crumpled, etc).

The warehouse care about the number of milk cartoons that are in stock on the shelves and in the warehouse, as well as predicting how much should be ordered.

The product catalog cares about the milk as a concept, the nutritional values, its product picture, etc.

The online team cares about presenting the data to the user, mostly similar to the product catalog, until it hits the shopping cart / actual order. The online team also does prediction, based on past orders, and may suggest shopping carts or items to be purchased.

All of these departments are talking about the same “thing”, or so it appears, but it looks, behaves and acted upon in very different ways.

Async/Await and EventHub triggers

If you’ve got a WebJob with a trigger function for an EventHub, make certain nothing is Async/Await because this will result in the attempted processing of messages which have already been disposed.

Best thing to do with a good EDA is to do it without Async but make it as lightweight as possible by offloading processing to an Event Consumer downstream.

Reconnect network drive at startup

Create a Scheduled Task which executes this script as a batch file:

@echo off

:Start
timeout /t 5 /nobreak >NUL
if exist S:\NUL goto End
net use s: \\THE_NETWORK_PATH /USER:<user name> <password> /P:YES
if ERRORLEVEL 1 goto Start
:End

 

Docker moans about ports

If you get this:

docker.exe: Error response from daemon: driver failed programming external connectivity on endpoint amazing_lalande (feafa70c6122eb46579cbf74766644fe447bd24897b295157fd67955cff9a8bf): Error starting userland proxy: mkdir /port/tcp:0.0.0.0:9200:tcp:172.17.0.2:9200: input/output erro

… or something like it, just restart Docker and you’re good.

See: https://github.com/docker/for-win/issues/1038

IoTHub Nodejs SDK Gotcha

If you want to connect using the fromConnectionString API, you first need to be aware that the connection string is not the connection string you’d copy from the Access Keys blade in the portal. This is a connection string which is documented as is required to be formatted like so:

HostName=<iothub_host_name>;DeviceId=<device_id>;SharedAccessKey=<device_key>

The catch here is that this connection string will work, if you generate a SharedAccessKey specifically for the device you want to connect, as is defined by the DeviceId parameter.

If you want to use a single connection string for ALL devices to connect, you need to format your connection string like so:

HostName=<iothub_host_name>;DeviceId=<device_id>;SharedAccessKeyName=<policy_name>;SharedAccessKey=<policy_key>

Note the passing of the SharedAccessKeyName. This is the name of the policy you want to use to connect your devices, the default is “device”.

If you specify the policy to use, you can then just pass along the shared access key for that policy and use this connection string for any device.