Troubleshooting Assembly Binding Issues in .NET

I’ve been using fuslogvw.exe to troubleshoot assembly binding issues for several years so I was pretty surprised to find out that most of the guys on my team had not heard about it. Here’s a link to a great blog post that explains how to use it for those not in the know: http://www.meadow.se/wordpress/viewing-assembly-binding-logs-using-fuslogvw-exe/

ASP.NET MVC Attribute Supporting SSL Terminated at Amazon Elastic Load Balancer

In my last post, I described an ASP.NET Web Api RequireHttps attribute that supports SSL terminated at a load balancer like Amazon’s ELB.  Here’s a RequireHttps attribute for ASP.NET MVC with load balancer support:

using System;
using System.Configuration;
using System.Web.Mvc;
using System.Web;
using System.Collections.Generic;

namespace MvcHelpers
{
    public class RequireHttpsSupportsLBAttibute : RequireHttpsAttribute
    {
        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            if (filterContext.HttpContext.Request.IsSecureConnectionConsideringLoadBalancer()) return;

            base.OnAuthorization(filterContext);
        }
    }

    public static class HttpRequestBaseHelper
    {
        public static bool IsSecureConnectionConsideringLoadBalancer(this HttpRequestBase request)
        {
            return request.IsSecureConnection || LoadBalancerSecured(request);
        }

        public static bool LoadBalancerSecured(HttpRequestBase request)
        {
            if (string.Equals(request.Headers["X-Forwarded-Proto"],
                "https"
                StringComparison.InvariantCultureIgnoreCase))
            {
                return true;
            }

            return false;
        }
    }
}

ASP.NET MVC URLs for Knockout (and other MV-something Javascript Frameworks)

Here’s a way to pass ASP.NET MVC URLs to your Knockout models from an ASP.NET MVC application via HTML configuration instead of global Javascript variables. It also works with any of the other MV-something Javascript frameworks, like AngularJS, and plain Javascript. The key here is the Javascript does not have to know how to build MVC URLs. Instead, MVC is used to configure the URL that is used by Javascript.

First the view:

<div id="myForm" data-search-url='@Url.Action("Action", "Controller", new {area="optionalArea"})'>
<!-- form with bindings to the Knockout model -->
</div>

Here’s an AJAX post:

$.ajax({
  type: "POST",
  url: $("#myform").data("search-url"),
  contentType: 'application/json; charset=utf-8',
  //postData is a Javascript object with properties matching those of the .NET objet
  data: ko.toJSON(postData),
  success: function (data) {
    //handle response
  }
  error: function(xhr, ajaxOptions, thrownError) {
    //error handling
  }
});

If the MVC route expects parameters in the query string, an AJAX get is also straightforward:

$.ajax({
  type: "GET",
  url: $("#myform").data("search-url"),
  contentType: 'application/json; charset=utf-8',
  //query string here is ?name1=value1&name2=value2
  data: {name1: value1, name2: value2},
  success: function (data) {
    //handle response
  }
  error: function(xhr, ajaxOptions, thrownError) {
    //error handling
  }
});

You can also handle more complex routing schemes by putting placeholders in the data attribute on the view side and using replace on the Javascript side to set the parameters. For example, imagine we want a URL like “/area/controller/action/{id}”. In that case, the view would look like this:

<div id="myForm" data-search-url='@Url.Action("Action", "Controller", new {area="optionalArea", id="_id_"})'>
<!-- form with bindings to the Knockout model -->
</div>

And the AJAX call:

$.ajax({
  type: "GET",
  url: $("#myform").data("search-url").replace("_id_", idFromModel),
  contentType: 'application/json; charset=utf-8',
  success: function (data) {
    //handle response
  }
  error: function(xhr, ajaxOptions, thrownError) {
    //error handling
  }
});

The beauty of this approach is it relies completely on MVC for the format of the URL. There are absolutely no assumptions in the Javascript about the routing scheme.

