• NHibernate String Enumeration Mapping

    Here’s what’s needed to have NHibernate map an enumeration by the enumeration name instead of the number.

    <property name="DayOfWeek" type="NHibernate.Type.EnumStringType`1[System.DayOfWeek, mscorlib], NHibernate"></property>
    
  • NHibernate Session Per Request Using Castles WcfFacility

    I was under the false impression that the NHibernateFacility would handle session by request, needed for lazy loading collections, when used with the WcfFacility in an IIS setting. This might work if you use ASP.NET compatibility mode, however, it’s not a recommended solution and I needed to support multiple database connections. Soooo … after searching and reading some other great posts to get me in the right direction I came up with the following solutions.

    First the posts that helped me with this:

    Second what I’m building on:

    • Castle.Windsor
    • Castle.NHibernateFacility
    • Castle.WcfFacility
    • Running on IIS

    The solution:

    First off we have a class used to hold the ISession references for the duration of the request.

    public sealed class NHibernateContextExtension : IExtension, IDisposable
    {
        public List Sessions { get; set; }
      
        public NHibernateContextExtension()
        {
            Sessions = new List();
        }
      
        public void Attach(InstanceContext owner)
        { }
      
        public void Detach(InstanceContext owner)
        { }
      
        public void Dispose()
        {
            if (Sessions != null)
                Sessions.ForEach(s => s.Close());
        }
    }
    

    Next we need to hook into the WCF call at the before and after invoke. This is where we create the needed ISession instances and store in the above class.

    public class WcfSessionPerRequestCallContextInitializer : ICallContextInitializer
    {
        private readonly ISessionManager sessionManager; 
        private readonly string[] dbAliases;
      
        public WcfSessionPerRequestCallContextInitializer(ISessionManager sessionManager, string[] dbAliases)
        {
            sessionManager = sessionManager; 
            dbAliases = dbAliases;
        }
      
        public object BeforeInvoke(InstanceContext instanceContext, IClientChannel channel, Message message)
        {
            var extension = new NHibernateContextExtension();
      
            foreach (var dbAlias in dbAliases) 
                extension.Sessions.Add(sessionManager.OpenSession(dbAlias));
    
            instanceContext.Extensions.Add(extension);
            return extension;
        }
        
        public void AfterInvoke(object correlationState)
        {
            if (correlationState != null)
                ((IDisposable)correlationState).Dispose();
        }
    }
    

    Now we needed to hook the ICallContextInitializer into WCF using a IServiceBehavior. The WcfFacility will add this to all WCF services if it’s registered on the container.

    public class WcfSessionPerRequestBehavior : IServiceBehavior
    {
        private readonly ISessionManager sessionManager; 
        private string[] dbAliases = { "nh.facility.default" };
        public string[] DbAliases
        {
            get { return dbAliases; } 
            set { dbAliases = value; }
        }
    
        public WcfSessionPerRequestBehavior(ISessionManager sessionManager)
        {
            sessionManager = sessionManager; 
        }
    
        public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        {
        }
      
        public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection endpoints, BindingParameterCollection bindingParameters)
        {
        }
      
        public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        {
            foreach (var cdb in serviceHostBase.ChannelDispatchers)
            {
                var channelDispatcher = cdb as ChannelDispatcher;
                if (null != channelDispatcher)
                {
                    foreach (var endpointDispatcher in channelDispatcher.Endpoints)
                    {
                        foreach (var dispatchOperation in endpointDispatcher.DispatchRuntime.Operations)
                        {
                            dispatchOperation.CallContextInitializers.Add(new WcfSessionPerRequestCallContextInitializer(sessionManager, _dbAliases));
                        }
                    }
                }
            }
        }
    }
    

    Lastly, register the behavior with the container and provide any aliases needed.

    container.Register(
        Component.For()
            .ImplementedBy()
            .DependsOn(new Hashtable { { "DbAliases", new[] { "nh.facility.default" } } })
        );
    
  • Unit Testing WCF Security with Castles WcfFacility

    Building off David Tchepak’s post “Faking WCF Authentication”, here’s some code to override the Service Host creation when using the Castle WcfFacility.

    The main integration points are a custom IWcfServiceModel and IServiceHostBuilder using the custom model. Both points have abstract base classes to build from. The model in this case is just an empty class used by the facility for finding the builder.

    public class TestSecurityServiceModel : WcfServiceModel<TestSecurityServiceModel>
    {
    }
    

    The service host builder is where we inject the authorization data we want available in our services. This host and authorization code are from David’s post, check out that for the TestAuthPolicy, TestPrincipal, and TestIdentity code. Here’s the builder.

    public class SecurityDefaultServiceHostBuilder : AbstractServiceHostBuilder<TestSecurityServiceModel>
    {
        public SecurityDefaultServiceHostBuilder(IKernel kernel)
            : base(kernel)
        {
        }
      
        protected override ServiceHost CreateServiceHost(ComponentModel model, TestSecurityServiceModel serviceModel, params Uri[] baseAddresses)
        {
            return CreateServiceHost(model, GetEffectiveBaseAddresses(serviceModel, baseAddresses));
        }
      
        protected override ServiceHost CreateServiceHost(ComponentModel model, Uri[] baseAddresses)
        {
            return InjectAuthorizationPolicies(new DefaultServiceHost(model, baseAddresses));
        }
      
        protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
        {
            return InjectAuthorizationPolicies(new DefaultServiceHost(serviceType, baseAddresses));
        }
      
        private static ServiceHost InjectAuthorizationPolicies(ServiceHost host)
        {
            host.Authorization.ExternalAuthorizationPolicies
                = new List<IAuthorizationPolicy> { new TestAuthPolicy() }.AsReadOnly();
      
            host.Authorization.PrincipalPermissionMode = PrincipalPermissionMode.Custom;
      
            return host;
        }
    }
    

    It’s creating an instance of the DefaultServiceHost and added the authorization properties needed before returning the created service host.

    Lastly, we need to integrate this with the WcfFacility. This is don’t at two points, first we need to tell the facility about our custom building and model with the AddServiceHostBuilder method.

    var facility = new WcfFacility();
    _container.AddFacility("wcf", facility);
    facility.Services.AddServiceHostBuilder<SecurityDefaultServiceHostBuilder, TestSecurityServiceModel>();
    

    Then when registering a service we set the ActAs model to the new TestSecurityServiceModel. This tells the facility to use the SecurityDefaultServiceHostBuilder to the service host.

    Component.For<IService>()
        .ImplementedBy<Service>()
        .Named("MyService")
        .ActAs(new TestSecurityServiceModel()
        .AddEndpoints(
            WcfEndpoint.BoundTo(new NetTcpBinding { PortSharingEnabled = true })
                .At(MyServiceAddress))),
    

    Now, when a client channel connects to this service the service host will be built by the new builder and have the authorization data needed to test the service.

    IService client = ChannelFactory<IService>.CreateChannel(
        new NetTcpBinding { PortSharingEnabled = true }, new EndpointAddress(MyServiceAddress));
    client.ServiceCall(1);
    

    This was used for unit/integration tests, but could be used to simply extend the service host when used in the WcfFacility.

  • Getting Started With The Spark View Engine

    Here’s some quick notes for getting started with the Spark View Engine on ASP.NET MVC, including setting up a container (Castle Windsor).

    Spark

    1. Reference the Spark assemblies Spark.dll, Spark.Web.Mvc.dll, and SparkLanguage.

    2. Configure and add the view engine in the MvcApplication class (full class below)

      var settings = new SparkSettings() .SetDebug(true) //.SetPageBaseType(“Your.NonDefault.BaseSparkView”) //.AddAssembly(“YourAssembly”) .AddNamespace(“System”) .AddNamespace(“System.Collections.Generic”) .AddNamespace(“System.Linq”) .AddNamespace(“System.Web.Mvc”) .AddNamespace(“System.Web.Mvc.Html”);

      ViewEngines.Engines.Add(new SparkViewFactory(settings));

    3. Add an Application.spark file to the Shared Views folder. The engine looks for this file as the site master layout file. It will also look for one with the controller name to use for views related to that controller, ex, Home.spark for the HomeController.

      <use content="title" />

    Apart from the general syntax, there are two things to note both regarding the Use tag. File looks for other views in the shared folder to render. While the content looks for content to render in it’s place which can be set in a sub view, as below. content=”view” is the view being rendered.

    1. The view, Index.spark, is just a normal view. The tag defines the content used for the title in the Application.spark view above.

      My Home Page </assets:title>

      ${"Hello world"}

      ${Guid.NewGuid().ToString("n")}

    The documentation on the Spark site is pretty good.

    Container Setup

    Thanks to Matt Halls post for pointing me to the integration point for adding a container to MVC for controller creation, the IControllerFactory.

    public class ControllerFactory : IControllerFactory
    {
        private readonly IWindsorContainer container; 
        public ControllerFactory(IWindsorContainer container)
        {
            container = container;
        }
    
        public IController CreateController(RequestContext requestContext, string controllerName)
        {
            return (IController) container.Resolve(controllerName.ToLowerInvariant() + "controller"); 
        }
    
        public void ReleaseController(IController controller)
        {
            container.Release(controller);
        }
    }
    

    Next setup the container in the MvcApplication class and set the factory in MVC with the ControllerBuilder.Current.SetControllerFactory method. Also register the controllers in the container.

    public class MvcApplication : HttpApplication
    {
        private WindsorContainer container; 
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
      
            routes.MapRoute(
                "Default",                                              // Route name
                "{controller}/{action}/{id}",                           // URL with parameters
                new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
            );
        }
      
        protected void Application_Start()
        {
            RegisterRoutes(RouteTable.Routes);
      
            ControllerBuilder.Current.SetControllerFactory(GetControllerFactory());
      
            var settings = new SparkSettings()
                .SetDebug(true)
                //.SetPageBaseType("Your.NonDefault.BaseSparkView")
                //.AddAssembly("YourAssembly")
                .AddNamespace("System")
                .AddNamespace("System.Collections.Generic")
                .AddNamespace("System.Linq")
                .AddNamespace("System.Web.Mvc")
                .AddNamespace("System.Web.Mvc.Html");
      
            ViewEngines.Engines.Add(new SparkViewFactory(settings));
        }
      
        private IControllerFactory GetControllerFactory()
        {
            container = new WindsorContainer();
      
            container.Register(AllTypes 
                  .Of<IController>()
                  .FromAssembly(typeof (HomeController).Assembly)
                  .Configure(c => c.Named(c.ServiceType.Name.ToLowerInvariant()).LifeStyle.Transient));
    
            container.AddFacility("logging", new LoggingFacility(LoggerImplementation.Trace));
      
            return new ControllerFactory(_container);
        }
    }
    
  • Changing The FluentNHibernate Id Conventions

    FluentNhibernate provides a bunch of Convention interfaces and base classes to override the default conventions. In this case our database naming requires Id columns to include the table name like ProductId for the Products table. Also, we’re using the HiLo algorithm. This can be done with a simple class the implements IIdConvention.

    public class FullIdNameConvention : IIdConvention
    {
        public void Apply(IIdentityInstance instance)
        {
            instance.Column(instance.EntityType.Name + "Id");
            instance.GeneratedBy.HiLo("100");
        }
    }
    

    The convention also required referenced id to be named as Id where the default is _id. This can be changed with the follow two classes.

    public class ManyToManyIdNameConvention : IHasManyToManyConvention
    {
        public void Apply(IManyToManyCollectionInstance instance)
        {
            instance.Key.Column(instance.EntityType.Name + "Id");
            instance.Relationship.Column(instance.Relationship.StringIdentifierForModel + "Id");
        }
    }
      
    public class ReferenceIdNameConvention : IReferenceConvention
    {
        public void Apply(IManyToOneInstance instance)
        {
            instance.Column(instance.Name + "Id");
        }
    }
    

    Some cases may require other interface implementations.

    Lastly, FluentNhibernate needs to know about these conventions which can be on the AutoPersistenceModel class passed to the NHibernate configuration. This is done in an implementation of IConfigurationBuilder passed to the Castle NHibernate Facility.

    var model = new AutoPersistenceModel()
        .AddEntityAssembly(typeof(Product).Assembly)
        .Where(t => t.Namespace.StartsWith(typeof(Product).Namespace))
        .Conventions.AddFromAssemblyOf<FullIdNameConvention>()
        .UseOverridesFromAssemblyOf<ProductMapping>()
        ;
      
    configuration.AddAutoMappings(model);
    

    More info can be found on the FluentNHibernate wiki.

  • NServiceBus 1.9 to 2.0 Upgrade Issues

    Here’s some notes about breaking changes we ran into upgrading from 1.9 to 2.0 of NServiceBus.

    • The distributor. This was mostly due to the fact that we had our own TopShelf implementation and had to remove that stuff.
    • The auto loading of message handlers now throws on dll’s and exe’s that are not .net assemblies. I think this is better, but some of our projects reference native dll’s and so we changed our code to explicitly load the needed assemblies with the Configure.With(params Assemblies[] assemblies) overload.
    • Configuration Files. A lot of code was moved from NServiceBus.dll to NServiceBus.Core.dll and the config references need to be updated to reflect that. This was often resulting in “ComponentActivator: could not instantiate NServiceBus.Unicast.UnicastBus” errors. Mostly this was a problem for us regarding logging, but I think many of the other configuration section handlers moved to NServiceBus.Core too.
      • Common.Logging.ConfigurationSectionHandler, NServiceBus.Core
      • Common.Logging.Log4Net.Log4NetLoggerFactoryAdapter, NServiceBus.Core
    • Installing into our existing WindsorContainer. This was a fairly easy and welcome change, consisting of mostly deleting code and passing our container in the Configure.With().CastleWindsorBuilder(containerInstance) method.
  • Overriding NServiceBus Configuration

    I needed to override the default NServiceBus configuration (app.config/web.config). This turns out to be really easy with the 2.0 NServiceBus release.

    First, when setting up the Bus I needed to call CustomConfigurationSource(myCustomSource) like this:

    var unicastBusConfig = configure.CastleWindsorBuilder(container) 
          .CustomConfigurationSource(myCustomSource)
          .XmlSerializer("http://tempuri.com")
          .MsmqTransport()
              .PurgeOnStartup(purgeOnStartup)
          .UnicastBus();
    

    Second, I needed to implement IConfigurationSource on my myCustomSource class. This default implementation takes the passed in type and creates the configuration section handler of that type. To override a specific configuration section you can create an instance of that type, set it’s properties and return it. Otherwise, create and return the class without overriding any values.

    There are four types of configuration sections used in NServiceBus currently, MsmqSubscriptionStorageConfig, DBSubscriptionStorageConfig, MsmqTransportConfig, and UnicastBusConfig.

    public T GetConfiguration() where T : class
    {
        if (typeof(T) == typeof(MsmqSubscriptionStorageConfig))
            return ConfigurationManager.GetSection(typeof(T).Name) as T;
      
        if (typeof(T) == typeof(DBSubscriptionStorageConfig))
            return ConfigurationManager.GetSection(typeof(T).Name) as T;
      
        if (typeof(T) == typeof(MsmqTransportConfig))
            return MsmqTransportConfiguration() as T;
      
        if (typeof(T) == typeof(UnicastBusConfig))
            return UnicastBusConfiguration() as T;
      
        return null;
    }
    

    Finally, the MsmqTransportConfiguration method creates a instance of MsmqTransportConfig and sets it’s values. In this case to fields that are passed in to the constructor, but it could be some other strategy or custom settings class.

    private MsmqTransportConfig MsmqTransportConfiguration()
    {
        return new MsmqTransportConfig
                   {
                       ErrorQueue = errorQueue, 
                       InputQueue = inputQueue,
                       MaxRetries = maxRetries, 
                       NumberOfWorkerThreads = numberOfWorkerThreads
                   };
    }