Tag Archives: Asp.Net MVC3

Asp.Net MVC Code

Bundling single & multiple files in a view for MVC 3/4

If you have been following the development of asp.net mvc 4 you’ll be aware of the new bundling/minification feature; I won’t go in to detail how it works or how to use it as there are plenty of other sources for that.

I’m working on an existing MVC 3 project that is quite large has has a mixture of css, less and js dotted about with a minification system that works ok; so I was looking for a way to use the the new bundling feature in the existing project. Luckily the feature is available on nuget via the Microsoft.Web.Optimization package and there is a project called Bundle Transformer that extends the functionality.

The problem arises in registering a new bundle, the existing organisation doesn’t allow the use of the dynamic folder bundle and the front end devs want to avoid writing back end code as much as possible.

To solve this problem I developed a small bit of code that allows you to register a bundle right in the view (this is assuming you are following the Bundle Transformer documentation and have a “BundleConfig.cs” file in the App_Start folder):

 private static void RegisterBundle(string virtualPath, bool css, params string[] files)
    {
      var existing = BundleTable.Bundles.GetBundleFor(virtualPath);
      if (existing != null)
      {
        return;
      }

      var newBundle = new Bundle(virtualPath);
      foreach (var file in files)
      {
        newBundle.Include(file);
      }

      var nullOrderer = new NullOrderer();
      newBundle.Orderer = nullOrderer;

      if (css)
      {
        var cssTransformer = new CssTransformer();
        var cssMinifier = new CssMinify();
        newBundle.Transforms.Add(cssTransformer);
        newBundle.Transforms.Add(cssMinifier);
      }
      else
      {
        var jsTransformer = new JsTransformer();
        var jsMinifier = new JsMinify();
        newBundle.Transforms.Add(jsTransformer);
        newBundle.Transforms.Add(jsMinifier);
      }

      BundleTable.Bundles.Add(newBundle);
    }

    public static IHtmlString RegisterScript(string virtualPath, params string[] files)
    {
      RegisterBundle(virtualPath, false, files);
      return Scripts.Render(virtualPath);
    }

    public static IHtmlString RegisterStyle(string virtualPath, params string[] files)
    {
      RegisterBundle(virtualPath, true, files);
      return Styles.Render(virtualPath);
    }

    public static IHtmlString RegisterScriptUrl(string virtualPath, params string[] files)
    {
      RegisterBundle(virtualPath, false, files);
      return Scripts.Url(virtualPath);
    }

    public static IHtmlString RegisterStyleUrl(string virtualPath, params string[] files)
    {
      RegisterBundle(virtualPath, true, files);
      return Styles.Url(virtualPath);
    }

And now the front end devs can register a bundle in the view:

@BundleConfig.RegisterStyle("~/css/common-loggedin",
    "~/Content/less/global.less",
   "~/Content/css/transforms.css",
   "~/Content/css/ui-darkness/jquery-ui.custom.css",
   "~/Content/css/jquery.qtip.css" ,
   "~/Content/css/chosen.css" 
   )
	<link rel="stylesheet" href="@BundleConfig.RegisterStyleUrl("~/css/print","~/Content/less/print.less")" media="print" />

 @BundleConfig.RegisterScript("~/script/application",
        "~/Content/js/application.js"  , 
        "~/Content/js/thap/notifications.js"   
    )

The first parameter defines the bundle name, the rest are the files you want to include.

Asp.Net MVC Code

Unit of Work, NHibnernate and Asp.Net MVC

In a previous post I mentioned for some projects I’m using a combination of NHibernate, unit of work and asp.net mvc; this post will give an example of how I set this up for a project and how to get mvc to automatically create instances of UoW, wrap our code in transactions and clean up after it’s self via ActionFilterAttributes. Some of the code I have is a modified version of this but probably not as nice.

Here is a list of the interfaces that’ll be created:

And classes that implement them:

And finally the mvc Attribute: UnitOfWorkFilter.

This maybe(is) a lot of work for for something that seems pretty straight forward but it allows the code to be decoupled and makes testing much easier.  For example a project I’ve been working on uses this workflow and has a windows service to do some back end processing; by creating a RequestState to work with a windows service the rest of the code doesn’t need changing (apart from the filter obviously.)

I’ll leave the code further down in the post so things don’t get messy.

Actually using this setup.

This post makes the assumption that your data access is all via nhibernate and you’re using the repository pattern or something similar. Your repositories will need access to the IActiveSessionManager. If you’re using a DI like Ninject it should pass it through for you.

In your repository you can access the nhibernate session like so:

this.activeSessionManager.GetActiveSession();

I personally have a property to do this for me:

    public ISession Session
    {
      get
      {
        return this.activeSessionManager.GetActiveSession();
      }
    }

From here on do what ever queries you need, all the repositories in the will share the same session during the same request.

Applying the attribute

You can either have the UnitOfWorkFilter attached to each controller/method or in the global.asax you can register is as a global filter.

 [UnitOfWorkFilter]
  public class UserController : Controller
{
}

or

    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
      filters.Add(new UnitOfWorkFilter());

    }

That’s it!.

How it all fits together

Imagine you have a controller that gets you a list of users (UserController).

  1. You issue a GET to the controller action
  2. The UnitOfWorkFilter kicks in and starts a new transaction from the ActiveSessionManager (The same manager your repo’s use)
  3. The ActiveSessionManager checks for/creates a new nhibernate session to work with
  4. Your repos use this ActiveSessionManager/NHibernate session to get its data
    1. If you have more than one repo in the controller action then no new sessions are created, the same one is shared.
  5. The controller returns the users
  6. The UnitOfWorkFilter then commits the transaction and closes the current session
    1. If something goes wrong like an exception the the UnitOfWorkFilter rollsback the transaction – preserving the integrity of the database

