1

I have an application using ASP.NET Core, Angular 5 And ADO.NET

It worked fine until I decided to change the code to set a session variable with a database connection string gotten from my appssettings.json file.

I am using this as a reference: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/app-state?view=aspnetcore-2.2

However, when I try to set the session variable, I get a Null object reference in my SetSessionVariable() method.

Error is:

An error occurred while starting the application. NullReferenceException: Object reference not set to an instance of an object. Angular5NetcoreAdo.Startup.SetSessionVariable() in Startup.cs, line 82

My code is:

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.SpaServices.AngularCli;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Angular5NetcoreAdo.Models;

// Added these.
using Microsoft.AspNetCore.Http;
using System;

namespace Angular5NetcoreAdo
{
public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // Added this.
    public HttpContext HttpContext { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

        // In production, the Angular files will be served from this directory.
        services.AddSpaStaticFiles(configuration =>
        {
            configuration.RootPath = "ClientApp/dist";
        });

        services.AddScoped<EmployeeDataAccessLayer>();

        // Added this.
        services.AddSession(options =>
        {
            options.Cookie.Name = ".ConnectionString";
        });

        // Added this.
        SetSessionVariable();
    }

    // Added this.
    public void SetSessionVariable()
    {
         HttpContext.Session.SetString("ConnectionString", Convert.ToString(Configuration.GetConnectionString("DBAngular5NetcoreAdoDatabase")));
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Error");
        }

        app.UseStaticFiles();
        app.UseSpaStaticFiles();

        // Added this.
        app.UseSession();

        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller}/{action=Index}/{id?}");
        });

        app.UseSpa(spa =>
        {
            spa.Options.SourcePath = "ClientApp";

            if (env.IsDevelopment())
            {
                spa.UseAngularCliServer(npmScript: "start");
            }
        });
    }
}

---- Per a suggestion below, I am including that code here:

// Middleware extension method.

using Microsoft.AspNetCore.Builder;

namespace Angular5NetcoreAdo
{
    public static class RequestConnectionMiddlewareExtensions
    {
        public static IApplicationBuilder UseRequestConnection(this 
IApplicationBuilder builder)
        {
            return builder.UseMiddleware<RequestConnectionMiddleware>();
        }
    }
}

using Microsoft.AspNetCore.Http;
using System.Threading.Tasks;
using System;
using Microsoft.Extensions.Configuration;

namespace Angular5NetcoreAdo
{
    public class RequestConnectionMiddleware
    {
        public IConfiguration Configuration { get; }
        public HttpContext HttpContext { get; }

        private readonly RequestDelegate _next;

        public RequestConnectionMiddleware(RequestDelegate next, 
IConfiguration configuration)
        {
            _next = next;

            Configuration = configuration;
        }

        public async Task InvokeAsync(HttpContext context)
        {
            // Set the session variable with the database connection string from appsettings.json.
            HttpContext.Session.SetString("ConnectionString", Convert.ToString(Configuration.GetConnectionString("DBAngular5NetcoreAdoDatabase")));

            await _next(context);
        }
    }
}

Now in the Startup.cs, I call the new middleware message method after the app.UseSession();

app.UseSession();

// Call the middlware now to set the session variable with the database
// connection string from appsettings.json. 
app.UseRequestConnection();

------------------ Added now as a new error refers to this class.

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using Microsoft.Extensions.Configuration;
using Microsoft.AspNetCore.Http;

namespace Angular5NetcoreAdo.Models
{
    public class EmployeeDataAccessLayer
    {
       public HttpContext HttpContext { get; }
       public string connectionString;

       public EmployeeDataAccessLayer(HttpContext httpContext)
       {
           // Set the property.
           HttpContext = httpContext;

           // Get the connection string session variable.
           connectionString = HttpContext.Session.GetString("ConnectionString");
       }

       public IEnumerable<Employee> GetAllEmployees()
       {
          try
           {
               List<Employee> lstemployee = new List<Employee>();

               using (SqlConnection con = new SqlConnection(connectionString))
               {
                   SqlCommand cmd = new SqlCommand("SelectEmployees", con);
                   cmd.CommandType = CommandType.StoredProcedure;

                   con.Open();

                   SqlDataReader rdr = cmd.ExecuteReader();

                   while (rdr.Read())
                   {
                       Employee employee = new Employee();

                       employee.ID = Convert.ToInt32(rdr["EmployeeID"]);
                       employee.Name = rdr["Name"].ToString();
                       employee.Gender = rdr["Gender"].ToString();
                       employee.Department = rdr["Department"].ToString();
                       employee.City = rdr["City"].ToString();

                       lstemployee.Add(employee);
                   }

                   rdr.Close();
                   con.Close();
               }

               return lstemployee;
           }
           catch
           {
               throw;
           }
       }

