Archives

Archives / 2008 / August
  • Dependency injection made easy for the ASP.NET MVC

    I decided to write this post to show how cool is Autofac for doing dependency injection in the ASP.NET MVC framework. Autofac, for me the Moq stepbrother  in the dependency injection arena because of its very-easy-to-use fluent interface and nice support of lambda expressions, comes with a built-in ASP.NET module to automatically intercept the creation of the controllers and pass the required dependencies to them, the only thing a programmer has to do is to provide instances of those dependencies or expressions to build them.

    Well, it is time to see Autofac in action with a practical example. If you have the chance to use the MVC preview 4, you may notice that it comes with a new controller "Account" to manage the website membership. This controller receives two dependencies in the constructor,

    public AccountController(IFormsAuthentication formsAuth, MembershipProvider provider)

    {

      FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();

      Provider = provider ?? Membership.Provider;

    }

     

    public IFormsAuthentication FormsAuth

    {

      get;

      private set;

    }

     

    public MembershipProvider Provider

    {

      get;

      private set;

    }

    If those dependencies are not provided, it creates a default implementation of "FormsAuthenticationWrapper" and use the Membership singleton instance. Ok, let's make some minor changes to this controller so we always assume that those instances must be provided by the caller code (It will be actually responsibility of the DI container).

    public AccountController(IFormsAuthentication formsAuth, MembershipProvider provider)

    {

      FormsAuth = formsAuth;

      Provider = provider;

    }

    We now have to initialize a container to instruct Autofac about how to initialize or get instances of those classes. This can be done in the global.asax file,

    static IContainerProvider containerProvider;

     

    protected void Application_Start()

    {

       RegisterRoutes(RouteTable.Routes);

     

       var builder = new ContainerBuilder();

     

       // Automatically register all controllers in the current assembly.

       builder.RegisterModule(new AutofacControllerModule(Assembly.GetExecutingAssembly()));

     

       builder.Register<MembershipProvider>(container => Membership.Provider).ExternallyOwned();

       builder.Register<FormsAuthenticationWrapper>().As<IFormsAuthentication>().FactoryScoped();

     

       containerProvider = new ContainerProvider(builder.Build());

     

       // Hook MVC factory.

       ControllerBuilder.Current.SetControllerFactory(new AutofacControllerFactory(containerProvider));

    }

    There are some lines in the code above that deserve special attention, so let's discuss them in details:

    1.

    // Automatically register all controllers in the current assembly.

    builder.RegisterModule(new AutofacControllerModule(Assembly.GetExecutingAssembly()));

    This line basically discovers and registers all the controllers within the current assembly (The website itself) into the DI container.

    2.

    builder.Register<MembershipProvider>(container => Membership.Provider).ExternallyOwned();

    builder.Register<FormsAuthenticationWrapper>().As<IFormsAuthentication>().FactoryScoped();

    The dependencies are registered in the container builder (The one that later knows how to create instances of the dependencies). The Register method optionally receives an lambda expression that will be used later to create or get the dependency instance, it could be considered a sort of lazy class construction. The container can also be used in the expressions to resolve other dependencies, for example,

    builder.Register<MessagingService>(c => new MessagingService(c.Resolve<IMessageRepository>).As<IMessagingService>();

    Another important aspect in the initialization is the scope, which basically controls the dependency lifetime. In the code above I used two scopes, ExternallyOwned (The instance is managed by the application) and FactoryScoped (A new instance is created for every dependency resolution, very useful for instances that must be used and disposed just after, like the DataContext in Linq to SQL). Other possible scopes could be ContainerScoped (An instance per container) or Singleton (An instance shared between all containers).

    3.

    containerProvider = new ContainerProvider(builder.Build());

     

    // Hook MVC factory.

    ControllerBuilder.Current.SetControllerFactory(new AutofacControllerFactory(containerProvider));

    The container provider is created, and the controller factory implementation provided by Autofac is set for the current application.

    As you can see, most of the plumbing code is already provided by Autofac, just a couple of lines were needed to start using DI in the MVC framework.

    The code sample is available to download here

    Read more...

  • Combining JQuery Validation with ASP.NET MVC

    One of the most nicest things about JQuery - in addition to the powerful mechanism it provides to manipulate the HTML DOM - is the great number of very useful plugins available out there.

    JQuery Validation is one of my favorites, and today we will see how this plugin can be used with the MVC framework to validate all the inputs in a form before it is submitted to the controller.

    This plugin supports the concept of "validation rule", a validation that has to be performed to an input field. For instance, "The field is required", "The field should have at least N characters", or "This field has to be a valid email", many of them are the same you can find in the ASP.NET validators. (These validators do not work with the MVC framework because they are tied to the ASP.NET Viewstate). Of course, new rules can also be created for performing custom validations specific to an application, some examples of this are also available in the plugin's website.

    A rule can be applied to an input field in two ways:

    1. Declarative, the rule is specified in the input field by means of the class attribute:

    <input name="email" id="email" maxlength="60" class="required email" type="text"/>

    As you can see, two rules were specified in the class attribute, "Required" and "Email", which means that two validations have to be performed for this field. Many rules can be applied to the same field, they only have to be separated by an space.

    2. Imperative in code, the rule is specified in an script:

    <script type="text/javascript">

    $(document).ready(function(){

      $("#form-sign-up").validate( {

        rules: {

          email: {

            required: true,

            email: true

        },

        messages: {

          email: {

            required: "Please provide an email",

            email: "Please provide a valid email"

         } });

    });

    </script>

    The validation was attached to the input field "email" in the form "form-sign-up". The message displayed when a validation fails for an specific field can also be customized using the "messages" section in the script. (This is optional, the plugin already comes with a set of pre-defined error messages)

    And finally, one of the most interesting validation rules you can find there is "remote", which performs a remote validation using an Ajax endpoint. At this point we can use an MVC controller method to perform an specific validation, for instance to see if a login name is still available to be used.

    <script type="text/javascript">

    $(document).ready(function(){

    $("#form-sign-up").validate( {

      rules: {

        login: {

          required: true,

          remote: '<%=Url.Action("IsLoginAvailable", "Accounts") %>'

       }

      },

      messages: {

        login: {

         required: "Please provide an alias",

         remote: jQuery.format("{0} is already in use")

       }

      } });

    });

    </script>

    The only requirement for the controller is that it must be return Json with the result of the validation. This can be easily done with MVC,

    public JsonResult IsLoginAvailable(string login)

    {

        //TODO: Do the validation

        JsonResult result = new JsonResult();

        if (login == "cibrax")

          result.Data = false;

        else

          result.Data = true;

     

        return result;

    }

    In the example above, if "cibrax" is entered as login name, the validation will fail and the user will see an error message.

    The styles for the error messages can also be customized with the following rules,

    label.error {

    display: block;

    color: red;

    font-style: italic;

    font-weight: normal;

    }

    input.error {

    border: 2px solid red;

    }

    td.field input.error, td.field select.error, tr.errorRow td.field input,tr.errorRow td.field select {

    border: 2px solid red;

    background-color: #FFFFD5;

    margin: 0px;

    color: red;

    }

    As we have discussed here, JQuery validation is a great tool that we all should consider at the moment to validate data in the ASP.NET MVC framework.

    A complete example with different validations can be downloaded from this location.

    Read more...