3

I have the following setup in my project:

public class WebApiApplication : System.Web.HttpApplication
{
    public static ISessionFactory SessionFactory { get; private set; }

    public WebApiApplication()
    {
        this.BeginRequest += delegate
        {
            var session = SessionFactory.OpenSession();
            CurrentSessionContext.Bind(session);
        };


        this.EndRequest += delegate
        {
            var session = SessionFactory.GetCurrentSession();

            if (session == null)
            {
                return;
            }

            session = CurrentSessionContext.Unbind(SessionFactory);
            session.Dispose();
        };
    }

    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();

        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);
        var assembly = Assembly.GetCallingAssembly();
        SessionFactory = new NHibernateHelper(assembly, Server.MapPath("/")).SessionFactory;
    }
}

public class PositionsController : ApiController
{
    private readonly ISession session;

    public PositionsController()
    {
        this.session = WebApiApplication.SessionFactory.GetCurrentSession();
    }

    public IEnumerable<Position> Get()
    {
        var result = this.session.Query<Position>().Cacheable().ToList();

        if (!result.Any())
        {
            throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.NotFound));
        }

        return result;
    }

    public HttpResponseMessage Post(PositionDataTransfer dto)
    {
        //TODO: Map dto to model
        IEnumerable<Position> positions = null;
        using (var transaction = this.session.BeginTransaction())
        {
            this.session.SaveOrUpdate(positions);

            try
            {
                transaction.Commit();
            }
            catch (StaleObjectStateException)
            {
                if (transaction != null && transaction.IsActive)
                {
                    transaction.Rollback();
                }
            }
        }

        var response = this.Request.CreateResponse(HttpStatusCode.Created, dto);
        response.Headers.Location = new Uri(this.Request.RequestUri.AbsoluteUri + "/" + dto.Name);
        return response;
    }

    public void Put(int id, string value)
    {
        //TODO: Implement PUT
        throw new NotImplementedException();
    }

    public void Delete(int id)
    {
        //TODO: Implement DELETE
        throw new NotImplementedException();
    }
}

I am not sure if this is the recommended way to insert the session into the controller. I was thinking about using DI but i am not sure how to inject the session that is opened and binded in the BeginRequest delegate into the Controllers constructor to get this

    public PositionsController(ISession session)
    {
        this.session = session;
    }

Question: What is the recommended way to use NHibernate sessions in asp.net mvc/web api ?

2 Answers 2

2

There are multiple options that might be used in your case.

One option is described as passing controllers an instance of a NHibernate session which is unique for the HTTP request - NHibernate sessions in ASP.NET MVC

Another options can be found in NHibernate Wiki

2
  • 1
    The 2nd link is dead. Mar 29, 2023 at 15:28
  • Thank you @GertArnold for pinging back!
    – Yusubov
    Jan 26 at 16:44
2

I am not sure if this is the recommended way to insert the session into the controller

Use constructor injection, as long as session is required for controller. Your "composition root" should be able to do this. And you had provided an example.

I was thinking about using DI but i am not sure how to inject the session that is opened and binded in the BeginRequest delegate into the Controllers constructor to get this

Usually DI containers are configured with "scope" abstraction. There are several default scopes for most of DI containers, among them are Signleton, Transient, Thread and Request (for HTTP requests). Last one will create one instance of dependency per HTTP request, and injects it into all objects that handle this request. As soon as HTTP Request will be done, DI should dispose all dependencies also. So, there is no need to explicitely create, handle and dispose session yourself.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.