View reuse for ASP.net MVC - c#

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

Related

Sharing Data Access Layer DLLs among multiple Projects

We have multiple projects which share same database.We have created DLLs for this data access layer.Now the problem is, in order to share it as DLLs we have kept 3 class libraries(3 layers of database access layer) inside a solution.There may be a scenario in future where data access layer needs some modifications(migrations).So how do keep the database access layer in such a way that it supports future modifications which is not very flexible as of now.
We cannot run migrations in a class library project, One workaround for it could be having a web project and adding 3 class libraries separately in it and then using it for modifications. how good is this approach?
We have kept the database access layer code in a different branch in our repository.What we need is that whenever some changes are made to the branch it should trigger some process which extracts the modified DLLs and add it as a reference in our projects.
The only time you should share a dll across projects is if the projects are really tiny and never change. In the real world, that is never the case and can quickly become unmanagable.
There are many many ways you could do this. Here are 2 of the better ways you could go about doing this:
put the shared code into a nuget package and host it locally (as easy as setting up a shared folder if you don't have azure)
create a micro service for the shared data and have apis that you call to get the info from each app. Can easily make a nuget package that is a "client" of the microservice and import that into each app instead of copy pasting the connection code in each app.

Is this an appropriate way to start sharing code across mutliple mvc apps?

We are developing multiple applications for the same company.
The applications are distinct (so not suitable for a multi-tennant app) but there will be lots of shared models, a couple of shared controllers and ideally some shared views.
It is the first time I have had to do this, and wonder if I am approaching it correctly. Here is my plan:
Create a DB for the shared stuff, and another (per application) for application specific stuff
Each application will have 2 connections in web config
Create a DLL from the shared models and controllers. Put this in the /bin directory and reference it in the project. I want this to approximate the way a nuget package might work, and reference the
For each app create a SharedApplicationDBContext and a LocalApplicationDBContext, each accessing the respective DB.
Questions
Are the above steps the right ones to be taking?
Is there any way to include cshtml Views in a DLL?
Is it ok to include the Users controller / models in the DLL?
Are there any gotchas I should be aware of when sharing code like this over mutliple apps?
I know SO likes specific questions, and this is a bit vague, but I'm a bit out of my depth here and looking for some general guidance as to the right approach to take.
You've got the general idea, but it needs some tweaking:
Don't fool around with DLLs. If the projects exist in the same solution, then you might as well keep your class library there as well. In which case, you can just do a straight project reference. If you're dealing with multiple solutions then you package your class library as a nuget package and actually install it in each project. Creating a nuget package is easy enough, and you can either install from a local/network path or you can set up your own private nuget repo. This makes it stupidly easy to share resources, and you get the ability to publish updates and see at a glance which projects are running which versions of your class library.
Each app should only have the context that relates to its individual database. The shared database can also use a shared context, which would be contained in your class library. You should also house all your migrations related to this shared context in the same class library.
You can include views in a class library, but not as cshtml. They have to be compiled into the class library. You'll need RazorGenerator to accomplish this.
It's 100% okay to include the models related to users in your shared library. However, the controller is trickier. Unless you set up an SSO server that will alone be responsible for handling all authentication (a non-trivial task to say the least), each application will need it's own controller for authentication tasks. If all of the sites will reside on the same domain or subdomains thereof, you can easily share the auth cookie between them. However, if they will reside on entirely different domains, you can still share the same "users", by virtue of using the same database for each, but each site will require a separate login process (logging in at one does not log you in at another, even though the same credentials would work for both). The only way around that is, again, SSO.
For what concerns the views, you can include them in a DLL, please read here
For the models it's ok to have them in a different project.
For the controllers you can do it but you must let MVC know where the controllers will be located and you can do it by writing a custom ControllerFactory, please read more here.

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

Where to put shared parts when using the onion architecture?

I am trying to apply the onion architecture by J. Palermo, but I have a few things I am struggling with.
I have a few parts and I don't know exactly where to put these.
I have a plugin engine which reads a directory and determine what things to load en to do
Have some resource files with translations which are used in several projects. Where should I put these files?
I have some attributes which are used throughout the system. Where to put these?
I also have two 'base' controllers, some default results and views. Where should I put these?
All those items are used in several projects so I want to put the items at a central point.
My current solution structure looke like this:
Project.Core (contains the domain objects and interfaces of the repositories)
Project.Infrastructure (is the implementation of the core)
I am using MVC2.
I don't think it's something that the Onion architecture would solve by itself.
What I would do, is to put all these items in one or several projects, within another solution and build Nuget packages allowing me to deploy them everywhere I would need them.
This way I would have deployed items like your base controllers in your MVC project and plugin/translation stuff in your Infrastructure project.
That way, whenever you'll need to have those elements available in your newly created projects, you'll just have to deploy the package again.
Those items will become independent, stored in a central point (a new sln) and will have it's own release cycle!

What is an easily maintainable way to share a common .net class library over many corporate asp.net mvc 3 web applications?

I've been struggling to do this in a way that fulfills all of my requirements.
Here is what we have in our library:
Base classes for controllers and services
Business objects (stores, departments, etc)
Common Partial Views (Login, Error, etc)
Base class for HttpApplication
General common code (read an INI file, create a db conn, etc)
The one requirement that has been giving me trouble is as follows:
Lives in one place on a server. (i.e. copy local = false)
This breaks because:
The DLL containing the HttpApplication class must be in the same directory as the web apps dll to launch. I haven't found a way around that. I'm ok with duplicating this code in every app, but would rather not.
The shared views don't like to work if I use Assembly.LoadFrom() to load the dll from the shared location. (I've been using this method to precompile my views)
Any namespace shortcuts in web.config break at runtime with compilation errors because the web.config is parsed before the assembly is loaded.
My question to you folks is how do you handle your common code in a similar environment?
The GAC seems to be more trouble than its worth, and we want all of our apps to be using the same code, and not have multiple apps on multiple versions and have to maintain all of that. Are there design patters/best practices that can guide us in this regard?
Also, as a bonus, if you can solve any of the problems above, that would be great, too.
Thanks!
Edit: I guess a question that follows is whether or not we should even have a directory with the common dll(s) on the server, or if they should only be deployed as projects are deployed/updated?
Firstly, you will want to separate out what you're trying to achieve. Don't create 1 library that does everything or you will have a Big Ball of Mud. Don't be afraid to create several maintainable libraries to achieve what you're after. Is there a specific reason it needs to be stored in one location?
For example, several of the items you mention are MVC or web specific. If you have items that can be reused by MVC, create a class library that contains MVC base classes you inherit and reference them in your project. Use the single responsibility principle as much as possible.
Regarding the other items you mentioned, like database connectivity, if it's reusable, abstract it out in a data access class library and reference it. Other simple operations like reading an ini file or creating a file, create another library and abstract it to easy to use methods.
I prefer to copy the library dlls locally. You never know when you will need to make changes to the library, but you don't want all of your projects to stop compiling. When you're ready to implement a new version of the library, copy the dll in and recompile.
Not sure why all the hate towards the gac. It was designed to handle this specific problem. Install your common dlls to the gac and all apps can see them. Need to deploy a new one, just re-install it in one place.

Categories