I've followed several methods on StackOverflow to fix my issue, none with a result:
My DefaultConnection-string is in my AppSettings.json. To retrieve info I am reading to use the IConfiguration from my startup.cs. The constructor of my MsSQL-context is still asking for this IConfiguration. Note: I'm using a repository pattern.
startup.cs:
public Startup(IConfiguration configuration)
{
this.Configuration = configuration;
}
public IConfiguration Configuration { get; private set; }
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IConfiguration>(Configuration);
I've added the Singleton in my startup after a suggestion. With or without this the constructor of MsSQLContext is still requesting this as a variable to be passed. Leaving the constructor without this gives me the error: Connectionstring not initialized.
AdminMsSQLContext:
private readonly string _connectionString;
public MSSQLAdminContext(IConfiguration configuration)
{
_connectionString = configuration.GetConnectionString("DefaultConnection");
}
Injecting IConfiguration is actually an anti-pattern, anyways. What you should be doing is supplying an action to your scope registration and change your MSSQLAdminContext class to accept just the connection string in its constructor:
public MSSQLAdminContext(string connectionString)
{
_connectionString = connectionString ?? throw new ArgumentNullException(nameof(connectionString));
}
Then:
services.AddScoped(_ =>
new MSSQLAdminContext(Configuration.GetConnectionString("DefaultConnection)));
Your repo should not have knowledge of something like your configuration. If it needs a connection string, then it should take the connection string, and that is all.
I believe the issue you are having is that you have not registered the MSSQLAdminContext with the DI container. Because of this the DI engine does not know to inject the IConfiguration into the class. In your start up you will register this class however you need, I tend to use scoped for these types of classes you may use in multiple places. So something like this.
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<MSSQLAdminContext>();
services.AddSingleton<IConfiguration>(Configuration);
}
Related
When trying to register a database context in startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(option => option.EnableEndpointRouting = false);
services.AddDbContext<PostDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("PostDbContext")));
}
I get error
The name "Configuration" does not exist in the current context.
All code examples are taken from the official Microsoft documentation.
Tutorials -> MVC -> Get started -> Add model.
ASP.NET Core version: 3.1
How fix it?
I have not defined a configuration.
public IConfiguration Configuration { get; }
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
This problem occurs because you have not defined Configuration which is an instance of IConfiguration interface like this-
public IConfiguration Configuration { get; }
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
Here Configuration is important to define which checks configuration details.
For Ex.-Configuration.GetConnectionString("Your Connection String") checks the connection string from appsettings.json file to get or set data in database.
I have a .net Core application and I've been attempting to read from my local instance of SQL Server (2014) with Windows Authentication and continue to run into a repeat error about my connection string. I've been reviewing the MSDN docs as well as connectionstrings.com and thought I had everything configured correctly.
This is my error:
"System.ArgumentException: 'Format of the initialization string does
not conform to specification starting at index 0.'"
Which I take to mean the very start of my connection string.
I have read the other posts related to this exact issue but haven't been able to use them to find a solution.
Here is what I attempt when the error occurs:
public class HomeController : Controller
{
private ModelContext _context;
public HomeController()
{}
public IActionResult Index()
{
var viewModel = new HomeViewModel();
var optionsBuilder = new DbContextOptionsBuilder<ModelContext>();
optionsBuilder.UseSqlServer("DefaultConnection");
using (_context = new ModelContext(optionsBuilder.Options))
{
>>>>>> viewModel.List = _context.TableName.ToList(); <<<<<<<<
I have the following in my "appsettings.json" file:
"ConnectionStrings": {
"DefaultConnection": "Server=MyComputerName; Database=DBName; IntegratedSecurity=SSPI;"
},
In my "ModelContext.cs" file
public class ModelContext : DbContext
{
public ModelContext(DbContextOptions<ModelContext> options)
:base(options)
{ }
[<Table Properties>]
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("DefaultConnection");
}
And "Startup.cs" file:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddDbContext<ModelContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
}
Thanks for taking a look!
After much contemplation and re-review of the MS Documents site for EF Core DbContext, I found that I was attempting to implement ALL 3 methods of DbContext configuration: Constructor Argument, OnConfiguring, and dependency injection.
Decided to go with OnConfiguring to get the app moving.
After I've read this article about dependency injection Here I still do not have a clear understanding on how to read the appsetting in other than a controller classes.
Lets say for instance I have a helper class with a bunch of static methods that I'm planning to use, I do not create an instance of this class, how do I read setting values to use inside the methods of this class?
I used to create helper class to read data from appsettings.config in one of my applications:
public static class ConfigValueProvider
{
private static readonly IConfigurationRoot Configuration;
static ConfigValueProvider()
{
var builder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);
Configuration = builder.Build();
}
public static string Get(string name)
{
return Configuration[name];
}
}
However later I reviewed my application to get away from static methods which depends on application config in order to make my application testable.
You should use services.Configure as below:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.Configure<JSonAsClass>(Configuration.GetSection("MySectionName"));
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}
then you can inject JSonAsClass inside any class you want to use it:
private JSonAsClass jSonAsClass;
public MailService(IOptions<JSonAsClass> jSonAsClass)
{
this.jSonAsClass = jSonAsClass.Value;
}
Here is my asp.net core project structure
1- ASP.NET CORE Web API (contains aspsettings.json)
"ConnectionStrings": {
"DefaultConnection": "Server=(local)\\SQLEXPRESS;Database=testdb;Trusted_Connection=True;"
}
2-SERVICES Project (Web API Call method from Services Project)
3-REPOSITORY Project (Services call method from Repository Project and Repository Project include the DATA Project where all the models are)
4-DATA Project where it's contain all the model with code first
public class TtEntities : DbContext
{
public virtual DbSet<RoomMessage> RoomMessage { get; set; }
public virtual DbSet<UserRoom> UserRoom { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(#"Server=(local)\SQLEXPRESS;Database=testdb;Trusted_Connection=True;");
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
....
As you can see, I hardcoded the connection on the method OnConfiguring which is not the best practice for sure.
Is there a way to pass the connection string from the configuration file of the Web API Project?
Is update database command will still work if we pass the connection from the file aspsettings.json from web api project ?
Thanks a lot
A simple solution is like this:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
}
}
Consider how DefaultConnection is used in line 13. Also a sample appsettings is like as follow:
{
"ConnectionStrings": {
"DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=aspnet-WebApplication5;"
}
}
DI solves this problem perfectly and .NET Core 2.0 has Microsoft DI thats provides clearly experience with DI.
oh, lets starts(i think that DATA Project and REPOSITORY Project should be one)
from REPOSITORY Project
change your REPOSITORYClass to
public class REPOSITORYClass
{
private readonly TtEntities _db;
public REPOSITORYClass (TtEntities db){
_db = db;
}
//some your staff of REPOSITORYClass thats uses _db
}
now go to SERVICES Project
lets change some service that uses REPOSITORYClass
public class SomeService
{
private readonly REPOSITORYClass _repo;
public SomeService (REPOSITORYClass repo){
_repo = repo;
}
//other staff of SomeService thats uses _repo
}
after that go to ASP.NET CORE Web API startup file and add to
public void ConfigureServices
// Get connection of your repo
string connection = Configuration.GetConnectionString("DefaultConnection");
// add TtEntities as service
services.AddDbContext<TtEntities>(options =>
options.UseSqlServer(connection));
//add your repo
services.AddTransient<REPOSITORYClass>();
//add your service
services.AddTransient<SomeService>();
now go to the contoller thats uses your SomeService
public class SomeController: Controller
{
private readonly SomeService _someService;
public SomeController(SomeService someService){
_someService = someService;
}
//And use whatever your wants from your service that injected with deps of repo and injected db entity with connection
public string SomeMethod()
{
return _someService.SomeMethod();
}
}
And use whatever your wants from your service that injected with deps of repo and injected db entity with connection
thats all
PS also recommend to read this Introduction to Dependency Injection in ASP.NET Core
This question already has answers here:
Inject service into Action Filter
(6 answers)
Closed 6 years ago.
I am writing attribute that will verify captcha. In order to work correctly it needs to know secret, which I keep in the settings (Secret manager tool). However I don't know how to read config from the attribute class. DI in asp.net core supports constructor injection (and property injection is not supported), so this will give compilation error:
public ValidateReCaptchaAttribute(IConfiguration configuration)
{
if (configuration == null)
{
throw new ArgumentNullException("configuration");
}
this.m_configuration = configuration;
}
because when I decorate method with [ValidateReCaptcha] I can't pass config
So how do I can read something from config from the method in attribute class?
You can use ServiceFilter attribute, more info in this blog post and asp.net docs.
[ServiceFilter(typeof(ValidateReCaptchaAttribute))]
public IActionResult SomeAction()
In Startup
public void ConfigureServices(IServiceCollection services)
{
// Add functionality to inject IOptions<T>
services.AddOptions();
// Add our Config object so it can be injected
services.Configure<CaptchaSettings>(Configuration.GetSection("CaptchaSettings"));
services.AddScoped<ValidateReCaptchaAttribute>();
...
}
And ValidateReCaptchaAttribute
public class ValidateReCaptchaAttribute : ActionFilterAttribute
{
private readonly CaptchaSettings _settings;
public ValidateReCaptchaAttribute(IOptions<CaptchaSettings> options)
{
_settings = options.Value;
}
public override void OnActionExecuting(ActionExecutingContext context)
{
...
base.OnActionExecuting(context);
}
}
You should use ServiceFilter like this:
[ServiceFilter(typeof(ValidateReCaptcha))]
And if you want to use IConfiguration you should inject it in ConfigureServices:
services.AddSingleton((provider)=>
{
return Configuration;
});