Making ASP.NET MVC Windows Authentication With Role-Based Security Painless for Developers

I’ve always been a bit of a Windows Authentication hater for all the wrong reasons.  If I want to change my roles, I have to change my group memberships in Active Directory.  The network administrator never wants to give me access so I have to make a request and wait.  In the alternative, I can get a number of different users setup and logon to the computer as one of them every time I want to test different security settings.  If my development box is not part of the domain, I can manipulate my local security settings, but that is not always an option either.  I can also set things up so my account doesn’t have access to the application.  This way I “simply” type in the credentials of the user I want to test under each time I fire up the web application. It is just painful to work with Windows Authentication on a developer box

Unfortunately, my current team has to deal with Windows Authentication on our current project and was running into these headaches on a daily basis.  I finally put together a simple solution that swaps in a configuration-based GenericPrincipal for developers that allows them to set up any role memberships they want locally without impacting Active Directory or the server deployment environment.  It’s all controlled from a single configuration setting contained in the appSettings section of the web.config:

<!-- Comma-delimited list of roles to be used in development environment (Windows authentication off).-->
<add key="Roles" value="AutobahnAdministrators" />

If the configuration key is present, the AutenticateRequest event in global.asax injects a GenericPrincipal with the configured role memberships:

protected void Application_AuthenticateRequest(object sender, EventArgs e)
{
    var roles = ConfigurationManager.AppSettings["Roles"];
    if (!string.IsNullOrEmpty(roles))
    {
        var genericIdentity = new GenericIdentity("developer");
        HttpContext.Current.User = new GenericPrincipal(genericIdentity, roles.Split(','));
    }
}

Optional — Allow IoC Container to Inject Correct IPrincipal

Our team uses Castle Windsor to inject an IPrincipal into our controllers to perform role checks. This allows us to avoid directly accessing the HttpContext, which makes unit testing much easier. I’m sure the code below could be adapted to work with any of the popular IoC libraries.

public class Installer : IWindsorInstaller
{
    protected override void RegisterComponents(IWindsorContainer container, IConfigurationStore store)
    {
        //This allows us to inject an IPrincipal into any controller.
        //Will be based on configuration if:
        //  1) Anonymous authentication is enabled (Windows authentication is disabled)
        //  2) AppSettings["Roles"] is a comma-delimited list of roles to assign
        //
        // Throws exception if anonymous authentication is in use and AppSettings/@key=Roles is not configured
        container.Register(Component.For().UsingFactoryMethod((kernel, creationContext) =>
            {
                //if this is a generic principal, it was injected based on the configuration so we can just use it
                if (HttpContext.Current.User is GenericPrincipal)
                {
                    return HttpContext.Current.User;
                }
                //This is only used in integration test scenarios using the container.  If you are running the web app, the proper generic identity from the web.config was injected in global.asax AuthenticateRequest()
                var roles = ConfigurationManager.AppSettings["Roles"];
                if (!string.IsNullOrEmpty(roles))
                {
                    return new GenericPrincipal(new GenericIdentity("developer"), roles.Split(','));
                }

                //if there is not configuration and this is a windows principal, then just return it
                if (HttpContext.Current.User is WindowsPrincipal)
                {
                    return HttpContext.Current.User;
                }

                throw new HttpException(401, "Windows authentication must be on or AppSettings/@key=Roles must be configured");
            }).LifestylePerWebRequest());
    }
}

Issues with System.Web.Optimization when using Areas on a Web Converted from ASP.NET MVC 3 to ASP.NET MVC 4

If you convert an existing ASP.NET MVC 3 application to ASP.NET MVC 4, any new area you add to your project will throw a compilation exception about System.Web.Optimization on every view or partial view in the area. To fix the problem, simply remove the add element for namespace=”System.Web.Optimization” from the area’s web.config or install the Nuget package if you want to use the bundling and minification optimization feature in MVC 4.