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).
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).
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.)
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?
I am trying to use in jBPM users from existing ASP .NET MVC Web Site.
As I understand from docs and this forum topics (first, second) best solution would be implementing of UserGroupInfoProducer that will call external service. But due lacking of experience with java I faced with several problems.
First approach: Create project with required implementation, deploy it and config jBMP to use it.
Problem was in implement interfaces that declared in another project, I've tried to add maven dependencies but after failing with some classes I've just added reference to required jar.
Deploy it on jboss like war failed, deploying like jar succeeded but server did not find UserGroupInfoProducer and other implemented interfaces.
Another problem in changing config of jbmp-console. Only way that I've found for that is modify archive directly, but I don't this it's right solution.
Second approach: Create own package of jBPM with required classes.
Problem here that I don't know what repository use for this and how to build version for my server.
As I understand from this link I need to use jbmp-console-ng, only maven task for creating war package that I found was in jbpm-console-ng-showcase I've tried to run it (release 6.2.0 Final) on:
On Windows: failed to execute because of maven error about long path, after migrating project to gradle and excluding dependencies on jmxtools-1.2.1.jar and jmxri-1.2.1.jar it created war but jboss failed to start service.
On Mac and Ubuntu using virtual box: it required to downgrade java to 1.6 and built war after this, but it failed to deploy due duplication of some classes.
As I understand you need to build diferently for each version of server but I don't know how to do this.
Third approach: Create come simulation of supported authorization ways. As I understand jBMP support LDAP, JAAS, database and file. Database and files will require duplicating users so I researched about simulating LDAP or JAAS (preferably using C#) but did not find any acceptable way.
I will be very grateful for any advise which of this approach may work or some other suggestions. Especially about building war of jbmp-console.
version used:
jBPM(6.2.0 Final), jBoss(Wildfly 8.1.0 Final), Java(1.8.0.73), Ant(1.9.6), Gradle(2.11), Intellij IDEA (15.0.3).
After a few weeks of try and error approach I have finally managed to provide fully custom authorization module for JBPM suite ( kid-wb, server and dashbuilder ) in our application. It wasn't easy and required some magic - overwriting two classes won't do it :)
My requirements was quite complex and final solution consist of kie-wb, server, dashbuiler and external authentication which provide by REST Web Service response users with roles based on token passed in session. Another thing that you have to keep in mind is that kie-wb and server are communicating through BASIC authentication - if you want to use server also you have to provide two possible methods of authentication. I won't be able to publish here any code, because it is not an open source project, but I will try to help the best I can.
If you are using WildFly as you are saying above, what you should look at is Undertow Servlet Extension
Overwriting handleDeployment method allow you to write your own IdentityManager( if you need one ) and register your custom AuthenticationMechanism.
To implement your own AuthenticationMechanism you should look at this project Custom Spnego Auth for WildFly
My solution was based on mentioned above project - you don't have to implement every class - in my case writing my own class implementing AuthenticationMechanism was sufficient to get custom authentication working in kie-wb ( not for server though).
So if you already have overwritten Servlet Extension ( and registered by putting file io.undertow.servlet.ServletExtension containing your custom servlet extension class name inside /WEB-INF/classes/META-INF/services/ path of .war file ) and implemented custom AuthenticationMechanism next thing you should do is write class implementing org.jboss.security.auth.spi.LoginModule interface. If you don't want to implement this interface all by yourself you can just extend one of already implemented classes from WildFly - for example UsernamePasswordLoginModule or other.
To let WildFly know that we are using non-standard Login module we have to modify standalone-full.xml as follows:
<subsystem xmlns="urn:jboss:domain:security:1.2">
<security-domains>
<security-domain name="other" cache-type="default">
<authentication>
<login-module code="com.package.CustomAuth" flag="required">
</login-module>
</authentication>
</security-domain>
</security-domains>
</subsystem>
and then...we are almost done :) One thing left to do is to modify deployment descriptor inside .war file. We have to change web.xml inside /WEB-INF dir as follows:
<login-config>
<auth-method>BASIC?silent=true,CUSTOM</auth-method>
<form-login-config>
<form-login-page>/login.jsp</form-login-page>
<form-error-page>/login_failed.jsp</form-error-page>
</form-login-config>
</login-config>
CUSTOM is name of your authentication mechanism that was registered inside class implementing Servlet Extension class.
Above instruction does not cover kie-wb <-> kie server communication. This matter was more complex and required a few workarounds. As I said before I won't be able to provide full solution with more detailed examples, but feel free to ask me anything refering this case.
I'm fairly decent with MVC3 and enjoy creating my sites with it, however, I am yet to think up and implement a decent method of a "plugin" system.
Basically, I aim to have a generic "blog-type" CMS which I can distribute across my sites, but with the option to have certain things as plugins.
For example:
Generic build:
User area
Basic blog/news editing
Plugins: (May be needed for one or two sites, but not all)
Chatroom plugin
Stats
and so on...
Currently I would just make it all and disable things through a config file, however it would be nice if i could just drop a folder into my FTP and have an MVC page which automatically picks it up!
I assume I would have to start with scanning the directory "/plugins" and picking up a "plugin.config" (Or similar) file which would contain the basic details.
But how would I get my main system to pick these things up and actually use them?!
You may be able to do this using MVC Areas, here are some links about them:
ASP.NET MVC 2 Areas
ASP.NET MVC Areas: Are they important to a large application?
https://stackoverflow.com/questions/462458/asp-net-mvc-areas-are-they-important-to-a-large-application
Try assembly scanning with StructureMap dependency injection.
Read this great tutorial: ASP.NET MVC2 Plugin Architecture Tutorial
It help me create a plugin architecture with MVC3.
Areas solve the problem for you providing you have everything in the original project/assembly. You could write your plugin system to allow the plugins to register their own areas, or alternatively you could register some new view search paths in a custom Razor view engine.
I chose the latter for a recent OS project I wrote called Spruce, which uses a whole plugin architecture you might find useful as a reference.
You can scan all the assemblies in the bin directory on startup to check for plugins, via reflection. You usually check for types that implement an interface or inherit from a class, and use these along side an IoC container such as TinyIoc, NInject, StructureMap or Unity. I'd recommend TinyIoC which is used by NancyFX.