ASP.NET MVC multi-site design - asp.net

I'm looking to create a new MVC site, and one of the key problems I'm trying to solve is sharing code between a public area (web-facing) and an internal area.
Basically we have two applications, one that is the public web site that users access, and another that will be used internally at our company to view some of the same information that is also visible on the public site.
I would want to keep them as two separate sites (projects) because we have different teams of people working on each, and because we want to use different authentication formats (Forms for the public, Windows for the internal).
However, we also want to be able to share some of the code (views, controllers) between the two sites. How could we set up these two MVC sites such that one MVC site could reference a view and / or controller in another project?
For instance, we will have a view that will enable internal users to see transaction history of our public site users. If we have created that controller/view in the internal site and later we wanted to add the in the public site, how could we re-use this same view on the public site?

Technically, as others have already said, you can put everything you want shared in a class library project, and then reference this project from your other projects. Views are a bit different as, in order to share them between projects, you will have to compile them. You'll need Razor Generator for that.
Practically, though, it's going to be rare that a view should be shared between projects (aside from something like a layout), and virtually non-existent that you should share a controller. If the overlap is that great, it's an argument that the two projects should not in fact be two projects, but one. Controllers and views are so customized to the application that sharing them just doesn't make sense most of the time. It is however a very good idea to share your models and other classes.

2 approaches I can think of:
First option is to use MVC Area. It gives you different controller/view for each area, while sharing the same Model. You can also encapsulate common methods in a Helper class.
Second option, create 3 projects. One is a .NET library containing the common logic, Models, validations, sending emails etc. Then create 2 more MVC projects, one for each site, and reference the project.

Look at using Areas within your site (this would allow you to keep the projects independent, but together as one final solution). Also, look at compiling your views in another library so you can share them between projects.
Some references:
Compiling views in MVC
See also RazorGenerator
MVC pluggable modules

Related

Breaking a monolith into microservices using templates for similar apps

I have a huge monolith application, a ASP.NET MVC Framework service offering ~50 different "groups" of unrelated data, separated into 50 different controllers/business logics. I was tasked into breaking this monolith into 50 microservices (each one hosted in Docker containers).
What I'm planning to do is to create a "template application" using ASP.NET Core to serve as a reference project and, for each of those 50 applications, I will fork this "template" project, add the corresponding controller with the necessary business logic and may need or not to customize this template to add some specific features.
For example, one application may need to respond to requests using a CSV format instead of the JSON, which is the standard for ~45 apps. So, I would modify the "template project" to include this "CSV response" feature and it would be used by the other ~4 projects that would use it.
What I can see currently:
PROS
Developing a ASP.NET Core application is easy, but it requires some configurations and customizations (CORS, Cache, routes, etc.) that would be already defined into "my company template" project.
CONS
Forking and merging the template project can be troublesome. If we find a security issue in the template, it would be necessary to manually update all of the 50 projects and fix some potential merge conflicts.
Is there another option available in ASP.NET Core to make this "template" project easier for updates and maintenance? Or a design pattern for this?
Just use a class library. Common functionality and even base controllers and such can all go there and be referenced by the actual API projects. Your common config can be added to the class library as IServiceCollection extensions:
public static class IServiceCollectionExtensions
{
public static IServiceCollection AddMyCors(this IServiceCollection services)
{
services.AddCors(...);
return services;
}
...
}
Then, any change to this library automatically propagates to your APIs because of the direct reference.
However, bear in mind, that pretty much the entire point of microservices is loose-coupling. You should really only share this kind of functionality for things that are relatively static and won't change. Making changes that requires every single one of 50 services to be updated, pretty much defeats the entire point.
If there's too much common, shared functionality, you have to ask yourself if you've truly decomposed the services into subdomains. A very common mistake in this way is not realizing that the actual data should be segregated as well. Ideally, each microservice should have its own data store (database, for example). If you are trying to make the microservices share the same data store, then you will inevitably end up with significant cross-over and it will be difficult if not impossible to segregate their domains. That means you loose niceties like foreign keys sometimes and you may need to even incur some data duplication. That's where CQRS, event sourcing, and other related patterns start to come into play.

Why is Razor Pages the recommended approach to create a Web UI in Asp.net Core?

