Tag Archives: Extensions

Upgrading to MicroLite 6.1

There are a couple of changes in MicroLite 6.1 which you need to be aware of when updating from a previous version.

Listeners

In MicroLite 6.1, we have split the IListener interface into 3:

IDeleteListener containing the following methods:

void AfterDelete(object instance, int rowsAffected);
void BeforeDelete(object instance);

IInsertListener containing the following methods:

void AfterInsert(object instance, object executeScalarResult);
void BeforeInsert(object instance);

IUpdateListener containing the following methods:

void AfterUpdate(object instance, int rowsAffected);
void BeforeUpdate(object instance);

You can create as many listeners as you like implementing all or some of the above interfaces and register them in the appropriate collections.

Example – Create a listener which only cares about insert operations:

public class InsertOnlyListener : IInsertListener
{
   public void AfterInsert(object instance, int rowsAffected) { ... }
   public void BeforeInsert(object instance) { ... }
}

Listener.InsertListeners.Add(new MyInsertListener());

Example – Create a listener which cares about insert and update operations:

public class AuditListener : IInsertListener, IUpdateListener
{
   public void AfterInsert(object instance, int rowsAffected) { ... }
   public void AfterUpdate(object instance, int rowsAffected) { ... }
   public void BeforeInsert(object instance) { ... }
   public void BeforeUpdate(object instance) { ... }
}

var auditListener = new AuditListener();
Listener.InsertListeners.Add(auditListener);
Listener.UpdateListeners.Add(auditListener);

SQL Builder

The “write” builders (SqlBuilder.Delete and SqlBuilder.Update) now offer the same functionality for single columns as the read builder (SqlBuilder.Select):

  • Between(object lower, object upper);
  • In(params object[] args);
  • In(params SqlQuery[] subQueries);
  • In(SqlQuery subQuery);
  • IsEqualTo(object comparisonValue);
  • IsGreaterThan(object comparisonValue);
  • IsGreaterThanOrEqualTo(object comparisonValue);
  • IsLessThan(object comparisonValue);
  • IsLessThanOrEqualTo(object comparisonValue);
  • IsLike(object comparisonValue);
  • IsNotEqualTo(object comparisonValue);
  • IsNotLike(object comparisonValue);
  • IsNotNull();
  • IsNull();
  • NotBetween(object lower, object upper);
  • NotIn(params object[] args);
  • NotIn(params SqlQuery[] subQueries);
  • NotIn(SqlQuery subQuery);

WebApi Extension 3.0.0 Released

MicroLite.Extensions.WebApi 3.0.0 has been released on NuGet.

Configuration and Filters

In WebApi Extension 2.1 we added the ability for the extension to register the MicroLiteSession attribute globally to save you having to apply it to each controller or action which you wanted an ISession/IReadOnlySession opening for. This was done by passing a boolean value for registerGlobalFilter to the WithWebApi configuration extension.

The MicroLiteSession attribute has been moved into the Filters namespace and 2 more filters have been added, one to verify Api method parameters are not null and another to validate them if they are decorated with DataAnnotation attributes.

The configuration of the extension has also been updated, it is now required to specify a WebApiConfigurationSettings class. The WebApiConfigurationSettings class currently exposes 3 properties:

RegisterGlobalMicroLiteSessionAttribute - defaults to true
RegisterGlobalValidateModelNotNullAttribute - defaults to true
RegisterGlobalValidateModelStateAttribute - defaults to true

If you are happy to use the defaults, you can simply tell MicroLite to use the default settings:

Configure.Extensions().WithWebApi(WebApiConfigurationSettings.Default);

otherwise, simply specify the values you wish to use:

Configure.Extensions().WithWebApi(new WebApiConfigurationSettings
    {
        RegisterGlobalMicroLiteSessionAttribute = false
    });

Registering these filters at a global level means that they are called for every action on every controller and you don’t have to have the following at the start of every method on every controller.

