In my aspnetcore app (v2.1) I need to configure a read-only database (entityframework core + SQLite) which is in ~/wwwroot/App_Data/quranx.db
I need to call this code in Startup.ConfigureServices
services.AddDbContext<QuranXDataContext>(options => options
.UseSqlite($"Data Source={databasePath}")
.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking)
);
But at that point I cannot find a way to get the path to wwwroot. To get that path I need IHostingEnvironment, but I am unable to get a reference to that until Startup.Configure is called, and that is after Startup.ConfigureServices has finished.
How is this done?
It's easy enough to access IHostingEnvironment in ConfigureServices (I've explained how below) but before you read the specifics, take a look at Chris Pratt's warning in the comments about how storing a database in wwwroot is a very bad idea.
You can take a constructor parameter of type IHostingEnviroment in your Startup class and capture that as a field, which you can then use in ConfigureServices:
public class Startup
{
private readonly IHostingEnvironment _env;
public Startup(IHostingEnvironment env)
{
_env = env;
}
public void ConfigureServices(IServiceCollection services)
{
// Use _env.WebRootPath here.
}
// ...
}
For ASP.NET Core 3.0+, use IWebHostEnvironment instead of IHostingEnvironment.
Path.GetFullPath("wwwroot");
Related
I am trying to create an Angular 8 project with asp.net Core 2.1.
Whenever I try to add migration using command
cmd command: dotnet ef migrations add init --project ../Lgn.DAL
The terminal throws error :
Unable to create an object of type 'ApplicationDbContext'. Add an implementation of 'IDesignTimeDbContextFactory' to the project, or see https://go.microsoft.com/fwlink/?linkid=851728 for additional patterns supported at design time.
Startup.cs
``
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.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlite(Configuration.GetConnectionString("DefaultConnection")));
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseHsts();
}
app.UseCors(builder =>
{
builder.WithOrigins("http://localhost:4200");
builder.AllowAnyMethod();
builder.AllowAnyHeader();
});
app.UseHttpsRedirection();
app.UseMvc();
}
}``
Take a look at this solution to someone with a similar issue. Is your dependency injection setup all good? (number 2 on that list)
Here are the things to consider:
You get that error because to generate migrations you need either:
A DbContext with a default constructor (that is, a parameterless
constructor)
Being able to get the DbContext from ApplicationServices
(that is, Dependency Injection)
A design time factory that returns a
properly configured DbContext.
I have a blazor component in my application:
public class IndexComponent : ComponentBase
{
public string ContentRoot { get; set; }
public string WebRoot { get; set; }
private IHostingEnvironment HostingEnvironment;
public IndexComponent(IHostingEnvironment hostingEnvironment)
{
HostingEnvironment = hostingEnvironment;
}
protected override async Task OnInitAsync()
{
//Some Code Here
}
}
I am trying to use DI in my app , for example IHostingEnvironment.
Code give no compile time error here but when i run it than in code behind file of this razor (Index.razor.g.cs file):
public class Index : IndexComponent
at this line it says:
There is no argument given that corresponds to the required formal
parameter hostingEnvironment of IndexComponent.IndexComponent
This can be solved by using #inject IHostingEnvironment in Razor file but I am moving my function block from Razor to IndexComponent.cs file so need it there.
Neither of it works in below way:
[Inject]
IHostingEnvironment HostingEnvironment
What will work here?
Note: No use of ViewModel
Update 1
In StartUp.cs by adding namespace
using Microsoft.AspNetCore.Hosting.Internal;
And than
services.AddSingleton<IHostingEnvironment>(new HostingEnvironment());
It is now able to register IHostingEnvironment on client side project but it does not have values for its properties (contentrootpath and webrootpath).
Only one thing is available here which is EnvironmentName and its value is always Production ,
Update:
The error is from WebAssembly, so it is a client-side app. There is no HostingEnvironment on the client and therefore the service is not registered. It would be useless if it was.
So, step back: Why do (you think) you need it?
You should make it a protected or public read/write property:
// in IndexComponent
[Inject]
protected IHostingEnvironment HostingEnvironment { get; set; }
and remove the constructor parameters.
Side note: IHostingEnvironment is marked as obsolete.
It turns out that for Blazor you need a slightly different interface, namely IWebAssemblyHostEnvironment.
From this documentation, what you should inject is:
#inject IWebAssemblyHostEnvironment HostEnvironment
From this comment:
WASM: System.InvalidOperationException: Cannot provide a value for property 'HostingEnvironment' on type 'JewelShut.Client.Pages.Index'. There is no registered service of type 'Microsoft.AspNetCore.Hosting.IHostingEnvironment'
I'm guessing this is a client side Blazor application. (My apologies if I'm wrong with my guess.). On client side Blazor the IHostingEnvironment is not registered by default in DI container. Still the error says that the service you are trying to inject is not registered. To register a service:
In the Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
//few sample for you
services.AddScoped<AuthenticationStateProvider, ApiAuthenticationStateProvider>();
services.AddAuthorizationCore();
//register the required services
//services.Add...
}
If the injected service is registered the way #Henk Holterman has suggested is the right answer.
Di in blazor
I am trying to store my connection string into my system(windows 10) environment variable to protect my sensitive information before going to production.
When I do call my environment variables, it returns a null value. I don't have any errors.
I did follow those tutorials:
https://www.youtube.com/watch?v=TNghzUs0BQI&fbclid=IwAR2YUue7740qgVT_5z04xruel-4NwOuUyjQj5E63T1UpYqRoVuz_81DiZTo
https://medium.com/#gparlakov/the-confusion-of-asp-net-configuration-with-environment-variables-c06c545ef732
I don't see what I am missing here. For what I understand, if I don't use prefixes, I juste need to set the environment variable in my system and then make the call.
Here is an image of my environment variable. I do provide a link, because I don't have enough internet points to post the image.
https://i.imgur.com/j614O1n.png
This is my Startup.cs
private IConfiguration _configuration;
public Startup(IConfiguration configuration)
{
_configuration = configuration;
}
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddDbContext<dbApplicationServiceNavada>(options => options.UseMySql(Environment.GetEnvironmentVariable("ASNConnStr")));
services.AddScoped<IEmployeeData, SqlEmployeeData>();
services.AddScoped<ILanguageData, SqlLanguageData>();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app,
IHostingEnvironment env,
IConfiguration configuration)
{
//Show exception stack trace when in dev mode
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
//Use files in wwwroot folder
app.UseStaticFiles();
//Defines the available routes
app.UseMvc(ConfigureRoutes);
app.Run(async (context) =>
{
var RNA = configuration["RouteNA"];
context.Response.ContentType = "text/plain";
await context.Response.WriteAsync(RNA);
});
}
This is my webHostBuilder in Program.cs
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.AddEnvironmentVariables();
})
.UseStartup<Startup>()
.Build();
I also see that I have a launchSettings.json file with Environment variables in there, but I wonder if it's the same thing as system environement variables.
FIRST EDIT:
As mentioned in the answer, I did rename my environment variable to
MYSQLCONNSTR_ASNConnStr
I also removed the part in my program.cs to load environmental variable.
Now when I debug the project, I see in my _confirguration.Providers my environment variable getting loaded.
Here is a picture:
https://i.imgur.com/xGulUvX.png
When I do
services.AddDbContext<dbApplicationServiceNavada>(options => options.UseMySql(_configuration.GetConnectionString("ASNConnStr")));
It still returns a null value. I don't seem to be able to get the variable.
Picture of the error:
https://i.imgur.com/Kj0mvCS.png
SECOND EDIT:
Now the problem is solved, I just want to add to the contributor Simply Ged, that instead of :
services.AddDbContext<dbApplicationServiceNavada>(options => options.UseMySql(_configuration.GetConnectionString("ASNConnStr")));
I had to do:
services.AddDbContext<dbApplicationServiceNavada>(options => options.UseMySql(Environment.GetEnvironmentVariable("ASNConnStr")));
Now everything works fine!
THIRD EDIT:
After restarting my computer, this line of code works:
services.AddDbContext<dbApplicationServiceNavada>(options => options.UseMySql(_configuration.GetConnectionString("ASNConnStr")));
It appears that we need to restart the computer/server in order to get the environmental variable adequatly.
In Conclusion, the answer of the contributor Simply Ged was right.
You don't need to add ConfigureAppConfiguration to add environment variables to the configuration as it is done as part of WebHost.CreateDefaultBuilder. See this page for details about what the default builder provides.
Knowing that, you can replace read your connection string from the Configuration class:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddDbContext<dbApplicationServiceNavada>(options => options.UseMySql(Configuration.GetConnectionString("ASNConnStr")));
....
}
The Configuration class will load the correct value based on the order that is defined here
You would also need to change your environment variable name to the following:
MYSQLCONNSTR_ASNConnStr
You can read more about the Configuration in .NET Core here
I want to disable caching when running ASP.NET core application in Development environment. How can i do that?
I'm setting cache up in Startup:
services.AddMemoryCache();
I want to disable cache in templates, which use the <cache> tag:
<cache expires-after="#TimeSpan.FromSeconds(3600)">
You can simply inject IHostingEnvironment into the startup constructor of your Startup.cs
Like So
private readonly IHostingEnvironment _environment;
public Startup(IConfiguration configuration,IHostingEnvironment environment)
{
_environment = environment;
Configuration = configuration;
}
Then you can use the private IHostingEnvironment inside your configures services method .
public void ConfigureServices(IServiceCollection services)
{
if(!_environment.IsDevelopment())
services.AddMemoryCache();
}
EDIT :
After rereading the question the cache tags should be disabled aswell.
I would suggest adding a flag inside your appsettings.devlopment.json called"PageCachingEnabled": "false" .
On the view I would then inject the configuration like so
#using Microsoft.Extensions.Configuration
#inject IConfiguration Configuration
<cache enabled=#Boolean.Parse(Configuration["PageCachingEnabled"]) expires-after="#TimeSpan.FromSeconds(3600)">
The trick is to use services.AddDistributedMemoryCache(); in development, this will use the memory of the running system as a cache.
if(Env.IsDevelopment()) {
services.AddDistributedMemoryCache();
} else {
services.AddStackExchangeRedisCache();
}
I have an ASP.Net vNext project that uses Session. But I am getting this error while trying to get/set values in the session.
An exception of type 'System.InvalidOperationException' occurred in Microsoft.AspNet.Http.Core.dll but was not handled in user code
Additional information: Session has not been configured for this application or request.
Here's my controller method:
[AllowAnonymous]
[HttpGet("/admin")]
public IActionResult Index()
{
if (Context.Session.GetString("UserName") == null) // error thrown here
{
return RedirectToAction("Login");
}
return View();
}
I have added the KVM package "Microsoft.AspNet.Session": "1.0.0-beta3" in my project.json file as well and have configured my application to use session via my Startup.cs like so:
public void ConfigureServices(IServiceCollection services)
{
// code removed for brevity
services.AddCachingServices();
services.AddSessionServices();
}
public void Configure(IApplicationBuilder app)
{
app.UseMvc();
app.UseInMemorySession(configure: s => s.IdleTimeout = TimeSpan.FromMinutes(30));
}
I have looked at the vNext documentation on Github but it does not provide much information about ASP.Net sessions. What am I doing wrong?
So I figured this out. The fix was quite simple actually. Since ASP.Net adds the middlewares sequentially into the request pipeline, all I needed to do was use the session middleware before using MVC. More info here: https://stackoverflow.com/a/29569746/832546
Fixed code:
public void Configure(IApplicationBuilder app)
{
app.UseInMemorySession(configure: s => s.IdleTimeout = TimeSpan.FromMinutes(30));
app.UseMvc();
}
Thanks to #acrhistof the link helped.
So if you are using RC1:
add this these dependencies in project.json:
"Microsoft.AspNet.Session": "1.0.0-rc1-final",
"Microsoft.Extensions.Caching.Memory": "1.0.0",
in Startup.cs file:
public void ConfigureServices(IServiceCollection services)
{
services.AddCaching();
services.AddSession();
services.AddMvc();
}
and
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
app.UseSession(); //outside of dev if (env.IsDevelopment())
....
}
It seems like things changed once again and the well-known ASP.NET session has to be configured differently in the rc1. (no UseInMemorySession() or other AppBuilder methods are related to Session, now it is added as a service).
In general Session has to be installed, configured, and then used. All these steps are quite new and somewhat unusual. Moreover, it depends on Cache:
Session is built on top of IDistributedCache, so you must configure
this as well, otherwise you will receive an error.
The quotation above is from ASP.NET 5 docs. All you need to do is described here: https://docs.asp.net/en/latest/fundamentals/app-state.html#installing-and-configuring-session.