IOptions with Connection string - c#

I have very simple appsettings:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"ConnectionStrings": {
"DefaultConnection": "Server=test;Database=test;Trusted_Connection=True;"
},
"AllowedHosts": "*"
}
Class for connection string:
public class ConnectionStrings
{
public string DefaultConnection { get; set; }
}
I register in DI it like this:
builder.Services.AddOptions<ConnectionStrings>(builder.Configuration.GetConnectionString("DefaultConnection"));
I inject IOption in constructor, but it is always null:
public class ShoppingCartRepository : IShoppingCartRepository
{
private readonly IOptions<ConnectionStrings> _connectionStrings;
public ShoppingCartRepository(IOptions<ConnectionStrings> connectionStrings)
{
_connectionStrings = connectionStrings;
}
// ...
}
}
Can I use IOptions for connection string or I should use another approach?
What is best way of working with connection string?

The AddOptions method accept an argument of type string that is the name of the options instance. But You pass the value of DefaultConnection in appsettings.json to it.
You should add Bind method after AddOptions
builder.Services
.AddOptions<ConnectionStrings>()
.Bind(Configuration.GetSection("ConnectionStrings:DefaultConnection"));

Let's take it from here:
builder.Services.Configure<ConnectionStrings>(
builder.Configuration.GetSection("ConnectionStrings")
)

Related

In .net 6, how do I pass the parameter to the constructor when the service initialization comes before the configuration binding of values?

I can't seem to find the solution to my exact problem, because I need to call the dependency injection before calling the builder, but this results in a new object instantiation in the controller class and the values are lost.
If I put this line right after binding, I can get an error saying cannot modify the service after it has been built.
In the older version of .net, since Startup.cs is existing, this doesn't seem to be a problem due to the separation of methods ConfigureService and Configure.
AuthenticationBind.cs
public class AuthenticationBind
{
public int AuthenticationId { get; set; }
public string AuthenticationName { get; set; }
}
appsettings.json
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"TestAuthenticationBind": {
"AuthenticationId": "1324556666",
"AuthenticationName": "Test Authentication Name"
},
"AllowedHosts": "*"
}
Program.cs
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllersWithViews();
builder.Services.AddRazorPages();
builder.Services.AddSingleton<AuthenticationBind>();
var app = builder.Build();
AuthenticationBind tb = new AuthenticationBind();
IConfiguration configuration = app.Configuration;
configuration.Bind("TestAuthenticationBind", tb);
AuthenticationController.cs
private readonly AuthenticationBind authenticationBind;
public AuthenticationController(AuthenticationBind authenticationBind)
{
this.authenticationBind = authenticationBind;
}
Also, can I use the object instance to pass to services.AddSingleton method, instead of the class itself, like below?
builder.Services.AddSingleton<tb>();
It appears you're trying to bind configuration values into models. You can do this by calling IServiceCollection.Configure<T>() - for your code, it would look like this:
builder.Services.Configure<AuthenticationBind>(builder.Configuration.GetSection("TestAuthenticationBind"));
Afterwards, you can use the IOptions<T> interface in your controller to access the (bound) object:
public AuthenticationController(
IOptions<AuthenticationBind> authOptions
)
{
// You can access authOptions.Value here
}
Same goes in the startup class, you can request the IOptions interface like so:
var authOptions = app.Services.GetRequiredService<IOptions<AuthenticationBind>>();

IConfiguration is always NULL .NET CORE in Blazor app / Razor

IConfiguration is always null no matter what i try.. I have also tried to add singleton to the startup class, but always null...
Startup class
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
Here is my Security class
IConfiguration _configuration { get;} **<<always null**
public Security(IConfiguration configuration) **<<always null**
{
_configuration = configuration;
}
public string GetConnectionString()
{
string connectionString = _configuration.GetConnectionString("localDb");
return connectionString;
}
Here is my Index.Razor page
namespace WebbiSkoolsQuizManager.Pages
{
public class IndexBase : ComponentBase
{
public IConfiguration Configuration { get; }
public async Task TryLogin(string user, string pass)
{
}
public async Task AddUserHash(string username, string password)
{
Security secure = new Security(Configuration);
string connectionstring = secure.GetConnectionString();
}
}
}
Appsettings.json
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"ConnectionKeys": {
"localDb": "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=Quiz;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False"
},
"AllowedHosts": "*"
}
Thank you in advance, i have searched high and low, regarding a fix for blazor specific but i cant find anything.. (P.S its .Net core 3)
I guess this: public IConfiguration Configuration { get; }
Should be:
[Inject]
public IConfiguration Configuration { get; }
Note: You can't simply define a property of a service, and expect it to be populated... If you're using a Razor component class definition (.cs) as in your case, you can inject the service by using the [Inject] attribute. If you're using a Razor component (.razor), you can either use the #inject directive at the view portion of the component, as for instance:
#page "/"
#inject IConfiguration Configuration
or in the #code section, like this:
#code
{
[Inject]
public IConfiguration Configuration { get; }
}
Note also that if you want to inject a service into a normal C# class, you'll need to use constructor injection
I started a new blazor project (.Net 6) and when I #inject the IConfiguration to my .razor file, the configuration object turns out to be always null.

How to read connection string from appsettings.json in a DBContext file in Asp.Net Core? [duplicate]

