Reputation: 888
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;
}
}
}
}
Upvotes: 1
Views: 5169
Reputation: 2788
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.
Upvotes: 1