I'm using AutoMapper in a number of projects within my solution.
These projects may be deployed independantly, across multiple servers.
In the documentation for AutoMapper it says:
If you're using the static Mapper
method, configuration only needs to
happen once per AppDomain. That means
the best place to put the
configuration code is in application
startup, such as the Global.asax file
for ASP.NET applications.
Whilst some of the projects will be ASP.net - most of these are class libraries / windows services.
Where should I be configuring my mappings in this case?
The idea that it should only be required once per AppDomain stays the same, as far as I can tell. I always perform my mappings upon the initialization of the program itself. While I am not using AutoMapper I am using an IoC library (Windsor) which requires a mapping of sorts and this is done from my program.cs file. So when the application loads it performs the mapping and because the resolver is static and in a shared library it is available globally.
I don't know if this answers your question or not, but essentially every app has an entry point and if you need your mappings immediately after entry then the entry is the best place to put them.
I've elected to store my mappings in separate classes for each project so that they are reusable.
protected void Application_Start()
{
RegisterMaps();
}
private void RegisterMaps()
{
WebAutoMapperSettings.Register();
BusinessLogicAutoMapperSettings.Register();
}
This way I can easily call BusinessLogicAutoMapperSettings.Register() if I were to reuse only my BusinessLogic dll in another application or webservice
Related
I am writing a process that brokers data transfer between two identical APIs (FWIW, one is a local API running in a different container, and the other is in the cloud).
I want to write some test code to ensure that the data transfer code does what it should. Up till now, I've been using TestServer for API tests, but now things might get a little complicated when I want to run two servers. A couple of questions arise:
How do I get them to use different appsettings.json files? Right now, with just one TestServer, it's using the appsettings.json of the test project. How do you configure a TestServer to use a different config file?
Once I have two TestServers up and running, do they function as completely independent entities? Most particularly, if I have any static values, will their values be shared between the two environments, or can they function independently, as they would in real life?
This depends a little bit on how you're creating your TestServer.
If you're using TestServer's constructor (which takes a IWebHostBuilder as input), you can use the web host builder's ConfigureAppConfiguration method to setup whatever configuration sources you want. Appsettings.json is the default config source if you don't change anything, but it should be easy to create two separate TestServers using different IWebHostBuilders, each with their own ConfigureAppConfiguration call.
If you're using the WebApplicationFactory approach, you can create a custom WebApplicationFactory and setup configuration sources in that type's ConfigureWebHost method.
Since they run in the same process/appdomain, the two TestServers will be separate instances but share statics. If that's not desirable, you could consider running on of the servers out-of-process as a 'real' server (instead of a TestServer) or, maybe even better, avoid the use of statics!
We need a lot more information here... How are you registering your appsettings.json? Are you using DI?
a) Transform your config for your environment (server/cloud)
How do I transform appsettings.json in a .NET Core MVC project?
b) Create a second appsettings and change that in your application config.
https://learn.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-2.2
I've created a log4net wrapper class for my project team to use so we can all log from the same instance of log4net in our project. We're unsure what section this could come under i.e. Controller, one suggestion was to create a separate folder altogether for "Helper" classes.
Is there an industry standard to follow for this that we could use?
I can't speak to an 'industry standard' but for our application, putting the logging at the lowest level has worked best for us. We created our own class that wraps the 3rd party functionality in a one of our libraries referenced by nearly all others. Then we implemented our own methods to simplify and standardize logging in our app. This approach makes it possible to use logging anywhere without significant project changes. You'd just have to add static method calls where you need to log something.
No there's no industrial standard for such things. Nevertheless, instead of creating another wrapper for log4net consider using the existing one. Then simply register it in the DI of your choice and inject it via constructor.
I have a web application which is supposed to be composed as a series of plugins into a core infrastructure. A plugin is a compiled CLR dll + some content files which will be put in a certain location. I'm using Autofac to scan and register types out of the assembly, and some fancy routing to serve controllers and assets from there. But, since each plugin assembly can contain a DbContext (by convention each will use its own database), I can't quite figure out what to do there.
Now I've found a lot of stuff around how to use multiple contexts but it all requires knowing what these will be at development time. My application does not know what contexts will be used until runtime.
What I'm looking for ideally is would like is some way to do
ApplyMigrations<MyDbContext, MyDbConfiguration>();
Though I would also somehow have to provide an ordered set of migrations to apply (if using explicit migrations).
Where I'm stumbling currently is the standard
Database.SetInitializer(...)
since it is a static singleton and each dbcontext in my system has its own initializer.
First, of all SetInitializer stores the IDatabaseInitializer objects in a dictionary with the context Type as key, so theoretically multiple calls of SetInitializer should work fine.
On the other hand, if that doesn't work, another option is to explicitly perform initialization:
class YourContext : DbContext
{
static YourContext()
{
Database.SetInitializer<YourContext>(YourMigratingDatabaseInitializer);
using (var context = new YourContext())
{
context.Database.Initialize(false);
}
}
public YourContext()
{
Database.SetInitializer<YourContext>(null);
}
}
Perhaps write an interface for bootstrapping a plugin, so IPluginBootstrapper - from here you could pass in a ContainerBuilder to add to a collection of services that the plugin provides, or return a built Container that the plugin builds and combine it on the host. In this way, you're pushing the responsibility of the all the DB seed/migration work into each plugin - so when you drop in a new dll, when it's bootstrapped it can run it's own upgrade path.
Another alternative, perhaps you can have a configuration section which defines a pair of types, so Tuple and tell Autofac to find all pairs of these in the plugins directory, and then call SetInitializer with what is resolved?
I'm organizing a solution and I need some tips on how to properly arrange the project's components.
Right now I have everything implemented on a single project, but I feel like it makes sense to isolate some of the components on their own projects. The main modules I have are categorzed by folders on the project, and are the Logic module, Database Access module and the Model module. It makes sense to me that these modules should be defined on their own project (maybe as a DLL).
Now, my question comes from the fact that during the application startup, the logic instantiates a configuration class which reads configurations from the app.config file and is known by these modules. Does it make sense to isolate the configuration into it's own project, to prevent the other modules from depending on the logic module? If so, should the configuration class implement from interfaces so that each module only has access to it's relevant configurations?
"The main modules I have are categorzed by folders on the project, and
are the Logic module, Database Access module and the Model module...
the logic instantiates a configuration class which reads
configurations from the app.config file and is known by these
modules."
The picture this paints to me is that you've got a class or classes that either take the configuration class as a constructor parameter, or there's a global/ singleton instance of the configuration class that the other classes make use of.
But the configuration class can read configs, etc. Presumably, the other classes don't need something that can read configs. They just need some values* (that happen for now to be read from a config). Those other classes don't need to go out and ask anybody for those values**; they should just require those values as parameters in their constructors.
This way, those other classes do not need to have any knowledge of the configuration class. Someone just hands them the data that they need. But who?
The answer is the entry point(s)***. Each project in the solution that contains an entry point (console apps, web apps, and test projects) has the responsibility for interfacing with the environment; it knows the context that it wants the rest of the code to run in. So the entry points need to get configuration information by whatever means necessary (e.g. your configuration class or the autogenerated MyEntryPoint.Properties.Settings) and then supply that to the constructors of the other classes they need.
*If each class requires a great deal of configuration information (as your comment below implies), consider either breaking those classes up into something simpler (because needing a lot of configuration may point to an ill-defined responsibility) or grouping the necessary information into DTOs that represent coherent concepts. Those DTOs could then be placed in their own project that can be referenced by both consumers and producers of configuration information.
**This assumes that the values obtained from the configuration class are constant for the lifetime of the objects that would be constructed with them. If not, then instead of taking those values as constructor parameters, you should take an interface (or Func) that you can call for the info you need when you need it. Those interfaces could be defined in an otherwise-empty project which anybody can reference. This sounds like what you're getting at with
"should the configuration class implement from interfaces so that each module only has access to it's relevant configurations?"
When you say
"Does it make sense to isolate the configuration into it's own project, to prevent the other modules from depending on the logic module?"
the answer is yes and no. The Logic module does stuff; doing stuff implies a need for tests; tests want to configure whatever they are testing in whatever way suits the test. So Logic shouldn't be responsible for configuration; it should itself take in information from whoever does the configuration. Rather, configuration is the entry points' job.
***I'm using "entry point" a little loosely here. I'm not talking specifically about the .entrypoint IL directive, but just the first places in your code that can be given control by stuff outside of your control. This includes Main in C# console apps, HttpApplication.Application_Start in web apps, methods recognized as tests by the test runner of your choice, etc.
I am reading StructureMap about dependency injection, well there are two parts first to initialize the mapping, interface to concrete class type, and another one is just instantiation (asking for an instance).
First part requires configuration, setup which is mentioned to be done at a boot strapper.
what s the best practice for a boot strapper? static class with static constructors? how about in IIS?
Also, how can i configure Structure Map so that without restarting the application, I can change the dependencies? is that possible? how?
The configuration is done in the Composition Root. IoC container support for ASP.NET WebForms is very bad. The pages are created by IIS. The only thing you can do here is to inject properties after the page is created.
If you want to do DI for Websites then you should use MVC 3 instead of WebForms. In this case there is an integration package Structuremap.MVC3 that does the bootstrapping for you. You can find it on nuget. https://github.com/webadvanced/Structuremap-MVC3
Using a static class with a static constructor doesn't help much, because the static constructor won't get called until the class is actually used by the running code. Hence your best option is to bootstrap the DI in the program's main() method.
In IIS or similar environment there are usually events that get fired when the application / add-in / component is loaded or 'started'. In ASP.NET (that is in IIS) the global application events in the global.asax.cs file serve this purpose.