How to redirect Http to Https only in production

You are working locally without a SSL certificate and in production with certificate,=. The simplest way to work handle both case is to have a configuration that switch depending of if you are in your production server or in your local dev box. Here is two solutions. The first one is well known on Internet but require to have IIS with the rewrite module. This is not a problem with Azure, and even locally it’s not a big problem because it can be downloaded from IIS manager console, under Web Platform. But, you won’t need that. The first solution is to change the web.release.config to add the redirection on the deployed files only. This is done like this:

<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <system.webServer>
    <rewrite xdt:Transform="Insert">
      <rules>
        <rule name="Redirect HTTP to HTTPS">
          <match url="(.*)" />
          <conditions>
            <add input="{HTTPS}" pattern="off" ignoreCase="true" />
          </conditions>
          <action type="Redirect" url="https://{HTTP_HOST}/{R:1}" redirectType="Permanent"/>
        </rule>
      </rules>
    </rewrite>
  </system.webServer>
</configuration>

The second solution is simpler, because it’s just a change in code. However, the request needs to go to the Asp.Net pipeline which is more demanding for your webserver. You should have the redirection as soon as you can and doing it at IIS level is the best place. Nevertheless, it’s always good to have both solution on hands.

In global.asax.cs:

if (!HttpContext.Current.IsDebuggingEnabled)
{
     filters.Add(new RequireHttpsAttribute());
}

Azure WebJobs using CronJobs

Windows Azure lets you have background running jobs that are hosted with your website. If you want those jobs to be run in a specific time, you need to schedule them. This is where it can become confusing. Do you need or not to use the Azure Scheduler service? I firstly though that I needed the scheduler service to finally realize that it was not required. I also scheduled everything from Visual Studio who produced a scheduled file webjob-publish-settings.json but got issue with recurring schedule or more complexe scenario like running a job only during the week every 10 minutes. That said, I used for years Cron jobs on Linux and was very happy. Azure lets you configure with Cron jobs too.

First of all, you need to still have the webjob-publish-settings.json. This can be generated by Visual Studio for you. But before anything, be sure that your webjobs has the reference to the Microsoft.Web.WebJobs.Publish. Once you have that reference, be sure that inside the .csproj you have the target to the reference. Here is what you should see.

  <Import Project="..\..\..\packages\Microsoft.Web.WebJobs.Publish.1.0.10\tools\webjobs.targets" Condition="Exists('..\..\..\packages\Microsoft.Web.WebJobs.Publish.1.0.10\tools\webjobs.targets')" />

By right clicking your console application, you need to choose Publish as Azure Webjobs. This will let you create a schedule.
PublishAsAzureWebJob
Select a starting date, an ending date (since you cannot not select anything in this dialog) and choose the mode to on demand. Then, select the generated file webjob-publish-settings.json under the properties folder. You need to have the following properties filled up.

{
  "$schema": "http://schemastore.org/schemas/json/webjob-publish-settings.json",
  "webJobName": "YourJobNameHere",
  "startTime": null,
  "endTime": null,
  "jobRecurrenceFrequency": null,
  "interval": null,
  "runMode": "OnDemand"
}

The mode is on demand because we will run it by Cron job. This need to manually create a new file at the root of your console application named “settings.job”. You also need to go in the file’s property and select that this file will be copied if newer. This is required because when you publish, the system compiles the project and publish the bin folder. You need to have the settings.job file in the bin to be published too. That file will be read by Azure later.

The settings.job file is a JSON format with a single property named “schedule” which have a Cron job syntax. It has 6 fields which is seconds, minutes, hours, days, month, day of week.

{
    "schedule": "0 */10 * * * 1-5"
}

Once published, you will see your job under the website.
WebJobsOnAzure

From there, it is possible to see the job running in the portal.azure.com and see any diagnostic output, etc. One last detail, your website must be running on always on.
ApplicationSettingAlwaysOn

This is required to be able to have your jobs ran. Azure Scheduler is there to be able to do more advanced scenario like calling endpoints outside the scope of your web application. For more scenario, using Cronjob and having all the scheduling setup in your solution which can be on your code repository.

Telemetry with Application Insights JavaScript

Application Insights is a system that run on Azure that lets you send information about your application. I will not go in detail in that post about all its capability. I suggest you read the overview page from the official documentation. This article goal is to use Application Insights to collection information about two buttons that go to the the same page to figure out which one is the most popular. Since both links are normal Html link, we need to use JavaScript to bind the click event to both buttons and send the telemetry before moving to the actual page.

