I started a .net core web api project.
I have one solution with the main project and many other project like DAL, Common etc.
I want to create a class in the Common project that will share configuration settings(appsettings.json) between my different library project.
So, How can I acces Iconfiguration from that class ?
Is this a good way to do this ? Or should I create a class into the main project to get configuration data from other project ?
One way to do it would be to create a Configuration Model based on your section/subsection from your appsettings.json file, add the configuration section in your Startup.cs class, then you can use the built-in dependency injection to inject the configuration anywhere you would need it.
For Example
appsettings.json :
{
"MyConfiguration" : {
"Configuration1" : "1",
}
}
Your configuration model:
public class MyConfiguration
{
public int Configuration1 { get; set; }
}
Then in the StartupClass in the ConfigureServices method you have to add
services.Configure<MyConfiguration>(configuration.GetSection("MyConfiguration"));
services.AddOptions();
And when you want to use that Configuration somewhere in the code, you would just inject it in the constructor like so:
public class SomeClass
{
private MyConfiguration MyConfiguration { get; }
public SomeClass(IOptions<MyConfiguration> myConfigurationOptions)
{
MyConfiguration = myConfigurationOptions.Value;
}
//... more code
}
Then you can access it
MyConfiguration.Configuration1
You can add the file as a link in yout project.
Right click your project , then select "Add" ->"Existing Item..."
Choose the file that you want to add to the solution
Instead of hitting Enter or clicking the Add button, you need to click the
down-arrow icon at the right edge of the Add button, and select "Add As Link".
Please refer to this link.
Related
When I try to add new controller with scaffold visual studio prompt a error message:
There was an error running the selected code generator:
Unable to resolve service for type
1Microsoft.EntityFramework.DbContextOptions1
I have already check other question about the same problem but the answer didn't applied to my case cause already is a reference in my DbContext class to DbContext
public class HospitalDbContext : DbContext
{
public HospitalDbContext(DbContextOptions<HospitalDbContext> options)
: base(options)
{
}
public virtual DbSet<Product> Products { get; set; } = null!;
}
And Program.cs is
var builder = WebApplication.CreateBuilder(args);
builder.Configuration.AddJsonFile("appsettings.json");
builder.Services.AddControllersWithViews();
var conf = builder.Configuration;
builder.Services.AddDbContext<HospitalDbContext>(options => options.UseSqlServer(
conf.GetConnectionString("Default")
)
);
var app = builder.Build();
This is the project link on github under branch "stackoverflow": https://github.com/heitorgiacominibrasil/Hospital-Management-System-ASPNETCORE/tree/stackoverflow
I have had something similar happend once. I am not sure if this will apply to this issue but when I had this error, I just kept on pressing the "Add" button. After a couple of tries it just added the controller.
Not really sure if it will fix it but everytime I do this it works.
Solved by creating a new asp.net core mvc project, added an folder with the models/classes I needed, added the dbcontext and generated the scaffold process again. After the scaffold finished I coppied the controllers and views to my original project. This problem seems to happens when are multiple projects, and scaffold can't handle.
I have a Core API project that was originally accessing the database from the controller (bad practice) so I moved the data access methods into an existing .NET class library where the connection strings are stored in the app.config file. The same connection strings are also located in the Core API project's appsettings.json/appsettings.development.json folders.
I then tried to access this new .NET class library method (containing the call to the database) from my API, but I'm getting the "can't find 'connectionstringname' in app.config" error. I'm new to .NET but a colleague was saying perhaps the app.config isn't getting pulled into the API's bin folder. Has anyone had problems with .NET Core projects struggling to communicate with .NET project's connection strings and how could I go about troubleshooting this?
1.) I tried pasting the app.config file into the API's bin folder, to no avail (same error.)
I've seen a few answers on SO but haven't been able to implement them successfully, so I apologize if this has been answered before.
You need to completely throw out your dot-net-framework understanding of config settings.
https://learn.microsoft.com/en-us/aspnet/core/fundamentals/configuration/options?view=aspnetcore-5.0
Note the value of the url.
aspnet core fundamentals configuration
In DotNet-Core:
Highly recommend creating a first class object. (config-value-holder-poco)
And in your Ioc Registrations, inject the config-value-holder-poco into the Ioc (aka, "servicecollection" in dn-core).
And then constructor inject your settings poco holder.
As per the article.
Json "section"
"Position": {
"Title": "Editor",
"Name": "Joe Smith"
}
First class config-value-holder-poco.
public class PositionOptions
{
public const string Position = "Position";
public string Title { get; set; }
public string Name { get; set; }
}
IoC registration.
public void ConfigureServices(IServiceCollection services)
{
services.Configure<PositionOptions>(Configuration.GetSection(
PositionOptions.Position));
}
Constructor Injection:
public class Test2Model : PageModel
{
private readonly PositionOptions _options;
public Test2Model(IOptions<PositionOptions> options)
{
_options = options.Value;
}
public ContentResult OnGet()
{
return Content($"Title: {_options.Title} \n" +
$"Name: {_options.Name}");
}
}
and now you can take advantage of the "refresh-rate" BUILT IN options for how these are treated.
https://medium.com/#kmar.ayush/eli5-ioptions-vs-ioptionssnaphot-vs-ioptionsmonitor-fab1d7e26a75
IOptions vs IOptionsSnaphot vs IOptionsMonitor
We are developing an nopCommerce based application. Our login page needs to be minimalistic and would need only an email id, password entry fields and a Login button.
Could you point me to best practices for achieving the above objective ?
Do I modify the corresponding pages found in \Presentation\Nop.Web\Views\Customer\ & controllers in \Presentation\Nop.Web\Controllers\
Or
Is there a better way of doing this and organizing all the modified files in one place/folder so that upgrading to future versions of nopCommerce will not be difficult ?
The requirement is to ensure that all the changes made to the project(views/controllers etc) are in one folder so that they are not overwritten when we upgrade to a newer version of nopCommerce.
I read somewhere that you can copy stuff you need to change (Login.chtml, CustomerController) to Themes/DefaultClean and then make your changes in this folder. I dont remember where i read it.
I feel doing so will make it that much easier to maintain our codebase because all your custom code is in one place/folder/sub folders
Is this a best practise? And is there a disadvantage to this method of doing things?
The best way to modify your nopCommerce project without changing anything in the core code would be to use the plugin functionality which is described here (assuming you're using the newest version 4.40).
To change the login page you would then need to create your modified version as a .cshtml file in your plugin. You then need to set this file as Content and set the Copy to Output Directory property to Copy if Newer or Copy Always.
You also need to implement the IViewLocationExpander interface so that the Razor Engine knows that it should use your custom Login Page. The implementation should look something like this:
public class MyViewLocationExpander : IViewLocationExpander
{
public IEnumerable<string> ExpandViewLocations(ViewLocationExpanderContext context, IEnumerable<string> viewLocations)
{
if(context.ViewName == "Login")
{
viewLocations = new[] { "PathToCustomLoginPage" }.Concat(viewLocations);
}
return viewLocations;
}
public void PopulateValues(ViewLocationExpanderContext context)
{
return;
}
}
After that you also need to register your ViewExpander by implementing the INopStartup interface. The implementation would look something like this:
public class MyStartup : INopStartup
{
public int Order => int.MaxValue;
public void Configure(IApplicationBuilder application)
{
}
public void ConfigureServices(IServiceCollection services, IConfiguration configuration)
{
services.Configure<RazorViewEngineOptions>(options =>
{
options.ViewLocationExpanders.Add(new MyViewLocationExpander());
});
}
}
I'm building up a server side Blazor application. Inside this Blazor app I already have the localization running using the "IStringLocalizer" mechanism.
Now my project has grown and I want to reuse components, so I created a razor class library where I put all my reusable components in.
Solution
|
|-- VISU (the Blazor Project project)
|
|-- UI.Components (RCL project containing the components)
The components contain some text which must be translated dependent on the actual culture.
At the RCL I did following.
a) I create a folder "Resources"
UI.Components (RCL Project)
|
|- Resources
b) inside the "Resource Folder" I create the resource "UIComponentText.resx" file containing the translation
c) inside the "Resource" folder I create a file containing the dummy class "UIComponentText"
Furthermore I create a service class "UIComponentLocalizer"
public class UIComponentText
{
}
public class UIComponentLocalizer
{
private readonly IStringLocalizer _localizer;
public UIComponentLocalizer(IStringLocalizerFactory factory)
{
var type = typeof(UIComponentText);
var assemblyName = new AssemblyName(type.GetTypeInfo().Assembly.FullName);
_localizer = factory.Create("UIComponentText", assemblyName.Name);
var all = _localizer.GetAllStrings(false); // test to see content
}
public LocalizedString this[string key] => _localizer[key];
public LocalizedString GetLocalizedString(string key)
{
return _localizer[key];
}
}
d) Inside startup.cs of the Blazor app, I register the service
services.AddSingleton<UIComponentLocalizer>();
e) Inside a component I inject the service to make use of it
[Inject] public UIComponentLocalizer CompTranslate { get; set; }
--> Finally it does not work. :-(
The UIComponentLocalizer service is started, but the dictionary is empty.
Actually, I'm thinking that the access to the resource file is wrong.
The component resource has the namespace "UI.Components.Resources.UIComponentText" which is not
like the resources inside the Blazor project ("VISU.Resources.xyz")
Questions:
a) is it possible to create a RCL which includes localization which can be "includes" inside a Blazor serve side app.
b) If yes? Where do I make a mistake
Thanks
Wolfgang
Try to add your Resource file via the builder.Services:
builder.Services.AddLocalization(options => options.ResourcesPath = "Resources");
And go from there. Maybe this helps too: Blazor Localization
var userName = ConfigurationManager.AppSettings["FileUploadRoot"];
Iam getting null for the variable Username. The key FileUploadRoot is in another projects web config entry and the above piece of code is in another projects class file. so can you please tell me how to get the value from the web config file
The best way would be to include the config value in your first project too, to make it self-contained.
You can use a static class in the project that has the web.config file and expose the value in the web.config in an internal property
You can use something like this:
static class Utility
{
internal static string FileUploadRoot
{
get
{
return ConfigurationManager.AppSettings["FileUploadRoot"];
}
}
}
Another solution would be to add the file as a link to your project.
Right click on you project in solution explorer.
Select Add Existing Item...
Select the web.config file in the OpenFileDialog, but choose the Add as Link option in the dialog.
There is built in functionality for this:
string otherExe = #"C:\projects\otherExe\bin\Debug\BillsAndStatementsArchiver.exe";
Configuration otherConfig = ConfigurationManager.OpenExeConfiguration(otherExe);
string fileUploadRoot = otherConfig.AppSettings.Settings["fileUploadRoot"].Value;