How to establish a connection on a web application

I’m trying to migrate from SDK2 to SDK 3.
I’m using ASP.NET Framework 4.

In this link you say under “Connection Lifecycle” that I should connect and dispose inside my global.asax.

How exactly do I dispose of the cluster?
Cluster class doesn’t have a dispose method, and I don’t have access to the return object from the Application_Start in my Application_End method

It’s not like I can define the cluster variable globally (unless I use an Application variable, but even then I was unable to successfully access it from the Application_End to dispose of it or from other pages)

    protected void Application_Start(object sender, EventArgs e)
    {
        
        // get parameters from web.config
        Uri serverURI = new Uri(ConfigurationManager.AppSettings["CouchBase_serverURI"]);
     
        // server authentication
        RegistryKey registryKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Wow6432Node\Test\Couchbase");            

        if (registryKey != null)
        {
            string CouchbasePassword = registryKey.GetValue("Couchbase_p").ToString();

            var cluster = Cluster.ConnectAsync("couchbase://" + serverURI, "AppUser", CouchbasePassword);

        }
        
    }

    protected void Session_Start(object sender, EventArgs e)
    {
        
    }

    protected void Application_BeginRequest(object sender, EventArgs e)
    {

    }

    protected void Application_AuthenticateRequest(object sender, EventArgs e)
    {

    }

    protected void Application_Error(object sender, EventArgs e)
    {

    }

    protected void Session_End(object sender, EventArgs e)
    {

    }

    protected void Application_End(object sender, EventArgs e)
    {
      
    }

@alon.schachter -

ICluster does indeed have a Dispose method. Cluster.ConnectAsync returns a Task<ICluster> that is not being awaited here, thus your not seeing the Dispose method. Since Application_Start and Application_End are synchronous methods, you’ll need to make the calls synchronously. Here is an example:

    public class WebApiApplication : System.Web.HttpApplication
    {
        public static ICluster ClusterObj { get; private set; }
        public static IBucket BucketObj { get; private set; }

        protected void Application_Start()
        {
           ...

            var options = new ClusterOptions().WithCredentials("Administrator", "password");
            ClusterObj = Cluster.ConnectAsync("couchbase://localhost", options).GetAwaiter().GetResult();
            BucketObj = ClusterObj.BucketAsync("default").GetAwaiter().GetResult();
        }

        protected void Application_End()
        {
            if (ClusterObj != null)
            {
                BucketObj?.Dispose();
                ClusterObj.Dispose();
            }
        }
    }

And then use the objects as static references off of WebApiApplication:

 public async Task<ActionResult> Index()
 {
      var cluster = WebApiApplication.ClusterObj;
      var bucket = WebApiApplication.BucketObj;

      await bucket.DefaultCollection().UpsertAsync("weee", new {Poo = "bar"});
      ViewBag.Title = "Home Page";
      return View();
 }

It’s important to note that we normally don’t advocate calling async code synchronously like we did in Global.asax, but in this scenario using an older version of ASP.NET it might be an option. Another option is to use a static singleton to encapsulate the Cluster/Bucket and lazy load it on first use and the dispose of it on Application_End. There are probably a couple of other ways to do it, a Startup.csclass for example.

Also, SDK3 was designed and intended to be used in .NET Core applications using the built-in DI system and our helper DI infrastructure.

-Jeff

1 Like

Thanks @jmorris, I’ll give that a try.
As for using Startup.cs class, I believe that’s also a .NET Core / .NET 5 thing