Where to put shared parts when using the onion architecture? - c#

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!

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.

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.

C# Project folder naming conventions

I have a project called Data which is a data layer. In this project, all files are just lying in the top folder. I have enumerations, POCOs, repositories, partial classes and so on.
If i want to move those files into subfolders, what would be the preffered folder name for each folder? Is there any convention?
The "Repositories" folder is pretty obvious, but where should i keep POCOs and enumerations?
Thanks
I (currently - changes based on project) tend to use this approach when naming assemblies/projects/namespaces in a SAAS/Web style project)
CompanyName.
ProductName.
Data.
Business. (references data)
Model. (POCO and interfaces - referenced by all)
Services. (WCF service layer)
ServiceClient. (referenced by web clients)
Web. (web client business layer)
ViewModel. (view specific model)
{client facing product segment} [Commerce, CMS, CRM, Reporting, etc.]
To explain the Services/Service Client...I use an IoC (currently StructureMap) that allows my WebClient to either speak directly to the Business layer or to be redirected to speak through the ServiceClient through Services to the Business layer. This gives me the flexibility to either deploy my app layer to my web applications or to distribute pieces of my business layer (app layer) to different servers by way of WCF/SOA principles.
A good practice is to name the folder after the name of the project.
Design Guidelines for Developing Class Libraries has a set of Guidelines for Names
The last item should be of paticular interest for you:
Names of Assemblies and DLLs
Names of Namespaces
Types and Namespaces
I tend to use project folders as a way of separating out sub namespaces. So in your case, perhaps a folder called Repositories, which has class in the Data.Repositories namespace. Note, for partial classes, each file needs to be in the same namespace.
Best prectice is to divide entities in folders by object model meaning, not by type.
If it is not clear how to group the classes by usage or object model meaning, just leave them all in one folder. Using subfolders don't give values if they don't organise the classes in a meaningful way.
Dividing folders by type, e.g. enumerations, POCOs, repositories, partial classes etc is not likely to be useful.
You may wish to use a subfolder for generated code that should not be edited.
Also remember you can have folders within the solution explorer that are not part of the file system. Given how costly (in time) it is in some source code control systems to move files between directories, I would consider starting of just using msdev folders until you are clear on the structure you want.
There is no need to put each enumeration in its own file, if an enumeration is only used by one class, it is valid to put it in the same file as the class. E.g the PersonSex enumeration can be put in the person.cs file. Likewise if you have a lot of small and closely related classes, consider putting them in the same file.

Grouping Views, Controllers, Models in MVC

maybe i am wrong but i seriously i don't like the current structure of MVC application, and i think on big projects it will cause trouble to maintain.
so is there a way to group related Controllers,Views, Models together, like if i have gallery Module i want all it's Controllers, Views, Models to be grouped under Gallery Folder.
Areas sound like what you are looking for. This will let you group controllers/views/etc. Unless I misunderstood the question?
Phil Haack discussed this here, it's the same issue I've faced and have yet to overcome correctly.
From the sound of it you're moving against the basic principals of MVC, that being the separation of Model, View and Controller rather than your desire to split at 90 degrees to that by using modules.
I'm not entirely sure what benefit you would get from splitting it in to modules any way since I would expect you to have one GalleryController. Where you are likely to have the most 'entities' needing grouping is with the views, possibly one or more for each GalleryController action, but they are in their own folder which gives the sort of functionality you are looking for anyway.
Finally there are the models. Obviously I don't know your project so I don't know how it is laid out, but the Models do not usually exist for the use of one Controller (or module in your case). For example - I have Models for Users, Companies, Vehicles, etc, etc. These models are a shared representation of my data structure and have nothing to do with modules as a user may see it looking at a web page. I can't split them in to modules because the whole point is that they are shared by the entire application.
So...in reality it is the Views which can get a bit messy, but they are already split in to folders based on their Controller. Having said that you can move them around a bit if that suits your needs better. For the rest of it there is no need, either because you shouldn't if you want to use 'proper' MVC (i.e. modular Models) or there's no need (i.e. only one Controller). And if your controller gets too big just create a separate module for any functionality in that you want to split out. I reckon that's as modular as you should ever need to get.
I found a relatively simple solution that uses IIS configuration to simulate areas. No extensions to the existing MVC framework are needed.
Create a new MVC project under your solution for each area you want in your site (ex. Root, Blog, Forum, App1, App2). If you need any common supporting code or a common model, put it in a seperate dll project that the MVC projects depend on.
In IIS, configure the site root to point at the root project directory. Create web applications under the site root that point to each of the sub-area project directories.
When configuring the route maps for each sub area, don't include the name of the application in the route. IIS seems to take care of this for you. (ex. "ShowPost/{postname}", not "/Blog/ShowPost/{postname}")
The benefit is that you can change the name of the web applications independent of the routing system, and each application believes it is running with the whole server to itself.

Categories