       public Employee GetEmployeeData(int id)
       {
           try
           {
               Employee employee = new Employee();

               using (SqlConnection con = new SqlConnection(connectionString))
               {
                   SqlCommand cmd = new SqlCommand("SelectEmployeeById", con);
                   cmd.CommandType = CommandType.StoredProcedure; 
                   cmd.Parameters.AddWithValue("@EmpId", id);

                   con.Open();

                   SqlDataReader rdr = cmd.ExecuteReader();

                   while (rdr.Read())
                   {
                       employee.ID = Convert.ToInt32(rdr["EmployeeID"]);
                       employee.Name = rdr["Name"].ToString();
                       employee.Gender = rdr["Gender"].ToString();
                       employee.Department = rdr["Department"].ToString();
                       employee.City = rdr["City"].ToString();
                   }

                   rdr.Close();
                   con.Close();
               }

               return employee;
           }
           catch
           {
               throw;
           }
       }

       public int AddEmployee(Employee employee)
       {
           try
           {
               using (SqlConnection con = new SqlConnection(connectionString))
               {
                   SqlCommand cmd = new SqlCommand("InsertEmployee", con);
                   cmd.CommandType = CommandType.StoredProcedure;

                   cmd.Parameters.AddWithValue("@Name", employee.Name);
                   cmd.Parameters.AddWithValue("@City", employee.City);
                   cmd.Parameters.AddWithValue("@Department", employee.Department);
                   cmd.Parameters.AddWithValue("@Gender", employee.Gender);

                   con.Open();

                   cmd.ExecuteNonQuery();

                   con.Close();
               }

               return 1;
           }
           catch
           {
               throw;
           }
       }

       public int UpdateEmployee(Employee employee)
       {
           try
           {
               using (SqlConnection con = new SqlConnection(connectionString))
               {
                   SqlCommand cmd = new SqlCommand("UpdateEmployee", con);
                   cmd.CommandType = CommandType.StoredProcedure;

                   cmd.Parameters.AddWithValue("@EmpId", employee.ID);
                   cmd.Parameters.AddWithValue("@Name", employee.Name);
                   cmd.Parameters.AddWithValue("@City", employee.City);
                   cmd.Parameters.AddWithValue("@Department", employee.Department);
                   cmd.Parameters.AddWithValue("@Gender", employee.Gender);

                   con.Open();

                   cmd.ExecuteNonQuery();

                    con.Close();
               }

               return 1;
           }
           catch
           {
               throw;
           }
       }

       public int DeleteEmployee(int id)
       {
           try
           {
            using (SqlConnection con = new SqlConnection(connectionString))
               {
                   SqlCommand cmd = new SqlCommand("DeleteEmployee", con);
                   cmd.CommandType = CommandType.StoredProcedure;
                   cmd.Parameters.AddWithValue("@EmpId", id);

                   con.Open();

                   cmd.ExecuteNonQuery();

                    con.Close();
              }

               return 1;
          }
        catch
           {
               throw;
           }
       }
   }
}
0

1 Answer 1

1

Its because documentation says

HttpContext.Session can't be accessed before UseSession has been called.

and you call it in ConfigurationServices method where HttpContext.Session does not exist yet.

So you will need create your own middleware and call it after UseSession() method in Configure method.

Sign up to request clarification or add additional context in comments.

6 Comments

As per that 'create your middleware' link you included above, I created the middleware, placed the call to it after the UseSession() and I still get the same error. I included this code above for review.
@user3020047 You tried change HttpContext.Session. to context.Session ?
@user3020047 That's because you're executing HttpContext.Session.SetString... in your RequestConnectionMiddleware.Invoke(context), the HttpContext here is not passed from the parameter context , but from the Property of this middleware. Since you have never set this Property, it is null all the time
@itminus I added a set; to the property HttpContext. Then in the InvokeAsync() method I added: HttpContext = context; I now get an error on the next line __> await _next(context); ---->InvalidOperationException: Unable to resolve service for type 'Microsoft.AspNetCore.Http.HttpContext' while attempting to activate 'Angular5NetcoreAdo.Models.EmployeeDataAccessLayer'.
@daremachine I changed it to context.Sesson and I get the error: I now get an error on the next line __> await _next(context); ---->InvalidOperationException: Unable to resolve service for type 'Microsoft.AspNetCore.Http.HttpContext' while attempting to activate 'Angular5NetcoreAdo.Models.EmployeeDataAccessLayer'. ---> The same error as the suggestion from above. Note: I added the EmployeeDataAccessLayer code above for review but I don't get why this error message would have issue with it.
|

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.