The first step is well documented which is to add the Telemetry to the web project. The detail are also explained in the documentation. In short, it consists to get the right Nuget Package, create the Azure Application Insights account (needed to get a key) and then setup the Global.asax.cs + set the JavaScript that will collect client side telemetry. What is not really well clear is that you need to setup the maxBathSizeInBytes to zero if you want to get the telemetry sent very fast. This is required if you want it on a click event that leave the page. This is not required if you have a single page application that remains on the same page. The setup code look like the following:

<script type="text/javascript">
        var appInsights=window.appInsights||function(config){
            function r(config){t[config]=function(){var i=arguments;t.queue.push(function(){t[config].apply(t,i)})}}var t={config:config},u=document,e=window,o="script",s=u.createElement(o),i,f;for(s.src=config.url||"//az416426.vo.msecnd.net/scripts/a/ai.0.js",u.getElementsByTagName(o)[0].parentNode.appendChild(s),t.cookie=u.cookie,t.queue=[],i=["Event","Exception","Metric","PageView","Trace"];i.length;)r("track"+i.pop());return r("setAuthenticatedUserContext"),r("clearAuthenticatedUserContext"),config.disableExceptionTracking||(i="onerror",r("_"+i),f=e[i],e[i]=function(config,r,u,e,o){var s=f&&f(config,r,u,e,o);return s!==!0&&t["_"+i](config,r,u,e,o),s}),t
        }({
            instrumentationKey: "@Microsoft.ApplicationInsights.Extensibility.TelemetryConfiguration.Active.InstrumentationKey",
            maxBatchSizeInBytes: 0
        });

        window.appInsights=appInsights;
        appInsights.trackPageView();
    </script>

The second step is to add event on each link that you want to collect the click.

function attachTelemetries()
{
    $('#all-contests').click(function () {
        appInsights.trackEvent("BestLinkLocation",
            { LinkDestination: "Contest/List", LinkPageLocation: "DirectTopMenu" }
        );
        appInsights.flush()
    });
    $('#user-contests').click(function () {
        appInsights.trackEvent("BestLinkLocation",
            { LinkDestination: "Contest/List", LinkPageLocation: "SubMenu" }
        );
        appInsights.flush()
    });

}

You can use the appInsights variable, defined when setuping Application Insights with the method trackEvent. The method take a name for the telemetry captured following by properties and if needed some metric. In our case, we can just sum the each properties (each link location) and determine which one is the most popular. Something not clear in the documentation is that it is required to call the flush method. The reason is that once the click event is done, the browser move to the next page. Flush ensures that the telemetry is sent.
MetricExplorer
The third step is to analyse the result. Simply go to portal.azure.com, under the Application Insights.
Events

You can add a chart in the Metric blade, see a the top. Select Sum, in a grid, and group by the property you want to get the data. In our example, it is the property that change which is the location of the link. What can be confusing is to be able to select the property you need to go at the bottom of that blade and select the metric event.

GridTelemetry

The result is a table that contains only the data that has been collected. Hence, you need to have people clicking the buttons to see anything. Also, it can take some time (about 30 minutes) to see the information into the Azure portal.

Azure WebJob ResolveWebJobFiles Error

While working with Azure WebJob you may get in a weird situation where Visual Studio lets you compile but not publish your webjob.

The target “ResolveWebJobFiles” does not exist in the project.

This scenario is present if you create a C# console application and then added from NuGet the Microsoft.Web.WebJobs.Publish package. This package is required to be able to run a console application as a web job on Azure. The problem is that Nuget doesn’t play well with csproj, and this is even more try if you did it once and you updated Microsoft.Web.WebJobs.Publish. The first problem you might have is that the .csproj doesn’t add the import xml line in the project. If this is the case, you can manually add it :

<Import Project="..\packages\Microsoft.Web.WebJobs.Publish.1.0.10\tools\webjobs.targets" Condition="Exists('..\packages\Microsoft.Web.WebJobs.Publish.1.0.10\tools\webjobs.targets')" />

The second problem is that if you update the package, with Nuget, you may get two different problems. Problem A) the version doesn’t get updated, thus you get warning. Problem B) you will get an additional import, and the previous one still stay there.

In all case, you need to open in a text editor your csproj, search for Microsoft.Web.WebJobs.Publish. If it is not there, add it. If it’s there, be sure the version is right and only present once.