ASP.NET MVC web solution built from optional modules - c#

I recently came across an awesome NuGet package, called Hangfire, which enables using background processes in an ASP.NET MVC project. What is interesting about the package though, is that it automatically sets up a nice dashboard subpage (accessible through http://your.url/hangfire) and creates new tables in your database.
I wonder, is it possible to create a whole web solution from optional packages, like Hangfire? Like I would create just a simple home page and all other subpages would be optionally installed via a config file, or in the somewhere in the App_Start? I believe it should be very easy with the new .NET Core 5 and the Startup.cs class (since also SignalR has a Startup.cs class and is then available via http://your.url/signalr/hubs). However, I was unable to find any proper tutorial. Could somebody point me in the right direction?

Related

ASP.NET 5 use different service containers per route, application part or feature

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).

View reuse for ASP.net MVC

So I have inheritied a program (APPLE) whose code baseline originated on another program (ORANGE). In order to make it easier for multiple teams to update this code we are moving the 'common' stuff out into a Shared Project (TREE). So far, we have made this work great with pulling out the Models and Controllers to a Shared library (obviously a few Models/Controllers remain in ORANGE as they are specific to that application).
However, I'm hitting a wall on how to extract the Views. The idea would be that the Shared Library (TREE) contains the common views (like file import, and landing page) while leaving the program specific code behind in the 'main' ASP.net application (APPLE/ORANGE).
I found this article which looked really good. Except 1) I don't have Microsoft.AspNetCore Nuget (My Microsoft.AspNet.[package] don't appear to have ViewComponent), 2) When creating a new Web MVC project, it doesn't have a wwwroot, Program.cs, or the .json files. I also found another article talking about using VirtualFiles, but it doesn't really indicate where the EmbeddedResource class would reside, and (I could be mis-understanding) but it seems to look for all the Views in the vitural location.
So what is the best way to split common views out into the Shared Project I've created and utilize them in our program application?
This is an ASP.net application using MVC. It is not a Razor application.
I have access to Microsoft.AspNet.(various packages) and DevExpress.(various packages), but must go through a process to obtain other packages (so I can't easily download a package and test out suggestions).
You could simply make your own NuGet package which, when installed into any project, adds the shared views, controllers and any other files you want.
We've done that successfully in my organisation to effectively provide a base template for any new MVC applications. It adds certain specific views and templates, overrides the layout view, sets up a controller and adds some global filters. It also adds some CSS and JavaScript files, so we've got ready-made corporate branding on the app, consistent shared functionality provided, and so on. It also depends on some other of our nuget packages which are then also loaded into the project, which provide shared functionality such as error handling, logging services, pre-made data connections, an API client and other bits and pieces which we need in almost every app we write.
The package itself is built from a separate project which is also source-controlled like any other codebase, and we maintain numbered versions.
This works very well as a way of sharing code and components between projects. It also means that any updates can be pushed out to all applications with minimal fuss.
Your nuget package could be installed manually into the project, or served from your own feed - you can create private NuGet feeds in Azure DevOps and other places, or even just a folder on a shared drive can be used as a package source, if you have to.
(P.S. That article you've linked to is about .NET Core, whereas you're using .NET Framework. The project structures are significantly different, hence your confusion.)

Modular functionality with ASP.NET vNext Core CLR

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.

How to version an api endpoint in .net

We're setting up a bunch of json web services in ASP.NET which is served as .ashx (custom handlers) files. An example would be:
/mobile/json.ashx
We'd like to implement some form of versioning as well as to not break apps which has not upgraded. So we led down this path:
/mobile/json.ashx?v=1.0
Now, of course we have have a switch statement in our custom handlers to manage the differences between api version but this doesn't sound like a very maintainable solution to me.
What are the best practises for this kind of set up and what options are available for version control?
Thanks
Placing the version in the query parameters (that is, after the ?) suggests to the user that each endpoint is individually versioned. I would avoid this.
If your web service is structured such that there are larger logical units that are being individually versioned, then I would go with something like this:
/api1/1.0/some/endpoint
/api1/1.1/some/endpoint
/api2/1.0/some/other/endpoint
/api2/2.0/some/other/endpoint
...
The version portion of the path comes directly after the thing which is being versioned. This suggests to the user that everything underneath /api1/1.1/ is version 1.1 of API 1 and everything underneath /api2/2.0/ is version 2.0 of API 2.
If someone entirely omits the version portion of the path, the latest version should be implied. So /api2/some/other/endpoint would map to, say, /api2/2.0/some/other/endpoint.
If you're using ASP.NET MVC, all of this can be accomplished very easy using route configuration in the RegisterRoutes method in Global.asax.cs. For example:
routes.MapRoute("api1/1.1", "api1/1.1/some/endpoint",
new { controller = "Api1_1_1", action = "SomeEndpoint" });
where you have a controller class Api1_1_1 with method SomeEndpoint.

How to add modules to MVC4 at runtime without AppDomain restart

I am working on a multi-tenant MVC4 web portal that is meant to host dynamically generated MVC4 applications.
Use case: The client uses the web portal to upload a xml specification. The specification gets passed to a web service that generates an mvc4 application, compiles it and returns a zip file to the portal containing the views, css, javascript and a dll(compiled c# code). Then, the portal unzips the received zip file and places it's contents in a folder (Modules) inside the portal itself. Then the client can browse the newly 'deployed' application. Many versions of the same application can be deployed and I am planning to use different Namespaces for each deployment. Note: The generated modules have some dependencies that will be injected by the web portal using a DI injector (was thinking of using ninject)
I have done a lot of research on how to build a modular MVC application. I've looked at MVC Areas, done some research on MEF, DI frameworks, looked at nopCommerce and orchard code. One thing that I cannot seem to find an answer to is how to add the Modules at runtime without requiring an AppDomain restart? Also, is there an easy way to register routes for each of these modules at runtime?
I am trying to avoid app restarts because there may be other people using the portal/deployed modules while others are uploading new specifications.
Did you have a look on this (just very slightly outdated) Tutorial? It won't solve the problem of re-scanning the Modules, but the introduced PluginAreaBootstrapper class seems to be a good start. Maybe you would be able to run the PluginAreaBootstrapper's Init() method upon a specific Event in your System (let's call it OnNewModuleDeployed).

Categories