Archive for the ‘Programming’ Category.

Navigating to the Current Page on WP7

Sometimes you want to be able to “reset” the page you’re on. For example, the page is a form with a bunch of data that gets filled out. When the user clicks save, you prompt them and ask if they want to add another. If so, then you need to reset the page back to it’s original state. This sounds easy enough to do straight from code, but resetting everything isn’t always as easy as it sounds.

I’ve found that navigating to the current page works the best. Then the page runs as new, and everything gets setup properly without any extra code.

By default, you can’t navigate to the same page; it just doesn’t do anything. The trick here is to make the URI unique.

1 2 3
var uri = new Uri( string.Format( "{0}?unique={1}", "SamePage.xaml, Guid.NewGuid() ), UriKind.RelativeOrAbsolute );
RemoveBackEntry = true;
NavigationService.Navigate( uri );
view raw Example1.cs hosted with ❤ by GitHub

You may also have noticed the line ‘RemoveBackEntry = true;’. When navigating back to yourself, you don’t want the page to keep getting added to the back stack. You can see how to remove the back entry in my previous post Navigating with MVVM on WP7.

Navigation with MVVM on WP7

One thing that isn’t very straight forward when using MVVM on WP7 is how to navigate around. Many articles I’ve seen have said to use a messaging (pub/sub) system like the EventAggregator in Prism. I personally found this to not work the greatest. Plus, you want to be able to use the NavigationContext to grab things from the URL. The approach I came up with is pretty simple in my opinion and works just like it does if you’re using code-behind.

The view model base class will be setup just like a code-behind file so we can access the NavigationService, NavigationContext, and the navigation events.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
using System.Windows.Navigation;
using Microsoft.Practices.Prism.ViewModel;
 
namespace RememberIt.WP7.App.ViewModels
{
public abstract class ViewModelBase : NotificationObject
{
protected bool RemoveBackEntry { get; set; }
 
public NavigationService NavigationService { get; set; }
 
public NavigationContext NavigationContext { get; set; }
 
public virtual void OnNavigatedTo( NavigationEventArgs e ) {}
 
public virtual void OnNavigatingFrom( NavigatingCancelEventArgs e ) {}
 
public virtual void OnNavigatedFrom( NavigationEventArgs e )
{
if( RemoveBackEntry )
{
RemoveBackEntry = false;
NavigationService.RemoveBackEntry();
}
}
}
}
view raw Example2.cs hosted with ❤ by GitHub

For this to work, you’ll need a PageBase class every view will inherit from. I’m sure there is a slick way to hook into every page without doing this, but I haven’t taken the time to figure it out yet.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
using Microsoft.Phone.Controls;
using RememberIt.WP7.App.ViewModels;
 
namespace RememberIt.WP7.App.Views
{
public class PageBase : PhoneApplicationPage
{
protected PageBase()
{
Loaded += PageBaseLoaded;
}
 
private void PageBaseLoaded( object sender, System.Windows.RoutedEventArgs e )
{
var viewModel = DataContext as ViewModelBase;
if( viewModel != null )
{
viewModel.NavigationService = NavigationService;
}
}
 
protected override void OnNavigatedTo( System.Windows.Navigation.NavigationEventArgs e )
{
base.OnNavigatedTo( e );
var viewModel = DataContext as ViewModelBase;
if( viewModel != null )
{
viewModel.NavigationContext = NavigationContext;
viewModel.OnNavigatedTo( e );
}
}
 
protected override void OnNavigatingFrom( System.Windows.Navigation.NavigatingCancelEventArgs e )
{
base.OnNavigatingFrom( e );
var viewModel = DataContext as ViewModelBase;
if( viewModel != null )
{
viewModel.NavigationContext = NavigationContext;
viewModel.OnNavigatingFrom( e );
}
}
 
protected override void OnNavigatedFrom( System.Windows.Navigation.NavigationEventArgs e )
{
base.OnNavigatedFrom( e );
var viewModel = DataContext as ViewModelBase;
if( viewModel != null )
{
viewModel.NavigationContext = NavigationContext;
viewModel.OnNavigatedFrom( e );
}
}
}
}
view raw PageBase.cs hosted with ❤ by GitHub

So, when the page loads the NavigationService is set to the view model. When any of the navigation events occur, they are also called on the view model while setting the NavigationContext.

 

Audit Trail with NHibernate Using a Custom log4net Appender

I was originally using NHibernate event listeners to do an audit trail, and I might post on that some day. My issue with that was, you get your entities when intercepting. You can save off what’s going with your entites, but I really wanted to save the actual query that NHibernate generates. I wanted to log the same thing that NHProf shows; the actual SQL query.

The way to do this is to create a custom log4net appender that inserts info into your audit table. You need to hook into the NHibernate logs to do this. This is how I did it.

First, create the audit table.

1 2 3 4 5 6 7 8 9 10 11
CREATE TABLE [dbo].[Audit]
(
[Id] INT NOT NULL IDENTITY,
[User] NVARCHAR( 100 ) NOT NULL,
[Trail] NVARCHAR( MAX ) NOT NULL,
[Created] DATETIME NOT NULL
)
 
ALTER TABLE [dbo].[Audit]
ADD CONSTRAINT [PK_Audit_Id]
PRIMARY KEY (Id)
view raw Audit.sql hosted with ❤ by GitHub

Next, create the log4net appender.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
public class NHibernateAuditAppender : AppenderSkeleton
{
private static IKernel kernel;
 
protected override void Append( LoggingEvent loggingEvent )
{
#if !DEBUG
if( loggingEvent.RenderedMessage.StartsWith( "SELECT" ) )
{
return;
}
#endif
 
var session = kernel.Get<ISession>();
var audit = new Audit
{
Created = DateTime.UtcNow,
Trail = loggingEvent.RenderedMessage,
User = Thread.CurrentPrincipal.Identity.Name
};
session.Save( audit );
}
}
view raw gistfile1.cs hosted with ❤ by GitHub

I am using Ninject to get the current NHibernate session being used. All that you really need to know is, get a session from the session factory. The Append method passes in a LoggingEvent. The data that you need from here is the RenderedMessage. The is the formatted message that is to be logged. Create an audit object and save it off to the database. This assumes that you have a mapping set up for for the Audit object to the Audit table. Next, we need to actually hook into the NHibernate logs.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
public class NHibernateAuditAppender : AppenderSkeleton
{
private static IKernel kernel;
 
protected override void Append( LoggingEvent loggingEvent )
{
#if !DEBUG
if( loggingEvent.RenderedMessage.StartsWith( "SELECT" ) )
{
return;
}
#endif
 
var session = kernel.Get<ISession>();
var audit = new Audit
{
Created = DateTime.UtcNow,
Trail = loggingEvent.RenderedMessage,
User = Thread.CurrentPrincipal.Identity.Name
};
session.Save( audit );
}
 
public static void RegisterAppender( IKernel kernel )
{
NHibernateAuditAppender.kernel = kernel;
 
var repository = (Hierarchy)LogManager.GetRepository();
var appender = new NHibernateAuditAppender { Name = "NHibernateAuditAppender" };
var logger = (Logger)repository.GetLogger( "NHibernate.SQL" );
logger.Level = Level.Debug;
logger.Additivity = false;
logger.AddAppender( appender );
appender.ActivateOptions();
repository.Configured = true;
}
}

The RegisterAppender static method was added. Here we get the NHibernate.SQL logger. This is the logger that outputs the actual query that NHibernate generates. Add our appender to the logger, and it’s basically done. You can lookup the other details if you like. :)

Getting Arguments from a Running Process

If you get all the running processes using .NET, the Process.StartInfo.Arguments will be empty.

1
var processes = Process.GetProcessesByName( "MyProcess" );
view raw File1.cs hosted with ❤ by GitHub

This seems a little odd, but whatever, let’s find a workaround. Here is some code to get the arguments of a process.

1 2 3 4 5 6
var managementObjectSearcher = new ManagementObjectSearcher( "select CommandLine from Win32_Process where Name='MyProcess.exe'" );
var managementObjects = managementObjectSearcher.Get();
foreach( var managementObject in managementObjects )
{
var command = (string)managementObject["CommandLine"];
}
view raw File2.cs hosted with ❤ by GitHub

Command is the full command line used to start the process. This includes the path and all arguments.

Setting Up WCF with Multiple Services and Multiple Databases Using NHibernate and Ninject

This is a tutorial on how to setup WCF using NHibernate and Ninject with multiple databases and services. I’ve seen many examples of how to setup WCF with NHibernate, or Ninject, but not with both. None of the examples I’ve seen have used multiple services or multiples databases either. I had to do this, so I thought I’d share. We’ll setup this code as if we’re creating some sort of blog application.

First, create an assembly for each of the following: business logic, services, service contracts, and the service host.

We want to separate all these into different assemblies so we don’t have issues with circular dependencies. The other option is to have everything in a single assembly, but that usually isn’t an option, or a very good one for that matter.

Contracts

The contract assembly is where we keep all the contracts, or interfaces, that are used in our services. This makes it so that the services can reference and use the contracts, and so can a client to the services. If the service is visible to projects outside of yours, you can just give them the contract assembly.

Let’s create a service contract, and some data contracts for our blog application. I put them into folders to separate the service contracts from the data contracts.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
using System.Collections.Generic;
using System.ServiceModel;
using Wnn.Service.Contract.DataContracts;
 
namespace Wnn.Service.Contract.ServiceContracts
{
[ServiceContract]
public interface IBlogService
{
[OperationContract]
Post GetPostById( int id );
[OperationContract]
User GetUserById( int id );
[OperationContract]
User GetUserByUserNameAndPassword( string userName, string password );
[OperationContract]
List<Post> GetPosts();
[OperationContract]
List<Post> GetPostsFromAuthor( string userName );
}
}
view raw IBlogService.cs hosted with ❤ by GitHub
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
Post.cs
 
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
 
namespace Wnn.Service.Contract.DataContracts
{
[DataContract]
public class Post
{
[DataMember]
public int Id { get; set; }
[DataMember]
public string Title { get; set; }
[DataMember]
public string Content { get; set; }
[DataMember]
public DateTime Created { get; set; }
[DataMember]
public string Author { get; set; }
[DataMember]
public List<string> Tags { get; set; }
}
}
view raw Post.cs hosted with ❤ by GitHub
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
using System.Runtime.Serialization;
 
namespace Wnn.Service.Contract.DataContracts
{
[DataContract]
public class User
{
[DataMember]
public int Id { get; set; }
[DataMember]
public string UserName { get; set; }
[DataMember]
public string Email { get; set; }
[DataMember]
public string FirstName { get; set; }
[DataMember]
public string LastName { get; set; }
}
}
view raw User.cs hosted with ❤ by GitHub

Business Logic

Let’s create our business objects, repositories to access our database, and all the NHibernate guts. We don’t have a data layer here because NHibernate IS our data layer. There could still be a use of separating some stuff out into a data layer, but I will not be doing that. References will need to be added to NHibernate.dll, FluentNHibernate.dll, NHibernate.ByteCode.LinFu.dll, and NHibernate.Linq.dll.

Let’s create our POCO (plain old CLR object) business objects. All members need to be virtual so NHibernate can use them.

In the password property we want to encrypt any password that gets set.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
using System;
using System.Security.Cryptography;
using System.Text;
 
namespace Wnn.Business.Objects
{
public class User
{
private string password;
 
public virtual int Id { get; protected set; }
public virtual string UserName { get; set; }
public virtual string Email { get; set; }
public virtual string Password
{
get { return password; }
set
{
var md5 = MD5.Create();
var passwordBytes = Encoding.UTF8.GetBytes( value );
md5.ComputeHash( passwordBytes );
password = Convert.ToBase64String( md5.Hash );
}
}
 
public virtual string FirstName { get; set; }
public virtual string LastName { get; set; }
}
}
view raw User2.cs hosted with ❤ by GitHub
1 2 3 4 5 6 7 8 9
namespace Wnn.Business.Objects
{
public class Tag
{
public virtual int Id { get; protected set; }
public virtual string Name { get; set; }
public virtual Post Post { get; set; }
}
}
view raw Tag.cs hosted with ❤ by GitHub
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
using System;
using System.Collections.Generic;
 
namespace Wnn.Business.Objects
{
public class Post
{
public virtual int Id { get; protected set; }
public virtual string Title { get; set; }
public virtual string Content { get; set; }
public virtual DateTime Created { get; set; }
public virtual User Author { get; set; }
public virtual List<Tag> Tags { get; set; }
 
public virtual void AddTag( Tag tag )
{
tag.Post = this;
Tags.Add( tag );
}
}
}
view raw Post2.cs hosted with ❤ by GitHub

The AddTag method is used to set both sides of the object association. Otherwise NHibernate will not save them properly if a tag is added to the tags list.

Let’s create our NHibernate mapping files now. I use FluentNHibernate to do this.

Since we’re using a backing field for the Password property, we need to have NHibernate use that instead. We don’t want NHibernate to use the property because the stored hash would get hashed again when set.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
using FluentNHibernate.Mapping;
using Wnn.Business.Objects;
 
namespace Wnn.Business.Mappings
{
public class UserMap : ClassMap<User>
{
public UserMap()
{
SetupMapping();
}
 
private void SetupMapping()
{
Table( "Users" );
Id( m => m.Id );
Map( m => m.Email );
Map( m => m.FirstName );
Map( m => m.LastName );
Map( m => m.Password ).Access.CamelCaseField();
Map( m => m.UserName );
}
}
}
view raw UserMap.cs hosted with ❤ by GitHub
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
using FluentNHibernate.Mapping;
using Wnn.Business.Objects;
 
namespace Wnn.Business.Mappings
{
public class TagMap : ClassMap<Tag>
{
public TagMap()
{
SetupMapping();
}
 
private void SetupMapping()
{
Table( "Tags" );
Id( m => m.Id );
Map( m => m.Name );
References( m => m.Post, "PostId" );
}
}
}
view raw TagMap.cs hosted with ❤ by GitHub
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
using FluentNHibernate.Mapping;
using Wnn.Business.Objects;
 
namespace Wnn.Business.Mappings
{
public class PostMap : ClassMap<Post>
{
public PostMap()
{
SetupMapping();
}
 
private void SetupMapping()
{
Table( "Posts" );
Id( m => m.Id );
Map( m => m.Content );
Map( m => m.Title );
References( m => m.Author, "UserId" );
HasMany( m => m.Tags )
.Inverse()
.Cascade.AllDeleteOrphan()
.KeyColumns.Add( "PostId" )
.Fetch.Subselect();
}
}
}
view raw PostMap.cs hosted with ❤ by GitHub

Next we’re going to setup our repositories. This is where we access our data. Before we can do that though, we need to create a SessionManager object. SessionManager is just a wrapper around the NHibernate ISession object to allow for easier unit testing. We’re not hiding the fact that we’re using NHibernate though. The SessionManager wrapper still returns NHibernate objects. This could be completely abstracted so it didn’t matter which ORM or data layer is being used.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
using System;
using System.Data;
using System.Linq;
using NHibernate;
using NHibernate.Linq;
 
namespace Wnn.Business
{
public class SessionManager
{
private readonly ISession session;
 
public SessionManager( ISession session )
{
if( session == null )
{
throw new ArgumentNullException( "session" );
}
 
this.session = session;
}
 
public virtual IQueryable<T> Linq<T>()
{
return session.Linq<T>();
}
 
public virtual T Get<T>( int id )
{
return session.Get<T>( id );
}
 
public virtual ISQLQuery CreateSqlQuery( string queryString )
{
return session.CreateSQLQuery( queryString );
}
 
public virtual void SaveOrUpdate( object obj )
{
session.SaveOrUpdate( obj );
}
 
public virtual void Delete( object obj )
{
session.Delete( obj );
}
 
public virtual ITransaction BeginTransaction()
{
return session.BeginTransaction();
}
 
public virtual IDbConnection Close()
{
return session.Close();
}
 
public virtual void Dispose()
{
session.Dispose();
}
}
}
view raw SessionManager.cs hosted with ❤ by GitHub

Now we can create the repositories and a base repository class for common methods.

We put any common methods in the base class.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
using System.Collections.Generic;
using System.Linq;
 
namespace Wnn.Business.Repositories
{
public abstract class RepositoryBase<T>
{
protected SessionManager SessionManager { get; set; }
 
protected RepositoryBase( SessionManager sessionManager )
{
SessionManager = sessionManager;
}
 
public T Get( int id )
{
return SessionManager.Get<T>( id );
}
 
public List<T> GetAll()
{
return SessionManager.Linq<T>().ToList();
}
 
public void SaveOrUpdate( T obj )
{
SessionManager.SaveOrUpdate( obj );
}
 
public void Delete( T obj )
{
SessionManager.Delete( obj );
}
}
}
view raw RepositoryBase.cs hosted with ❤ by GitHub
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
using System.Linq;
using Wnn.Business.Objects;
 
namespace Wnn.Business.Repositories
{
public class UserRepository : RepositoryBase<User>
{
public UserRepository( SessionManager sessionManager ) : base( sessionManager ){}
 
public User GetByUserNameAndPassword( string userName, string password )
{
return ( from u in SessionManager.Linq<User>()
where u.UserName == userName && password == u.Password
select u ).SingleOrDefault();
}
}
}
view raw UserRepository.cs hosted with ❤ by GitHub
1 2 3 4 5 6 7 8 9
using Wnn.Business.Objects;
 
namespace Wnn.Business.Repositories
{
public class TagRepository : RepositoryBase<Tag>
{
public TagRepository( SessionManager sessionManager ) : base( sessionManager ){}
}
}
view raw TagRepository.cs hosted with ❤ by GitHub
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
using System.Collections.Generic;
using System.Linq;
using Wnn.Business.Objects;
 
namespace Wnn.Business.Repositories
{
public class PostRepository : RepositoryBase<Post>
{
public PostRepository( SessionManager sessionManager ) : base( sessionManager ){}
 
public List<Post> GetAllForUser( string userName )
{
return ( from p in SessionManager.Linq<Post>()
where p.Author.UserName == userName
select p ).ToList();
}
}
}
view raw PostRepository.cs hosted with ❤ by GitHub

Services

Now that we have our repositories setup, we can implement the services that will use the repositories.

We need to set the InstanceContextMode to PerCall. This makes it so WCF will create a new context instance per service call. This sets up NHibernate nicely because we can then start a transaction at the beginning of every service method call, and end the transaction at the end of the call, rolling back if an error occurred. More on that later.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using Wnn.Business.Repositories;
using Wnn.Service.Contract.DataContracts;
using Wnn.Service.Contract.ServiceContracts;
 
namespace Wnn.Service
{
[ServiceBehavior( InstanceContextMode = InstanceContextMode.PerCall )]
public class BlogService : IBlogService
{
private readonly UserRepository userRepository;
private readonly PostRepository postRepository;
private readonly TagRepository tagRepository;
 
public BlogService( UserRepository userRepository, PostRepository postRepository, TagRepository tagRepository )
{
this.userRepository = userRepository;
this.postRepository = postRepository;
this.tagRepository = tagRepository;
}
 
public Post GetPostById( int id )
{
return ConvertPost( postRepository.Get( id ) );
}
 
public User GetUserById( int id )
{
return ConvertUser( userRepository.Get( id ) );
}
 
public User GetUserByUserNameAndPassword( string userName, string password )
{
return ConvertUser( userRepository.GetByUserNameAndPassword( userName, password ) );
}
 
public List<Post> GetPosts()
{
return ( from p in postRepository.GetAll()
select ConvertPost( p ) ).ToList();
}
 
public List<Post> GetPostsFromAuthor( string userName )
{
return ( from p in postRepository.GetAllForUser( userName )
select ConvertPost( p ) ).ToList();
}
 
private static User ConvertUser( Business.Objects.User userData )
{
User user = null;
if( userData != null )
{
user = new User
{
Email = userData.Email,
FirstName = userData.FirstName,
Id = userData.Id,
LastName = userData.LastName,
UserName = userData.UserName,
};
}
return user;
}
 
private static Post ConvertPost( Business.Objects.Post postData )
{
Post post = null;
if( postData != null )
{
post = new Post
{
Author = postData.Author.UserName,
Content = postData.Content,
Created = postData.Created,
Id = postData.Id,
Title = postData.Title,
Tags = ( from t in postData.Tags
select t.Name ).ToList()
};
}
return post;
}
}
}
view raw BlogService.cs hosted with ❤ by GitHub

Service Host

The service host is what actually starts up all of our services. In this case, just one service, but this is being created so we can have as many as we want.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
using System.Collections.Generic;
using System.ServiceModel;
 
namespace Wnn.Service.Host
{
public class ServiceHostEngine
{
private readonly List<ServiceHost> serviceHosts = new List<ServiceHost>();
 
public ServiceHostEngine()
{
// We can have multiple services listed here.
// We could actually have a list of services in a config
// file that is dynamically loaded here also.
serviceHosts.Add( new ServiceHost( typeof( BlogService ) ) );
}
 
public void Start()
{
foreach( var serviceHost in serviceHosts )
{
serviceHost.Open();
}
}
 
public void Stop()
{
foreach( var serviceHost in serviceHosts )
{
serviceHost.Close();
}
}
}
}
view raw ServiceHostEngine.cs hosted with ❤ by GitHub

We are now to a part where Ninject is used to create the NHibernate session instances. We need to create a factory for creating NHibernate SessionFactories. We need a factory for every database that is being used. So, we need a SessionFactoryFactory. This will be back in our business layer.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
using System.Collections.Generic;
using FluentNHibernate.Cfg;
using NHibernate;
 
namespace Wnn.Business
{
public static class SessionFactoryFactory
{
private static readonly object locker = new object();
private static readonly Dictionary<string, ISessionFactory> sessionFactories = new Dictionary<string, ISessionFactory>();
 
public static ISessionFactory GetSessionFactory( string connectionStringKey )
{
ISessionFactory sessionFactory;
sessionFactories.TryGetValue( connectionStringKey, out sessionFactory );
 
// Double check locking is used here because
// WCF could have many instances accessing this
// code at the same time.
if( sessionFactory == null )
{
lock( locker )
{
sessionFactories.TryGetValue( connectionStringKey, out sessionFactory );
if( sessionFactory == null )
{
sessionFactory = Fluently.Configure()
.Database(
FluentNHibernate.Cfg.Db.MsSqlConfiguration.MsSql2005.ConnectionString(
c => c.FromConnectionStringWithKey( connectionStringKey ) )
.ProxyFactoryFactory( "NHibernate.ByteCode.LinFu.ProxyFactoryFactory, NHibernate.ByteCode.LinFu" ) )
.Mappings( m => m.FluentMappings.AddFromAssembly( typeof( SessionFactoryFactory ).Assembly ) )
.ExposeConfiguration( cfg => cfg.SetProperty( "generate_statistics", "true" ) )
.ExposeConfiguration( cfg => cfg.SetProperty( "adonet.batch_size", "10" ) )
.BuildSessionFactory();
 
sessionFactories[connectionStringKey] = sessionFactory;
}
}
}
 
return sessionFactory;
}
}
}

Now that we are able to create NHibernate sessions, let’s setup Ninject to create the ISession an SessionManager objects for us. We need to pass the connection string in to our Ninject setup so the SessionFactoryFactory can use the correct database connection. We will be creating a new Ninject kernel each WCF call, passing in the connection string.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
using NHibernate;
using Ninject.Modules;
using Wnn.Business;
 
namespace Wnn.Service.Host
{
public class NinjectSetup : NinjectModule
{
private readonly string connectionStringKey;
 
public NinjectSetup( string connectionStringKey )
{
this.connectionStringKey = connectionStringKey;
}
 
public override void Load()
{
Bind<ISession>()
.ToMethod( ctx => SessionFactoryFactory.GetSessionFactory( connectionStringKey ).OpenSession() )
.InSingletonScope();
 
Bind<SessionManager>()
.ToSelf()
.InSingletonScope();
}
}
}
view raw NinjectSetup.cs hosted with ❤ by GitHub

Now we can create our instance provider. The provider is what creates the instances that WCF uses. This gets called for every service method call because we used InstanceContextMode.PerCall for our services.

In the GetInstance method (which again happens per call), we create a Ninject kernel that we can use to create our objects for us. A SessionManager is created and a transaction is started. A transaction is meant to be used for a unit of work. Our unit of work here is a single service method call. A new service instance is then created by Ninject. This means that all our repositories in the constructor of the services will be injected for us.

The ReleaseInstance method is then called when the request is complete. In here we commit our transaction. If there are any errors, they are rolled back. The session is then closed.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
using System;
using System.Runtime.Remoting.Messaging;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Dispatcher;
using NHibernate;
using Ninject;
using Wnn.Business;
 
namespace Wnn.Service.Host
{
public class NHibernateInstanceProvider : IInstanceProvider
{
private const string sessionKey = "ThreadSession";
private const string transactionKey = "ThreadTransaction";
private readonly Type serviceType;
 
private static SessionManager SessionManager
{
get { return CallContext.GetData( sessionKey ) as SessionManager; }
set { CallContext.SetData( sessionKey, value ); }
}
 
private static ITransaction Transaction
{
get { return CallContext.GetData( transactionKey ) as ITransaction; }
set { CallContext.SetData( transactionKey, value ); }
}
 
public NHibernateInstanceProvider( Type serviceType )
{
this.serviceType = serviceType;
}
 
public object GetInstance( InstanceContext instanceContext )
{
return GetInstance( instanceContext, null );
}
 
public object GetInstance( InstanceContext instanceContext, Message message )
{
var connectionStringKey = GetConnectionStringKey( serviceType );
 
var kernel = new StandardKernel( new NinjectSetup( connectionStringKey ) );
 
SessionManager = kernel.Get<SessionManager>();
Transaction = SessionManager.BeginTransaction();
 
var instance = kernel.Get( serviceType );
 
return instance;
}
 
public void ReleaseInstance( InstanceContext instanceContext, object instance )
{
try
{
Transaction.Commit();
}
catch
{
Transaction.Rollback();
}
finally
{
SessionManager.Close();
SessionManager.Dispose();
}
}
 
private static string GetConnectionStringKey( Type serviceType )
{
// All of our database connections should
// go here. We could also put all of these types
// into a config file and load them dynamically.
string connectionStringKey;
if( serviceType == typeof( BlogService ) )
{
connectionStringKey = "Dashboard";
}
else
{
throw new Exception( "Service type '{0}' does not match any database connection." );
}
return connectionStringKey;
}
}
}

Now you may be wondering how all of this is setup. How do we let WCF know that it should use our instance provider instead? There are a couple custom configuration classes we need to create and we need to add our provider to the WCF configuration. Whatever app is running the WCF service; console app, windows service, or web app; a custom behavior needs to be added to it. In the services section, we setup our service with our custom element.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
<system.serviceModel>
<extensions>
<behaviorExtensions>
<add name="nhibernateServiceBehavior" type="Wnn.Service.Host.NHibernateBehaviorExtensionElement, Wnn.Service.Host, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</behaviorExtensions>
</extensions>
 
<behaviors>
<serviceBehaviors>
<behavior name="nhibernateServiceBehavior">
<nhibernateServiceBehavior />
<serviceMetadata />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="HttpEnableBehavior">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
 
<services>
<service name="Wnn.Service.BlogService" behaviorConfiguration="nhibernateServiceBehavior">
<host>
<baseAddresses>
<add baseAddress="net.tcp://localhost:8761/Services/" />
</baseAddresses>
</host>
<endpoint address="Blog" binding="netTcpBinding" contract="Wnn.Service.Contract.ServiceContracts.IBlogService" />
</service>
</services>
</system.serviceModel>
view raw web.config.xml hosted with ❤ by GitHub

The custom element returns a new instance of our service behavior.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
using System;
using System.ServiceModel.Configuration;
 
namespace Wnn.Service.Host
{
public class NHibernateBehaviorExtensionElement : BehaviorExtensionElement
{
protected override object CreateBehavior()
{
return new NHibernateServiceBehavior();
}
 
public override Type BehaviorType
{
get { return typeof( NHibernateServiceBehavior ); }
}
}
}

The service behavior is what actually creates out custom instance provider, passing in the service that is being used.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
using System;
using System.Collections.ObjectModel;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
 
namespace Wnn.Service.Host
{
public class NHibernateServiceBehavior : Attribute, IServiceBehavior
{
public void Validate( ServiceDescription serviceDescription, ServiceHostBase serviceHostBase )
{
}
 
public void AddBindingParameters( ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters )
{
}
 
public void ApplyDispatchBehavior( ServiceDescription serviceDescription, ServiceHostBase serviceHostBase )
{
foreach( var channelDispatcherBase in serviceHostBase.ChannelDispatchers )
{
var channelDispatcher = channelDispatcherBase as ChannelDispatcher;
if( channelDispatcher == null )
{
continue;
}
 
foreach( var ed in channelDispatcher.Endpoints )
{
ed.DispatchRuntime.InstanceProvider = new NHibernateInstanceProvider( serviceDescription.ServiceType );
}
}
}
}
}

The WCF setup is now complete. We able to have multiple services running and use multiple databases. All the services objects are created by Ninject. Our WCF application is now a lot more unit testable that it was before. This may seem like a lot of work to setup, but once it’s done, everything else is a breeze. You will be able to add services and databases easily, and you don’t have to worry about creating your objects in your service.

The last step is to actually host this service in a console app, windows service or web app. You are limited to only using HTTP bindings if you choose to use an IIS hosted service. All you have to do then is to create an instance of the ServiceHostEngine, and start it.

Here is an example of a console app:

1 2 3 4 5 6 7 8 9 10 11 12 13
namespace Wnn.Service.Host.Console
{
class Program
{
static void Main( string[] args )
{
var service = new ServiceHostEngine();
service.Start();
System.Console.WriteLine( "Press any key to stop the services" );
System.Console.ReadKey();
}
}
}
view raw Program.cs hosted with ❤ by GitHub

I put the code up on github. http://github.com/JoshClose/WcfNhibernateNinjectExample

Programmatically Taking a Full Web Page Screenshot

I needed to programmatically take a screenshot of a full web page, and not just the visible area. When I set out to accomplish this task, I didn’t realize how tough it was actually going to be.

The reason it was tough wasn’t because it was hard to do, but that there were many different ways of doing it, and each had different results. Some ways would only capture the visible screen. Some would be missing backgrounds. Some wouldn’t capture pages that loaded with JavaScript, such as google.com.

I was able to find a way that has worked on every site I’ve tested so far that is a combination of many of the other methods I’ve found. This way also does not require any assembly outside of the System namespace.

The code is pretty small and self explanatory, so here is how I did it.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
 
public class ScreenShot
{
[ComImport]
[InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]
[Guid( "0000010d-0000-0000-C000-000000000046" )]
private interface IViewObject
{
[PreserveSig]
int Draw( [In] [MarshalAs( UnmanagedType.U4 )] int dwDrawAspect, int lindex, IntPtr pvAspect,
[In] /*tagDVTARGETDEVICE*/ IntPtr ptd, IntPtr hdcTargetDev, IntPtr hdcDraw,
[In] /*COMRECT*/ Rectangle lprcBounds, [In] /*COMRECT*/ IntPtr lprcWBounds, IntPtr pfnContinue,
[In] int dwContinue );
 
[PreserveSig]
int GetColorSet( [In] [MarshalAs( UnmanagedType.U4 )] int dwDrawAspect, int lindex, IntPtr pvAspect,
[In] /*tagDVTARGETDEVICE*/ IntPtr ptd, IntPtr hicTargetDev, [Out] /*tagLOGPALETTE*/ IntPtr ppColorSet );
 
[PreserveSig]
int Freeze( [In] [MarshalAs( UnmanagedType.U4 )] int dwDrawAspect, int lindex, IntPtr pvAspect, [Out] IntPtr pdwFreeze );
 
[PreserveSig]
int Unfreeze( [In] [MarshalAs( UnmanagedType.U4 )] int dwFreeze );
 
void SetAdvise( [In] [MarshalAs( UnmanagedType.U4 )] int aspects, [In] [MarshalAs( UnmanagedType.U4 )] int advf,
[In] [MarshalAs( UnmanagedType.Interface )] /*IAdviseSink*/ IntPtr pAdvSink );
 
void GetAdvise( [In] [Out] [MarshalAs( UnmanagedType.LPArray )] int[] paspects,
[In] [Out] [MarshalAs( UnmanagedType.LPArray )] int[] advf,
[In] [Out] [MarshalAs( UnmanagedType.LPArray )] /*IAdviseSink[]*/ IntPtr[] pAdvSink );
}
 
public static Bitmap Create( string url )
{
using( var webBrowser = new WebBrowser() )
{
webBrowser.ScrollBarsEnabled = false;
webBrowser.ScriptErrorsSuppressed = true;
webBrowser.Navigate( url );
 
while( webBrowser.ReadyState != WebBrowserReadyState.Complete )
{
Application.DoEvents();
}
 
webBrowser.Width = webBrowser.Document.Body.ScrollRectangle.Width;
webBrowser.Height = webBrowser.Document.Body.ScrollRectangle.Height;
 
var bitmap = new Bitmap( webBrowser.Width, webBrowser.Height );
var graphics = Graphics.FromImage( bitmap );
var hdc = graphics.GetHdc();
 
var rect = new Rectangle( 0, 0, webBrowser.Width, webBrowser.Height );
 
var viewObject = (IViewObject)webBrowser.Document.DomDocument;
viewObject.Draw( 1, -1, (IntPtr)0, (IntPtr)0, (IntPtr)0, hdc, rect, (IntPtr)0, (IntPtr)0, 0 );
 
graphics.ReleaseHdc( hdc );
 
return bitmap;
}
}
}
view raw ScreenShot.cs hosted with ❤ by GitHub

From here, it’s pretty simple to start adding features like min/max width/height, a capture delay for pages that have Flash on them, etc.

Note: For Flash to work properly, you need to set the project type to x86. If running on a 64-bit system and the project is set to “Any CPU”, Flash won’t work because it’s not compatible with 64-bit systems.

Dynamically Loading Partial Views with the Spark View Engine

Loading a partial view is easy with Spark. There are basically two ways:

1
<use file="MyPartialView" />
view raw File1.xml hosted with ❤ by GitHub

And if you have name your files using the _MyPartialView.spark convention:

1
<MyPartialView />
view raw File2.xml hosted with ❤ by GitHub

Now what if you don’t know the name of the partial file until runtime and need to dynamically render the view? As far as I know, there is no way of doing this in Spark. How you can get around this is by doing some inline code using ASP.NET MVCs RenderPartial method.

1
#Html.RenderPartial( myPartialViewVariable );
view raw File3.cs hosted with ❤ by GitHub

This is assuming myPartialViewVariable is a string variable with the name of the view that needs to be rendered.

Update:

When you use ASP.NET’s Html.RenderPartial, your data isn’t automatically passed along to the spark view. To pass your data along, use the ViewData dictionary, like you would in a controller.

1 2 3 4 5 6
<ul>
<li each="var item in items">
#ViewData["item"] = item;
#Html.RenderPartial( "path/to/" + item.Name );
</li>
</ul>
view raw File4.xml hosted with ❤ by GitHub

In the partial view, use the <viewdata /> spark attribute like you normally would in a spark file.

1
<viewdata item="Item" />
view raw File5.xml hosted with ❤ by GitHub

FireFox is Slow When Using Visual Studios ASP.NET Development Server (Cassini)

If you’re ever running a web app locally in Cassini (Visual Studios built in web server) and FireFox is really really really slow, but IE is fast like it should be, then you probably need to turn off IPV6 in FireFox.

To do this, type “about:config” in the address bar and filter on “v6″. Turn off IPV6 and FireFox should be fast again.

ASP.NET Magic Maintenance Mode

I just recently found that you’re able to easily put your ASP.NET website int “maintenance mode”. All you need to do is add an App_Offline.htm file to you site root, and ASP.NET will serve up all requests to that file. Just rename or remove the file when you’re down with your maintenance.

Scott Gu has a couple good posts on this.

http://weblogs.asp.net/scottgu/archive/2005/10/06/426755.aspx

http://weblogs.asp.net/scottgu/archive/2006/04/09/442332.aspx

ASP.NET MVC, Ninject.Web.Mvc and 404’s

I went about trying to handle 404 errors on my ASP.NET MVC application by following code I found here.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
protected void Application_Error( object sender, EventArgs e )
{
var exception = Server.GetLastError();
 
Response.Clear();
 
var httpException = exception as HttpException;
 
var routeData = new RouteData();
routeData.Values.Add( "controller", "Error" );
 
if( httpException == null )
{
routeData.Values.Add( "action", "Index" );
}
else //It's an Http Exception, Let's handle it.
{
switch( httpException.GetHttpCode() )
{
case 404:
// Page not found.
routeData.Values.Add( "action", "HttpError404" );
break;
case 500:
// Server error.
routeData.Values.Add( "action", "HttpError500" );
break;
 
// Here you can handle Views to other error codes.
// I choose a General error template
default:
routeData.Values.Add( "action", "General" );
break;
}
}
 
// Pass exception details to the target error View.
routeData.Values.Add( "error", exception );
 
// Clear the error on server.
Server.ClearError();
 
// Call target Controller and pass the routeData.
IController errorController = new ErrorController();
errorController.Execute( new RequestContext( new HttpContextWrapper( Context ), routeData ) );
}
view raw File1.cs hosted with ❤ by GitHub

Although, this didn’t work for me because I’m using Ninject.Web.Mvc. Instead, I get this error:

The IControllerFactory ‘Ninject.Web.Mvc.NinjectControllerFactory’ did not return a controller for a controller named ‘blah’.

The NinjectControllerFactory.CreateController( RequestContext requestContext, string controllerName ) method is returning null when it can’t find a controller, when it should be throwing a 404 HttpException.

There apparently is a patch waiting to be merged into trunk for this, but until then, you can use this change to the controller factory. The factory now inherits from DefaultControllerFactory, CreateController and ReleaseController are now overrides, and a test for a null controller will call base.CreateController.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
using System;
using System.Globalization;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
 
namespace Ninject.Web.Mvc
{
/// <summary>
/// A controller factory that creates <see cref="IController"/>s via Ninject.
/// </summary>
public class NinjectControllerFactory : DefaultControllerFactory
{
/// <summary>
/// Gets the kernel that will be used to create controllers.
/// </summary>
public IKernel Kernel { get; private set; }
 
/// <summary>
/// Initializes a new instance of the <see cref="NinjectControllerFactory"/> class.
/// </summary>
/// <param name="kernel">The kernel that should be used to create controllers.</param>
public NinjectControllerFactory(IKernel kernel)
{
Kernel = kernel;
}
 
/// <summary>
/// Creates the controller with the specified name.
/// </summary>
/// <param name="requestContext">The request context.</param>
/// <param name="controllerName">Name of the controller.</param>
/// <returns>The created controller.</returns>
public override IController CreateController(RequestContext requestContext, string controllerName)
{
var controller = Kernel.TryGet<IController>(controllerName.ToLowerInvariant());
 
if(controller == null)
return base.CreateController(requestContext, controllerName);
 
var standardController = controller as Controller;
 
if(standardController != null)
standardController.ActionInvoker = new NinjectActionInvoker(Kernel);
 
return controller;
}
 
/// <summary>
/// Releases the specified controller.
/// </summary>
/// <param name="controller">The controller to release.</param>
public override void ReleaseController(IController controller) { }
}
}
view raw File2.cs hosted with ❤ by GitHub