public void Post(Customer customer)
{
     if (customer == null)
     {
          throw new ArgumentNullException("customer");
     }

     if (!this.ModelState.IsValid)
     {
          return this.Request.CreateResponse(HttpStatusCode.BadRequest, this.ModelState);
     }
}

Remember that even though the MicroLiteSession attribute is registered globally, you can still override its default behaviour on a per controller or per action basis by applying the attribute to a class/method. This is probably something you don’t need to do very often and can be left to the infrastructure to open and assign a session for your controller and begin/commit a transaction around each action.

WebApi Extension 2.1.0 Released

In the MVC and WebApi extensions post, we discussed using the GlobalConfiguration.Configuration.Filters to register the MicroLiteSessionAttribute. In MicroLite.Extensions.WebApi 2.1.0, we do that automatically when calling .WithWebApi();.

If you don’t want that to happen, simply call the overload instead to opt out of the registration .WithWebApi(registerGlobalFilter: false);

Unit Testing when using the Convention Based Mapping

If you are using the new Convention Based Mapping introduced in MicroLite 3.0 and want to unit test code which uses the SqlBuilder, you will need to ensure that the convention extension is loaded before the tests are run.

The reason for this is that the SqlBuilder reads the ObjectInfo for the type being queried to append the column names and ObjectInfo uses the mapping convention to interrogate the type information. Since the default mapping convention is the AttributeMappingConvention, it will be called instead of the ConventionMappingConvention.

The recommended approach here is to move the configuration of MicroLite extensions into a separate class:

public static class MicroLiteConfig
{
    public static void ConfigureExtensions()
    {
        Configure
            .Extensions()
            .WithNLog() // If used, always load the logging extension first.
            .WithConventionBasedMapping(new ConventionMappingSettings
            {
                IdentifierStrategy = IdentifierStrategy.DbGenerated,
                UsePluralClassNameForTableName = true
            })
            .WithMvc();

        // Register any listeners etc.
    }
}

You can then call MicroLiteConfig.ConfigureExtensions() in your test setup method.

This article was written for version 3.0.0 of the MicroLite framework.

New Infrastructure Interfaces

As part of MicroLite 3.0, two new interfaces were added to the MicroLite.Infrastructure namespace:

IHaveSession and IHaveReadOnlySession

These interfaces are implemented by the controllers in the ASP.NET MVC and ASP.NET WebApi extensions and the MicroLiteSessionAttribute for each extension checks against the interfaces rather than the base controllers.

This means that if you want to, you can use the extensions without having to inherit from the base controllers.

// Instead of having to do this:
public HomeController : MicroLiteController
{
...
}

// You can do this:
public HomeController : SomeOtherController, IHaveSession
{
...
}

This allows you to use the extensions in a scenario where you cannot control the base controller you are using or if you just don’t want to have to inherit from the base MicroLite controller for any reason.

MVC and WebApi extensions

If you use the MVC or WebApi extensions for MicroLite and you use an ISession or IReadOnlySession for every action (method) on your controllers, instead of applying the [MicroLiteSession] to each controller or method you can simply register it in GlobalFilters so that it is invoked for every controller action.

GlobalFilters.Filters.Add(new MicroLiteSessionAttribute());

You can still add a [MicroLiteSession] to specific controller actions if you want to use an Isolation Level or transaction style which differs from the default specified in GlobalFilters:

public class HomeController : MicroLiteController
{
    public ActionResult Index()
    {
        // For this action, this.Session will be resolved using the configuration of 
        // the MicroLiteSessionAttribute in GlobalFilters.
    }

    [MicroLiteSession(AutoManageTransaction = false)]
    public ActionResult Index2()
    {
        // For this action, we want to do something specific with the transaction so we add the
        // MicroLiteSessionAttribute to this method to override the default configuration.
        using (var transaction = this.Session.BeginTransaction())
        {
            ...
        }
    }
}