This question already has answers here:
Get ConnectionString from appsettings.json instead of being hardcoded in .NET Core 2.0 App
(13 answers)
Closed 3 years ago.
I have defined a connection string in the appsettings.json file. now I want to read it in my TextDBConext file, how can I do it?
public class TestContext: DbContext
{
public DbSet<TestTable> TestTable { get; set; }
public TestContext()
{
}
public IConfiguration Configuration { get; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("Connection string"); //I have hardcoded here, but I want from appsettings.json
}
}
Appsettings.json file:
{
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"connection_string": "Connection String"
}
}
You can setup your db context in the startup file and not override OnConfiguring at all.
Just add a constructor that takes DbContextOptions<TContext> to your DbContext class. This constructor should pass on the parameter to the base class' constructor,
then call AddDbContext<TContext> in your Startup.Configure as follows:
// your TestContext showing constructor
public class TestContext : DbContext
{
public TestContext(DbContextOptions<TestContext> options) : base(options){ }
}
// Then in Startup.cs
public class Startup
{
public IConfiguration Configuration {get;}
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<TeamsDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("connection_string")));
}
}
Worth noting is that the AddDbContext<TContext> method has overloads that allow setting the service lifetime for the context to Singleton or Transient if you so wish. The default is Scoped.
You can inject IConfiguration into TestContext constructor and then use GetConnectionString(string name) method to get the connection string.
So..
public class TestContext : DbContext
{
private readonly IConfiguration _configuration;
public TestContext(IConfiguration configuration)
{
_configuration = configuration;
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(_configuration.GetConnectionString("Your Connection String Name"));
}
}

Get Value from appsettings.json file in common class

I want to get value using Appsettings from appsettings.json file
My code is in appsettings.json file:
{
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AppSettings": {
"APIURL": "https://localhost:44303/api"
},
"AllowedHosts": "*"
}
But I don't know how to get that value in common class file.
In general, you want to use strongly-typed configuration. Essentially, you just create a class like:
public class AppSettings
{
public Uri ApiUrl { get; set; }
}
And then, in ConfigureServices:
services.Configure<AppSettings>(Configuration.GetSection("AppSettings"));
Then, where you need to use this, you'd inject IOptions<AppSettings>:
public class Foo
{
private readonly IOptions<AppSetings> _settings;
public Foo(IOptions<AppSettings> settings)
{
_settings = settings;
}
public void Bar()
{
var apiUrl = _settings.Value.ApiUrl;
// do something;
}
}
Create a class matching the structure of your JSON, and put it in a "common" place:
public class AppSettings
{
public Uri APIURL { get; set; }
}
Create an instance of AppSettings somewhere (what I like to do is create it in ConfigureServices and then register it with the container). For example
// create a new instance
var appsettings = new AppSettings();
// get section from the config served up by the various .NET Core configuration providers (including file JSON provider)
var section = Configuration.GetSection("AppSettings");
// bind (i.e. hydrate) the config to this instance
section.Bind(appsettings);
// make this object available to other services
services.AddSingleton(appsettings);
Then, when you need to use appsettings you can do so by simply injecting it into any services that need it. For example
public class SomeService
{
private readonly AppSettings _settings;
public SomeService(AppSettings settings) => _settings = settings;
...
}

Why am I getting an error in my ASP.NET Core SQL Server Express Connection String?

I've recently started a new ASP.NET Core web application and I'd like to connect it to my local SQLExpress database. I've been following the documentation but I'm getting an error of "Value cannot be null" when it tries to read my connection string at
options.UseSqlServer(configuration.GetConnectionString("DefaultConnection")
Here is my code so far. In Startup.cs I have the following setup:
using Microsoft.AspNetCore.Builder;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Blondie.CoreApiSql.Models;
using Microsoft.Extensions.Configuration;
namespace Blondie.CoreApiSql
{
public class Startup
{
private readonly IConfiguration configuration;
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<DatabaseContext>
(options => options.UseSqlServer(configuration.GetConnectionString("DefaultConnection")));
services.AddMvc();
}
public void Configure(IApplicationBuilder app)
{
app.UseMvc();
}
}
}
When you run the appliation the error is triggered at the following line:
services.AddDbContext<DatabaseContext> (options => options.UseSqlServer(configuration.GetConnectionString("DefaultConnection")));
I have defined the connection string in the appsettings.json as described in the documentation which is as follows:
{
"ConnectionStrings": {
"DefaultConnection": "Data Source=DESKTOP-PC009\\SQLEXPRESS;Database=Senua;Trusted_Connection=True;MultipleActiveResultSets=true"
},
"Logging": {
"IncludeScopes": false,
"Debug": {
"LogLevel": {
"Default": "Warning"
}
},
"Console": {
"LogLevel": {
"Default": "Warning"
}
}
}
}
I have already created the Senua database with a table in it which has no data. My database uses windows authentication.
I have defined my database context in the following manner with my single table.
public class DatabaseContext : DbContext
{
public DatabaseContext(DbContextOptions<DatabaseContext> options)
: base(options)
{
}
public DbSet<Hellheim> Hellheim { get; set; }
}
It was my understanding that this error is only typically visibly if you've failed to define your connection string in the appsettings.json file but I've already added it, has anyone had this problem before?
Define and assign a value to Configuration its of IConfiguration and requires a value.
Define the Dependency Injection in the constructor
public Startup(IConfiguration configuration)
{
this.configuration = configuration;
}

Categories