Fixing HTTPS Support in ASP.NET MVC Routing

I picked the great Steve's idea to add support for HTTPS in the routing. But I found couple of bugs.

First thing I've noticed after adding it and using ActionLink - was invalid HTTPS URL :). It looked like /App/https:/localhost/AppAccount/LogIn.aspx.

This is totally unexpected. So I asked debugger for some help and first thing I'd noticed is that EnableAbsoluteRouting.MakeAbsoluteUrl - doesn't track ApplicationPath slash which causes invalid link for site in root or in virtual directory. Fixed it the usual for ASP.NET way (with GetCorrectedAppPath).

 

It fixed the second RED problem. What about the leading virtual path appended to the link?

The problem is in the HttpsAwareHttpResponseWrapper.ApplyAppPathModifier and it is again related to the slash-thing. It receives appPath from MVC internals which is again slash-broken :). Then trying to apply RegEx to fails. There's one more problem with RegEx: the pattern is not escaped, but that another story. So instead of using string.Substring I decided to use normal RegEx in rely on it.

So the final fix for me at this moment is:

HttpsAwareHttpResponseWrapper:

public override string ApplyAppPathModifier(string virtualPath) {
    return Regex.Replace(virtualPath, "(.*)http(s?):(.*)", "http$2:$3", RegexOptions.IgnoreCase);// Just remove everything before "httpS:"
}

 

EnableAbsoluteRouting

private string MakeAbsoluteUrl(RequestContext requestContext, string virtualPath, string scheme) {
    return string.Format("{0}://{1}{2}{3}/{4}",
        scheme,
        requestContext.HttpContext.Request.Url.Host,
        GetPortSegmentOfUrl(scheme),
        GetCorrectedAppPath(requestContext.HttpContext.Request.ApplicationPath),
        virtualPath);
}
private string GetCorrectedAppPath(string appPath) {
    if (appPath.Length > 0 && appPath[0] != '/')
        return appPath = '/' + appPath; // Make sure there's slash
    return appPath;
}

 

Hope it will help.

I'm sure I'll find more bugs, but let's leave it for tomorrow :)

And many thanks to Steve Sanderson for the great idea.