Capturing ASP.NET Framework RawUrl with Azure Application Insights
Tags: azure, dotnet, aspdotnet, csharp
Published: 2020-09-14 15:43:02

---
title: Capturing ASP.NET Framework RawUrl with Azure Application Insights
published: true
date: 2020-09-14 00:00:00 UTC
tags: azure, dotnet, aspdotnet, csharp
canonical_url: https://swimburger.net/blog/azure/capturing-aspnet-framework-rawurl-with-azure-application-insights
---

Azure Application Insights is an Application Performance Management (APM) tool providing insights into the state of your application. By default, Application Insights will capture a lot of data about your ASP.NET applications including HTTP Requests made to your website. Unfortunately, the **URL captured by Application Insights doesn't always match the URL originally requested by the client**.

In many ASP.NET applications, especially CMS's like DNN, **the path of the HTTP request is internally rewritten by the time Application Insights records the data**. This results in the **rewritten URL to be captured and not the original URL**. You can simulate this scenario with a simple `Context.RewritePath` inside of the `Application_BeginRequest` method of the `global.asax.cs` file:

```csharp
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;

namespace AddRawUrlToApplicationInsights
{
    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_BeginRequest(object sender, EventArgs e)
        {
            // This code snippet is for demo purposes only!
            // these types of rewrites can be performed by IIS Rewrite module 
            // or you can update the routing table to resolve '/' to the HomeController

            string fullOrigionalpath = Request.Url.ToString();
            if (fullOrigionalpath.Contains("/about"))
            {
                Context.RewritePath("/home/about");
            }
            else if(fullOrigionalpath.Contains("/contact"))
            {
                Context.RewritePath("/home/contact");
            }
        }
    }
}
```

[Source at GitHub](https://github.com/Swimburger/AddRawUrlToApplicationInsights/blob/master/Global.asax.cs)

In this sample, when `/about` is requested, the path is rewritten to `/home/about` which will resolve to the `HomeController.About` action. When you browse to `/about` and look at the recorded HTTP request inside of Application Insights, the URL will be `https://domain.tld/home/about` instead of `https://domain.tld/about`. The rewritten URL is useful information, but you may also need the original URL for proper debugging/analyzing.

Luckily, there's a property called `RawUrl` on the request that will always have the original path including the querystring. Application Insights provides an extensibility point for you to capture additional data using the `ITelemetryInitializer` interface. You can capture the original URL by implementing `ITelemetryInitializer` and adding the `RawUrl` data to the telemetry properties:

```csharp
using System;
using System.Web;
using Microsoft.ApplicationInsights.Channel;
using Microsoft.ApplicationInsights.DataContracts;
using Microsoft.ApplicationInsights.Extensibility;

namespace AddRawUrlToApplicationInsights
{
    public class RawUrlTelemetryInitializer : ITelemetryInitializer
    {
        public void Initialize(ITelemetry telemetry)
        {
            if (telemetry is RequestTelemetry requestTelemetry)
            {
                var httpContext = HttpContext.Current;
                if (httpContext?.Request == null)
                {
                    return;
                }

                var request = httpContext.Request;
                requestTelemetry.Properties["RawUrl"] = request.RawUrl;
                requestTelemetry.Properties["RawUrlFqdn"] = new Uri(request.Url, request.RawUrl).ToString();
            }
        }
    }
}
```

[Source at GitHub](https://github.com/Swimburger/AddRawUrlToApplicationInsights/blob/master/RawUrlTelemetryInitializer.cs)

Whenever an HTTP Request telemetry is initialized, this initializer will grab the current HTTP Request and capture the `RawUrl` and the `RawUrlFqdn`. The `RawUrlFqdn` will include the protocol, full domain, port, path, and querystring.  
For Application Insights to use the `RawUrlTelemetryInitializer`, you must add a reference to the class in `ApplicationInsights.config`:

```xml
<?xml version="1.0" encoding="utf-8"?>
<ApplicationInsights xmlns="http://schemas.microsoft.com/ApplicationInsights/2013/Settings">
    <TelemetryInitializers>
        <Add Type="AddRawUrlToApplicationInsights.RawUrlTelemetryInitializer, AddRawUrlToApplicationInsights"/>
        ...
    </TelemetryInitializers>
    ...
</ApplicationInsights>
```

[Full source at GitHub](https://github.com/Swimburger/AddRawUrlToApplicationInsights/blob/master/ApplicationInsights.config)

This is what the resulting data looks like when sent to Application Insights:

```json
{
  "name": "AppRequests",
  "time": "2020-09-11T16:47:04.4346673Z",
  "tags": {
    "ai.cloud.roleInstance": "YOURHOSTNAME",
    "ai.operation.id": "26d253e8979c0f4fb602fc7df4a31039",
    "ai.operation.name": "GET home/about",
    "ai.location.ip": "::1",
    "ai.internal.sdkVersion": "web:2.14.0-17971"
  },
  "data": {
    "baseType": "RequestData",
    "baseData": {
      "ver": 2,
      "id": "59b220044848c141",
      "name": "GET home/about",
      "duration": "00:00:01.6182094",
      "success": true,
      "responseCode": "200",
      "url": "https://localhost:44308/home/about",
      "properties": {
        "RawUrlFqdn": "https://localhost:44308/about",
        "RawUrl": "/about",
        "DeveloperMode": "true",
        "_MS.ProcessedByMetricExtractors": "(Name:'Requests', Ver:'1.1')"
      }
    }
  }
}
```

Notice how the `url`, `properties.Rawurl`, and `properties.RawUrlFqdn` are all capture providing a more complete picture of the request:

- url: https://localhost:44308/home/about
- properties.RawUrlFqdn: https://localhost:44308/about
- properties.RawUrl: /about

## Summary

Using the `ITelemetryInitializer` extensibility point in Application Insights, you can capture additional data. Using the `RawUrl` on the `HttpContext.Request`, you can capture the original URL in addition to the rewritten URL which is captured by default.