DRY-ing ASP.NET MVC actions: ApplicationController or Service?

825 Views Asked by At

I'm writing an ASP.NET MVC 3 app and I'm finding myself writing this line rather often in my action methods:

var user = _session.Single<User>(u => u.UserName == User.Identity.Name);

(Obviously used in conjunction with the AuthorizeAttribute)

There are other things that get repeated quite often but this one is the most prominent and I end up having 3 actions next to each other, each needing to retrieve the authorized user.

So this needs DRY-ing up:

  1. Should I write an ApplicationContoller from which all other controller inherit and expose a User property there or should I add this to my IAdminService and expose it as a method?

  2. Is an ApplicationController something to avoid or to embrace in ASP.NET MVC?

2

There are 2 best solutions below

4
On BEST ANSWER

If you are finding yourself repeating this logic then a custom model binder for the User type might help:

public class UserModelBinder : DefaultModelBinder
{
    private readonly ISession _session;
    public UserModelBinder(ISession session)
    {
        _session = session;
    }

    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var username = controllerContext.HttpContext.User.Identity.Name;
        return _session.Single<User>(u => u.UserName == username);
    }
}

and once you register the binder your controller action might look like this:

[Authorize]
public ActionResult Foo(User user)
{
    // ...
}
1
On

As a person who doesn't really like controller super-types I would consider using Dependency Injection and use constructor injection to "inject" the user.

o/c this has some drawbacks. This means you'll have to a field for every use in your controller, and also have to create a binding in your IOC tool. This also assumes you're using an IOC container.

Regarding the other options:

Exposing it in the IAdminService gives you the added benefit of being availiable in other places, and not just in the Controller. So that's a plus. Just be certain that you don't clutter your interface too much.

Using it in a base controller is also tempting at first, but I've found that controller base types get bloated and mismanaged as more and more functionality is added, because there's no multiple inheritance and people need some of this and some of that... Things can get ugly. Not to mention that if you use the AsyncController you'll have two base-types to manage.

Basically, between your two option's I'd use the interface.

No matter what you do, you can still add a method to the interface and also abstract it behind a User property in a base Controller.