With ASP.NET 4.5 it is possible to use Assembly.Load() or AppDomain.CurrentDomain.Load() to dynamically load an assembly at runtime. This can be used to add new functionality to a running web application in the form of modules without having to rebuild or even restart the app.
I would like to know how this can be done with the new ASP.NET vNext (5.0?) targeting the Core framework. I know this can be done with the full framework as System.AppDomain is available along with an overloaded Assembly.Load(). When I change to target the Core framework, I no longer have System.AppDomain available and Assembly.Load() becomes limited.
Is there a way to get this dynamic modular functionality in the ASP.NET 5.0 Core framework?
I'm not sure what a good answer would be, because Asp.Net 5 is so new, and doesn't have a lot of full documentation.
It should theoretically be possible, it'll just be different than what you're used to.
Looking at the source there is an interface IAssemblyLoadContext which will allow you to get the assembly. There is also IAssemblyLoader.
These are used by the "kre" host, which is the underlying piece of Asp.Net 5 that basically boostraps your application. So you would need to add your IAssemblyLoader to the underlying host, so that the kre.
Unfortunately I'm not seeing very many extension points in the code as of yet. Will we be getting those extension points? I do not know. You can log an issue on the github page. It's also possible there is an extension point I'm not seeing currently.
To come back to the question, can you add that kind of extensiblity to Asp.Net 5 Core? Yes, you could create your own host, similar to the default host, that would then include your custom loader, and then start your application with that.
You can try ExtCore framework
It allows to have modular and extendable ASP.NET 5 applications out of the box.
In short
It allows to use both modules from dlls and from nuget packages at the same time.
It allows all modules to work with storage in the single context and to have their own models and repositories.
Every extension can have controllers, views, static content etc.
Related
I am trying to figure out how to possibly configure the use of different Service Containers for different routes/endpoints in a ASP.NET Core (.NET 5) application.
The background is that we have an application on ASP.NET 4.x that allows for plugins to register their own routes/endpoints (under configurable prefixes - that is also something I need to figure out in ASP.NET Core) - each such plugin gets its own Castle Windsor container where it can register services and other things with services we pre-register in that container. This container is also used to activate any ASP.NET WebApi controllers for that particular plugin.
We have done this by building some custom routing on top of ASP.NET 4 WebAPI/MVC where the route has information about which context it originates from (The core Application or a Plugin) as well as automatically prepending the prefix.
However, ASP.NET Core WebAPI/MVC has changed allot of things and I can't quite figure out how to get to the same result.
Because this is driven by plugins, it doesn't have to be done on a PER route basis obviously, instead PER plugin is good enough (Which would be a group of routes under the same prefix), so I have been trying to figure out of any of these provided a viable path for me:
Application Parts
Feature Providers (that container application parts)
Controller activators
I did try out a combination of all the above where a ApplicationPart would return custom implementation of types, there by letting us carry extra info about the controller to the IControllerActivator. However ASP.NET Core requires RuntimeType's rather than just any "TypeInfo" implementation.
I had a similar question and ran across this blog post which provides an example of using different IServiceCollections for different route prefixes. I think you can adapt it to get what you want.
Apparently the author also published the code in the WebAPIContrib.Core library (nuget package here).
Using Visual Studio 2017, I just created a simple API project as shown below.
And in the Startup.cs file I have this code.
public void ConfigureServices(IServiceCollection services) {
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}
Can someone please throw some light as to what is means? Do we need to keep this code?
I think MS should put some comments to indicate what such code does.
When you call the AddMvc method, several components are registered with certain options. You call one method and the whole mvc framework is wired up.
However, if the mvc team in the future decides to change a default value, or decides that a component is no longer to be registered by default, or changes an expected side effect of this method, the user code relying on that would break. To avoid such breakage, you can call the set compatibility method which the mvc team will use to preserve the behavior provided to you.
Suppose they introduce a new feature, which exists only when you are targeting the 2.3 platform: if your code declares that it targets the 2.2 api, the mvc team will know that you are not using that feature because it was not existing at that time. This way the can make safe assumptions about what should be provided and how.
For further details, please look at MSDN.
Yennefer's answer is great, i'll just add some things.
For ASP.NET Core 2.X it might very well be needed to use SetCompatibilityVersion, for the reasons Yennefer described.
For ASP.NET Core 3.0 it's a no-op, meaning it does absolutely nothing. Read more here.
For ASP.NET Core 3.X (but not 3.0) and forward, it might have a value. Read more here
FYI, SetCompatibilityVersion is a no-op for .Net Core 3 or later and deprecated in .Net 6.
https://learn.microsoft.com/en-us/aspnet/core/mvc/compatibility-version?view=aspnetcore-5.0
Does ASP.NET Core implement IConfiguration access to config values?
Most likely my question arose because I don't understand what exactly ASP.NET Core is. Well, I know it's a web framework, Not sure, but looks like it is a namespace in .NET, or a package... I know in php, a framework could be a set of classes (a namespace) or compiled library which is provided as an extension so I presume a similar approach in .NET.
Initially, I didn't intend to wrap my head around ASP.NET Core yet. I needed to store some config for my simple console C# application (VS Code and .NET Core). I've found a lot of topics (for example here: How to read values from config.json in Console Application) that to read JSON (recommended) config. Given that, I added three necessary nugget packages:
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Configuration.FileExtensions;
using Microsoft.Extensions.Configuration.Json;
I need to use:
new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json").Build();
This returns an object that implements the IConfigurationRoot/IConfiguration interface. But all the examples are given in an ASP.NET Core context. I have a really simple app and I don't need any of ASP.NET functionality yet.
So I've tried to access IConfigurationRoot without ASP.NET. The resulting object stores values from config file, but does not have all methods of its interface to access them.
How to explain this in context of .NET namespaces? Does ASP.NET Core implement methods to access values from IConfiguration like Get<T>()?
If Microsoft.Extensions.Configuration is part of or heavily dependent on Microsoft.AspNetCore.App, why is it in different namespace?
If I add ASP.NET Core (NuGet package and namespaces), will it be an overkill?
Maybe I should use soemthing other than ConfigurationBuilder to read JSON?
Microsoft.Extensions.Configuration, like other packages in the Microsoft.Extensions namespace (e.g. Options, or DependencyInjection), are packages that were created as part of the ASP.NET Core framework. The way ASP.NET Core and all its related packages were built however is in a very modular way, so all the libraries can be used within the ASP.NET Core context, or without.
You have to understand those packages just as libraries. They are included in ASP.NET Core since the framework builds on top of them, but if you do not need the ASP.NET Core web framework, you can still use those libraries separately without any mention of ASP.NET Core. That’s actually why they live inside the Microsoft.Extensions namespace instead of Microsoft.AspNetCore: They are completely separate projects. Of course, development of those packages is done by the ASP.NET Core team and the design decisions of ASP.NET Core do affect how those extension packages evolve; but the team is very careful with these packages so that the general use is not affected.
So that all being said, how do you use these packages? Just like any other library, you just add a NuGet reference to it. Since Microsoft.Extensions.Configuration is the base library which does not come with any facility to load files, you also need Microsoft.Extensions.Configuration.Json if you want to load JSON files.
But then it’s really straight forward:
var configuration = new ConfigurationBuilder()
.AddJsonFile("config.json")
.Build();
// retrieve configuration values
Console.WriteLine(configuration["foo"]); // bar
Console.WriteLine(configuration["baz:bar"]); // qux
For this example, the config.json looked like this:
{
"foo": "bar",
"baz": {
"bar": "qux"
}
}
So you can just load the configuration like this. Be sure to still check the documentation though. It may be about the configuration used inside of ASP.NET Core but the underlying concepts still apply (e.g. how configuration paths look like, or how binding works).
Finally, note that this is really just meant for configuration. Loading data from JSON is just one of many configuration sources you can with Microsoft.Extensions.Configuration. But regardless of what provider you will use, you will end up with the same configuration format that has the concepts of sections and key paths.
If you came to the package while looking how to parse JSON, then it’s likely that you are looking at the wrong tool. If you want to parse JSON to retrieve a proper data structure, like you would use when using JSON as a way to serialize data, then you should look at something different. The most common solution for parsing JSON (serializing too) is using Json.NET which is a very powerful and flexible tool to deal with any kind of JSON data.
My team is working on a new project that is built on the ASP.NET Core Web Application (.NET Framework) template. For legacy reasons we have another project that was build upon System.Web and directly accesses HttpContext via HttpContext.Current. Since our new project uses Microsoft.AspNetCore.Http.HttpContext we would like to know if its possible to convert the HttpContext to the older System.Web.HttpContext?
'Legacy' ASP.NET and ASP.NET Core don't play well together. In fact, I'd be surprised if they do at all. Their nature and characteristics are very different. Mocking the HttpContext in the legacy ASP.NET is pretty difficult. And even if you could, it's gonna be a hell of a job to set it correctly in the HttpContext.Current without being bitten by multi-threading issues.
My suggestion is to migrate the legacy application or expose the legacy functionality via a web API and use that to communicate between the two applications.
Well, I have a project, and by the moment I am using .NET 4.0, because I would like that this application is compatible with windows XP, because EF 5.0 is only for windows 7 and upper.
However, I would like to implement some parts of the application with the features of .NET 4.5, such as EF 5.0.
So for my database access I have a reposotry class that now use EF 4.0, this is a independent dll, so I can create other repository dll that use EF 5, and in my project import both dlls, then I can instantiate the correct repository according to the version of EF 5.0 that I can use. This is a paramater in the config file. is this the best way?
I ask this because I don't know where I must declare my interface. because my repository classes need to implement this interface, but then this tie my dlls to my application, but I need to use this repositories in two different applications, so I want to implement once, and use in many applications. I want independent dlls, because now are two applications, but in the future, can be more.
The reason to want to use an interface in the application that uses the repositories is because I would like to instantiate at runtime the correct repository, according to the config file settings. So in the fututre I can implement new repositories and there is no needed to change the code.
EDIT1: I read about multi targeting, but if in my project I use features for example of .NET 4.0 and I want to complie for 3.5, I get an error because this feature does not exist in 3.5. That's correct. Then the only way is to mantain two different projects? It would be a double work.
Thanks.
Daimroc.
So for my database access I have a reposotry class that now use EF
4.0, this is a independent dll, so I can create other repository dll that use EF 5, and in my project import both dlls, then I can
instantiate the correct repository according to the version of EF 5.0
that I can use. This is a paramater in the config file. is this the
best way?
You can go this route and I don't really see an issue with it unless you think that this could cause maintenance/development headaches in the future. There are a couple of other things that you can look into doing. I think both are completely valid and probably just personal opinion/preference.
Modules You can go a modular route where your repository DLLs are potentially loaded dynamically. Look into Microsoft's Unity library. This should allow you to create an IModule in each of your repository DLLs that will set up your application as needed. Then just create a UnityBootstrapper class to tell it how to find your modules (manually add them, look in a directory, etc.). This should allow you to hot swap your repository DLLs and not have to worry about setting a config file if you don't want to.
Preprocessor Directives With preprocessor directives you get to define how your code will compile. Depending on how you have your classes structured this may be something fairly simple to set up or a complete nightmare that makes you want to abstract and refactor your classes. This question: Detect target framework version at compile time has an answer for handling different compile results depending on the target framework. Personally though, I like the modular route.
I ask this because I don't know where I must declare my interface.
because my repository classes need to implement this interface, but
then this tie my dlls to my application, but I need to use this
repositories in two different applications, so I want to implement
once, and use in many applications. I want independent dlls, because
now are two applications, but in the future, can be more.
The reason to want to use an interface in the application that uses
the repositories is because I would like to instantiate at runtime the
correct repository, according to the config file settings. So in the
fututre I can implement new repositories and there is no needed to
change the code.
Sounds like you need to create another library that is used to communicate between your UI and your Repository libraries. This can be a little tricky and overwhelming to set up just right. Basically you want your gateway DLL to house the interfaces and business objects. Your Application would reference this DLL and this DLL would reference your repositories.
Depending on your needs you may actually need to set up another intermediary DLL that would actually just house your interfaces and most basic utility classes. This would allow you to have your EF objects implement the same interface that your application is using without the need for your gateway DLL having to map your business objects and EF objects back and forth.
EDIT1: I read about multi targeting, but if in my project I use
features for example of .NET 4.0 and I want to complie for 3.5, I get
an error because this feature does not exist in 3.5. That's correct.
Then the only way is to mantain two different projects? It would be a
double work.
I believe you can get around this by using the Preprocessor Directives I mentioned above. Below is just an example of making a method handle work differently depending on if the framework is .NET 2.0; it's just an example and not tested. The DefineConstants will need to be set up, but this should allow you to handle 1 project for multiple framework targets while also being able to use newer .NET features as they are released.
public Person FindPersonByName(List<Person> people, string name)
{
#if DOTNET_20
foreach(Person person in people)
{
if (person.Name == name)
return person;
}
return null;
#else
return people.FirstOrDefault(p => p.Name == name);
#endif
}
I hope this was helpful and the best of luck in finding the right solution.