Below is the code to implement this.

IUnitOfWork

  public interface IUnitOfWork : IDisposable
  {

    void BeginTransaction();

    void EndTransaction();

    void RollBack();
  }

IRequestState

  public interface IRequestState
  {
    T Get<T>(string key);

    void Store(string key, object something);
  }

ISessionProvider

The ISession is the NHibernate session.

  public interface ISessionProvider
  {
    ISession Create();
  }

IActiveSessionManager

  public interface IActiveSessionManager: IDisposable
  {
    ISession GetActiveSession();

    void ClearActiveSession();

    bool HasActiveSession { get; }
  }

UnitOfWork

/// <summary>
  /// An nhibernate specific implementation of the unit of work concept
  /// </summary>
  public class UnitOfWork : IUnitOfWork
  {
    private readonly IActiveSessionManager sessionManager;

    private ITransaction transactionScope;

    public UnitOfWork(IActiveSessionManager sessionManager)
    {
      this.sessionManager = sessionManager;
    }

    public void Dispose()
    {
      if (this.transactionScope != null)
      {
        this.transactionScope.Dispose();
      }

      this.sessionManager.Dispose();
    }

    public void BeginTransaction()
    {
      if (this.transactionScope != null)
      {
        throw new InvalidOperationException("Transaction already started; nested transactions are not supported");
      }

      this.transactionScope = this.sessionManager.GetActiveSession().BeginTransaction();
    }

    public void EndTransaction()
    {
      if (this.transactionScope == null)
      {
        throw new InvalidOperationException("No active transaction found");
      }

      if (!this.transactionScope.IsActive)
      {
        throw new InvalidOperationException("This transaction is no longer active");
      }

      try
      {
        this.transactionScope.Commit();
      }
      catch (Exception ex1)
      {
          this.RollBack();
      }
    }

    public void RollBack()
    {
      this.transactionScope.Rollback();
    }
  }

AspNetRequestState

  public class AspNetRequestState : IRequestState
  {
    public T Get<T>(string key)
    {
      return (T)HttpContext.Current.Items[key];
    }

    public void Store(string key, object something)
    {
      HttpContext.Current.Items[key] = something;
    }
  }

SessionProvider

Note that the session factory has not been configured, this is left up you to configure.

 public class SessionProvider : ISessionProvider
  {
    private static ISessionFactory sessionFactory;

    public SessionProvider()
    {
      if (sessionFactory == null)
      {
	    // Do your mhibernate configuration here
        var configration = new Configuration();
        sessionFactory = configration.BuildSessionFactory();
      }
    }

    public ISession Create()
    {
      return sessionFactory.OpenSession();
    }
  }

ActiveSessionManager

public class ActiveSessionManager : IActiveSessionManager
  {
    private const string sessionKey = "_currentSession";

    private readonly IRequestState requestState;

    private readonly ISessionProvider sessionProvider;

    public ActiveSessionManager(IRequestState requestState, ISessionProvider sessionProvider)
    {
      this.requestState = requestState;
      this.sessionProvider = sessionProvider;
    }

    public ISession GetActiveSession()
    {
      if (this.Current == null)
      {
        var newSession= this.sessionProvider.Create();
        this.Current = newSession;
        return newSession;
      }

      return this.Current;
    }

    public void ClearActiveSession()
    {
      this.Current = null;
    }

    public bool HasActiveSession
    {
      get { return this.Current != null; }
    }

    protected virtual ISession Current
    {
      get
      {
        return requestState.Get<ISession>(sessionKey);
      }
      set
      {
        requestState.Store(sessionKey, value);
      }
    }

    public void Dispose()
    {
      var session = this.Current;
      if(session != null)
      {
        session.Dispose();
        this.ClearActiveSession();
      }
    }
  }

 

UnitOfWorkFilter

 

public class UnitOfWorkFilter : ActionFilterAttribute
  {
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
      var unitOfWork = DependencyResolver.Current.GetService<IUnitOfWork>();
      unitOfWork.BeginTransaction();
    }

    public override void OnResultExecuted(ResultExecutedContext filterContext)
    {
      var unitOfWork = DependencyResolver.Current.GetService<IUnitOfWork>();
      unitOfWork.EndTransaction();
    }
  }
Code

How I fixed FluentNHibernate.Cfg.FluentConfigurationException on MVC 3

Just to let you know this may not solve your version of this error (since it’s so vague) but it’s how I solved it in one of my projects.

On a previous post I mention I was using NHibernate in one of the projects I’m working on and as such we’re using FluentNHibernate.

I’ve created a class (let’s call it SessionManager) that handles creating the ISessionFactory instance (and stores it in a static field). The project is built with MVC 3 and makes use of the DI provider along with Ninject so this code snippet should look familiar. (It’s where you set up you DI – usually the AppStart_NinjectMVC3)

kernel.Bind<ISessionFactory>().ToConstant(SessionManager.CreateSessionFactory());

That is the line the caused the problems; not sure how but the aspnet compiler dies. In the end I changed ninject to use “ToMethod” instead:

kernel.Bind<ISessionFactory>().ToMethod(c => SessionManager.CreateSessionFactory());

Since the session manager handles creating the ISessionFactory like I mentioned earlier we don’t get multiple instances of ISessionFactory.