Learning new things needs an investment of time, space and energy. I am currently learning Asp.Net Core MVC 2.0. This ASP.NET Core tutorials overview states:
Razor Pages is the recommended approach to create a Web UI with ASP.NET Core
This information confused me in deciding whether I have to stop learning Asp.net Core MVC and start learning Asp.net Core Razor Pages.
Why is Razor Pages the recommended approach to create a Web UI in Asp.net Core?
Any directions are welcome.
From this article in Microsoft docs:
MVC: Using controllers and views, it was common for applications to have very
large controllers that worked with many different dependencies and view models and returned many
different views. This resulted in a lot of complexity and often resulted in controllers that didn’t follow
the Single Responsibility Principle or Open/Closed Principles effectively.
Razor Pages addresses this
issue by encapsulating the server-side logic for a given logical “page” in a web application. A Razor Page that has no server-side logic can simply consist of a Razor file (eg. “Index.cshtml”). However, most non-trivial Razor Pages will have an associated page model
class, which by convention is named the same as the Razor file with a “.cs” extension (for example, “Index.cshtml.cs”). This page model class combines the responsibilities of a Controller and a ViewModel. Instead of handling requests with controller action methods, page model handlers like “OnGet()” are
executed, rendering their associated page by default.
Razor pages simplify the process of building
individual pages in an ASP.NET Core app, while still providing all the architectural features of ASP.NET Core MVC. They are a good default choice for new page-based functionality.
When to use MVC:
If you’re building web APIs, the MVC pattern makes more sense than trying to use Razor Pages.
If your project will only expose web API endpoints, you should ideally start from the Web API project
template, but otherwise it’s easy to add controllers and associated API endpoints to any ASP.NET Core
app. You should also use the view-based MVC approach if you’re migrating an existing application
from ASP.NET MVC 5 or earlier to ASP.NET Core MVC and you want to do so with the least amount of
effort. Once you’ve made the initial migration, you can evaluate whether it makes sense to adopt
Razor Pages for new features or even as a wholesale migration.
Note:
Whether you choose to build your web app using Razor Pages or MVC views, your app will have
similar performance and will include support for dependency injection, filters, model binding, validation, etc.
Update: Some more reasons i read on this github issue commented by scott sauber:
We're using Razor Pages for a [complex] Health Insurance portal... We have 60+ pages and I can say that for Server-rendered HTML, I will never go back to MVC. It's also not just for simple things. The Health Insurance domain is inherently complex and combine this with the fact that it's a multi-tenant app (we sell the product to other insurance companies), which adds more complexity as the app is highly configurable as different insurance companies do things a bit differently.
Why use it?
Razor Pages is more secure by default. Razor Pages gives you AntiForgeryToken validation by default. Plus you opt-in to what properties you want to be model bound via [BindProperty] which limits your exposure to over-posting attacks.
Razor Pages has a better folder structure by default that scales better. In MVC, the default folder structure simply does not scale. Having separate folders for Views, Controllers, and often ViewModels when all three are ultimately tightly coupled to one another is a huge PITA to work with. You end up bouncing to all 3 folders and navigating a bunch anytime you need to add or change a feature. It's horrible. This is why I advocated for Feature Folders. With Razor Pages, your PageModel (Controller + ViewModel) are in the same folder as your View. You can just hit F7 to toggle between them which is also super convenient.
Leads to more maintainable code that scales better. With MVC it was super easy to bloat a Controller with 10+ Actions. Often, these Actions weren't even related to one another in any way (except maybe a Redirect between the two). This made navigating the Controller to find code very difficult. It got worse if there were private methods in the Controller too, further adding to the method bloat. With Razor Pages, it's nearly impossible to bloat up your Page Model with unrelated methods to your page. Everything you put in your PageModel is related to your Page.
Unit Testing is easier. With a Controller, you might have 8 Actions and some of your dependencies you inject in were only related to one or two Actions. So when unit testing a single Action either you need to mock those out unnecessarily or pass a null, both of which feels gross (this can be solved a bit with the Builder pattern). With Razor Pages, the dependencies you inject in are 100% related to GET and POST actions you're working with. It just feels natural.
Routing is easier. By default in Razor Pages, routing just matches your folder structure. This makes nesting folders way easier to accomplish. For instance, all of our HR Admin pages are under the /Administrator folder and all the Employee pages are under the /Employee folder. We can authorize an entire folder and say the person must be an Administrator to get to any subfolder of /Administrator, which was way easier to do that than with multiple Controllers that make up the Administrator features.
I think that's the big stuff.
Update 2:
This is about some complexity of MVC pattern, does not directly answer the question but can be useful: An Engineering Manager at Facebook, said (here) for their “sufficiently” large codebase and large organization, “MVC got really complicated really quickly,” concluding that MVC does not scale. The complexity of the system went exponential every time they attempted to add a new feature making the code “fragile and unpredictable.” This was becoming a serious problem for developers new to a certain codebase because they were afraid to touch the code lest they might break something. The result was MVC was falling apart for Facebook.
Razor Pages are optimized for page-based workflows and can be used in these scenarios with fewer moving parts than traditional MVC models. This is because you don't need to deal with Controllers, Actions, Routes, ViewModels, and Views (as you typically would). Instead your route is convention-based, and your PageModel serves as your Controller, Action(s), and ViewModel all in one. The page, of course, replaces the View. You also don't have to have as many folders as you would in MVC, further simplifying your project.
From ASP.NET Core - Simpler ASP.NET MVC Apps with Razor Pages, a Sept. 2017 MSDN article by Steve Smith:
[Razor Pages] provide
a simpler way to organize code within ASP.NET Core applications, keeping implementation logic and view models closer to the view implementation code.
They also offer a simpler way to get started developing ASP.NET Core apps,
That article has more information on why to use Razor Pages over MVC for page-based workflows. Obviously, for APIs, you will still want to use Controllers.
3rd party edit - disadvantages of classical MVC folder organization
ASP.NET Core - Feature Slices for ASP.NET Core MVC, an older MSDN article from Sept. 2016, describes why the classical MVC convention to organize views and controller might have disadvantages for larger projects. The article gives an example of four loosely related application concepts: Ninjas, Plants, Pirates and Zombies. The article outlines a way to structure them outside of the default folder convention by organizing files into folders by feature or area of responsibility.
Microsoft is coming back to the WebForms approach to simplify the project structure trusting in the "Convention over configuration" mantra, while hiding the configuration from developer to make things faster. But it has the disavantage that everything will be mixed again. It doesn't look like a smart move for organizing. But... Hey! Something new must catch the attention of the dev towards Microsoft.
If your page uses an MVC Web API for the REStful, it's really more easy to just use Razor pages. If not, I would recommend you to use Core MVC.
In huge projects, where the model and controller are together in the same file, maintenance will be a nightmare. It works well for clases that are just 2 properties long, but it violates the Open Close Principle of OOP. You should design and use an architecture that can grow with time (Extensible) and still be stable and logic(No reestructuring the project), just extend it using the same pattern.
As a Software Architect I use design patterns automatically. What I like a lot is the Facade design pattern. You hide everything related to Home behind a HomeController and you can do the same with Repositories.
Want to know a funny thing? A tour guide explained where the name
Facade comes from. In Amsterdam you have big houses across the waters.
From the outside they look luxureous. But from the behind they can be
messy. The facade of the house hides whats behind it. Design patterns
comes from the building world. Well whats behind in my applications
also looks good but it was nice to know from the tour guide about the
explanation.
What about support for Sharing and Grouping actions in Razor pages. If you look at MVC Controllers you can see that you can Group controller actions based on functionality. You could say the Home page is such a functionality. Then you have a HomeController with About() and Contact() in it, but with Razor Pages this would be different pages. May be you have a big HomeController with lets say 5 other Views in it. They can all be grouped in the same HomeController.
A Controller has two things a Razor Pages does not have:
Sharing: You can share Controller actions between different pages, sometimes controller actions are not bound only to one page but can be shared between several pages. Remember Controller actions can also only return Data (JSON/XML/etc). Sometimes what they return can be used by different pages too.
Grouping: You can group related Controller actions together in one Controller. Ok if you are a fan of small Controller files you won't do this. I do. I group my Controllers based on functionality. That makes navigation much easier.
What is the Razor pages way of handling this: Use of directories I think:
Grouping: If we have the HomeController, then we could make a subdirectory Home with all the Home pages in it.
Question: For a simple Home that would be enough. But lets say we have an XController that uses for all actions the same Repository. You could initialize that Repository in the Initializer function of the XController. But for pages in the X subdirectory you would have to do that for all X actions again. Is that DRY?
Sharing: You could make a "Share" subdirectory and under that, directories with functionality that should be shared between pages.
Question: If you look at my fix you can see I use directories to solve the Share and Grouping problem of Razor pages.
How would you do this?
or...are Razor pages just meant to be for simple websites, could this be the conclusion for this version of Razor pages.
Blazor server has a strange architecture. It looks like a chat application by use of SignalR. My experience with applications like that is that events can get lost. I don't want to lose events, better is they are stacked and guaranteed to be processed like mail.
Developers were on forums in 2013 asking "What does Microsoft mean, Silverlight is not the recommended ...???"
Only this time, it is that MVC is going to be pronounced dead and long live MVVM.
And you can likely expect MVC to be thrown to the scrap heap, slowly, but sped up in about 18 months from now, and any and all time you spent learning MVC will go to that same scrap heap.
Also, MVVM looks easy but it takes a year to get the hang of it and really do it right.

