Fabian's Mix

Mixins, .NET, and more

re-mix: Encapsulate and share ASP.NET MVC controller actions

with 2 comments

Jan Jonas has written a blog post about how to encapsulate commonly used controller actions using mixins with ASP.NET MVC 3. I think that it’s a really cool idea to use re-mix for this, however Jan is facing a few stumbling blocks that I want to comment upon. (Actually, I wanted to post this as a comment to his blog post, but for some reason, the comment form isn’t working.)

I understand Jan is saying that ASP.NET MVC doesn’t find the action methods added by mixins because the proxies generated by re-mix don’t inherit from ControllerBase. Therefore he needs to implement a custom ControllerActionInvoker to get ASP.NET MVC to invoke action methods introduced by mixins.

Actually, the proxies re-mix generates do inherit from the mixed classes; in Jan’s example, those are Controller1Controller and Controller2Controller, i.e., the proxies do inherit (indirectly) from ControllerBase. Then why isn’t ASP.NEW MVC finding those controller actions by default?

Maybe the problem is that the proxies implement the mixin interfaces (in the example, IEchoControllerMixin) explicitly, and ASP.NET MVC probably doesn’t search for explicit interface implementations. However, one can tell re-mix to implement interface members publicly, either by putting the MemberVisibilityAttribute on the methods in the mixin, or by specifying IntroducedMemberVisibility = MemberVisibility.Public when applying the UsesAttribute. (You can also derive a custom attribute from UsesAttribute that sets IntroducedMemberVisibility to MemberVisibility.Public by default, since you’ll always want to do that for controller mixins.)

If, for some reason, that still doesn’t work, one could put the CreateActionInvoker override into the target class (Controller1Controller) rather than the mixin, or into a different mixin (e.g., a ControllerMixinSupportMixin). That would enable one to use multiple controller mixins without generating conflicts on the CreateActionInvoker method.

A second problem Jan is facing is that the controller mixins can’t access the protected members declared by the controller and its base classes. However, re-mix allows this: to give mixins access to protected members of the target class, one can specify a custom interface as the TTarget parameter to the Mixin<TTarget> base class. Just define a public interface redeclaring all the controller methods the mixins should be able to access and specify that for the TTarget type parameter. The target class doesn’t actually have to implement that interface, it just needs to provide all the members, with either public or protected visibility.

I’ve adapted Jan’s example accordingly:

public interface IMixedController
{
  ViewResult View();
  ViewResult View (string viewName);
  ...
}
public class EchoControllerMixin : Mixin<IMixedController>, IEchoControllerMixin
{
  public ActionResult Echo(string id)
  {
    var result = new ContentResult();
    var controllerName =
        Target.ControllerContext.RouteData.Values["controller"].ToString();
    result.Content = string.Format(
        "re-mix added Echo action to controller '{0}'<hr/>You said: {1}", 
        controllerName,
        !string.IsNullOrEmpty(id) ? id : "<i>nothing</i>");
    return result;
  }
}
public class UsesControllerMixinAttribute : UsesAttribute
{
  public UsesControllerMixinAttribute (Type mixinType)
    : base (mixinType)
  {
    IntroducedMemberVisibility = MemberVisibility.Public;
  }
}
[UsesControllerMixin(typeof(EchoControllerMixin))]
public class Controller1Controller : Controller
{
}

 

Feel free to ask at the discussion list (http://groups.google.com/group/re-motion-users) if you face any other issues with re-mix.

Update (2012-01-11): Fixed base attribute ctor call in code.

Update (2012-01-16): As mentioned in the comments, Jan Jonas has published a blog post discussing my suggestions.

Written by Fabian

January 10th, 2012 at 10:09 am

Posted in mixins

2 Responses to 're-mix: Encapsulate and share ASP.NET MVC controller actions'

Subscribe to comments with RSS

  1. Hi Fabian, I’ve written a follow-up post http://blog.janjonas.net/2012-01-15/asp_net-mvc_3-remix-library-add-controller-actions-mixins-part2 that shows how to integrate your suggestions into my first approach. Thanks again!

    Jan

    15 Jan 12 at 15:37

  2. Cool, I’ve added a link to the blog post.

    Fabian

    16 Jan 12 at 08:21

Leave a Reply