ASP.net MVC: Multiple domains, separate projects, separate deployments

I may be searching on the wrong keywords, but I'm having a hard time finding a suitable solution for the following case. We have an internal application that has five separate business areas within the application. In the past, this has all been set-up inside a web site project, and we've piece meal deployed changes to this environment. We've always had issues with one change bringing down the entire site.
In order to mitigate this while also bringing easier ways to unit test and potentially get into continuous integration use cases, I would love to have a structure where all the transactions for particular business areas (domains) stay within their own separate project. The architecture may look something like:
Main Project (Houses authentication, base master page, styles)
Ordering (Houses all things ordering)
Models/Views/Controllers
Pricing (Houses all things pricing)
Models/Views/Controllers
My question is how do I incorporate all this and give myself the ability to deploy each project separately at any time I'd like. So, for instance, I make updates to the Ordering domain, compile it, then upload the project without affecting the other domains.
Obvious other questions revolve around routing. How do I get the route correct? I'm assuming there are ways within the RouteConfig to set namespacing? What's the solution for this?
Is this what MEF does?
Have a look at Areas:
The MVC pattern separates the model (data) logic of an application
from its presentation logic and business logic. In ASP.NET MVC, this
logical separation is also implemented physically in the project
structure, where controllers and views are kept in folders that use
naming conventions to define relationships. This structure supports
the needs of most Web applications.
However, some applications can have a large number of controllers, and
each controller can be associated with several views. For these types
of applications, the default ASP.NET MVC project structure can become
unwieldy.
To accommodate large projects, ASP.NET MVC lets you partition Web
applications into smaller units that are referred to as areas. Areas
provide a way to separate a large MVC Web application into smaller
functional groupings. An area is effectively an MVC structure inside
an application. An application could contain several MVC structures
(areas).
(from MSDN, linked above)
Which would give you the logical separation, but not the functional.
To deploy Ordering without potentially taking down Pricing, the easiest thing to do would be to have separate web applications (which can be hosted within a single site if that's a requirement) for each. You can extract any shared logic to a class library project and reference that in both front ends.

Injecting a complete module in ASP.Net MVC

I am developing a multi-tenant application based on ASP.Net MVC. Depending on the user setup, the site needs to redirect to a separate module/area for that user. Each area has uses some common services, however the site's look and feel and navigation are completely different for each area/ module. Models are also overridden from a base library and we need separate teams to develop the modules (which includes controllers, views and models).
We are considering dependency injection tools such as Unity or Ninject for the same. Question is how do we inject complete module/area inside a main web site. Controllers and Models part is well understood. What is not clear is how to develop Views so that correct views are searched and used.
UPDATE
We need to develop this application with different teams. Each team will develop a module per sub-site/ area. There is a business layer which provides common services, framework and workflows. MVC is primarily a presentation layer. Each team develops a sub-site per customer using specific branding for that customer. As we add more customers, we need to add more sites. We could have used themes etc. However, the customers have different screens and different set of fields per screen. All these fields capture similar data however, the end users are in different roles to capture the data. E.g. The front office person captures varying no. of fields per customer and back end person completes the remainder. Similarly there could be more than one users facing customer's customers (visitors). There is a common component which is used for managing the visitors flow, front end desks in each office session etc. Question is how do we independently develop the MVC sub-sites and bring them under a common site using dependency injection. Specially the views. Is deployment script the only option?
From what I understand.
Your goal is to use Dependency Injection with something like Ninject so that you can inject different implementations based on the Controller in a particular area being used in your application?
If this is the case, you can setup NinjectModules that bind certain implementations of a particular service defined by your interface or abstract class through the Ninject Named attribute, which you can place on your Controller Constructors.
For example, you might have a general Search Controller that is open to the public in an area such as
http://example.com/users/home/search
Using Ninject Named Attribute you could inject an implementation of a ISearchService which is consumed by that controller, which may offer a limited amount of functionality for public users to search properties on,
however in another area of the site, such as admin or users who post their own properties on the site may get more access through the search functionality
http://example.com/tenants/home/search
This HomeController can have a different injected implementation of the ISearchService which is passed through its constructor.
Just ensure to load all your NinjectModules in Global.asax
This can be found under the Ninject Contextual Bindings documentation here
I'm going on very little information from what you've given me here, you may get better answers if you provide a little more context / code examples of the issue you are facing with your architectural design considerations.

extend whole website in asp.net

I'm looking for best practices and good ideas rather than a proper solution.
scenario: I work in a web agency and thus we are plenty of websites from several customers. They're built upon a cms we made, so websites are quite identical for the 90% of code. However, remaining 10% struggles me and my team as it involves not only the presentation layer but behavioral logics too (ex: a website1 requires simply user/pass registration while website2 needs more data, facebook connector, etc. But this is a very easy example).
Making ad hoc development for our customers is becoming painful as keep each version aligned is getting really hard for us
What I really dream to have is an extendible website that works by itself, but in which I can override a part. This behavior should sound like "look for the specific part, if it doesn't exists get the base one". The parts could be a method, a class, a page, a control, a static file.
example:
Suppose I want website2 to have an own login component, let's so imagine that we have a situation like:
/website_base
|_ login.aspx
/website1
/website2
|_ login.aspx
So, if I ask for www.website1.com I'll get /website_base/login.aspx, but if I ask for www.website2.com I'll get /website2/login.aspx
Any idea?
Thanks
PS: we work with asp.net 3.5 framework.
There are couple of ways to achieve this.
Approach 1:
1. Split the common functionality in modules and create a pluggable structure. (like DotNetNuke) Obviously this will be more time consuming initially but over the period of time it can make itself like a product.
Approach 2:
Firstly - I would create separate solution for each client for better maintainability. This will save me a lot of hassle while maintaining the source control and when one client comes back with issues and we have multiple releases for a single client.
Secondly - From my core solution, I will identify most commonly used artifacts for each layers and move them to a core assembly.
a. For example – In UI you can use themes to give different looks for each client. Have a default master page which comes with the core site structure. All client specific details like Logo, name, contact details etc… can be configured using some DB fields.
b. In Business Layer and Data Access Layer – core functionalities like Membership, Logging, CMS related Entities etc I would have as a dll
i. I will derive my client specific logic from these core classes.
Last but not the least – how you deploy your code and how your IIS VD structure looks like… I believe it will be totally dependent on how the solution is packaged.. I would create a deployment package for each client which will give them the ability to deploy it to any server wherever they want until you have specific issues about proprietary software hosting.
Look into ASP.NET MVC. It is much more extensible than Web Forms, can be integrated into your existing Web Forms application, and it is very easy to build reusable custom components like what you are describing.
Otherwise, I would suggest looking into WebParts and developing reusable custom server controls for the components that you need. This way you can encapsulate the complex functionality within a single UI control without having to write repetitive code. WebParts are also compatible with Personalization, which you can leverage to manage the variance between which sites use which controls.
I definitely recommend MVC as the way to go for building extensible .NET web applications, but learning a new technology always incurs a cost in the time it takes to understand the new paradigm. I hope this helps you.
I found a smart solution here: http://www.codeproject.com/KB/aspnet/ASP2UserControlLibrary.aspx
Check it out

Resources