Injecting a complete module in ASP.Net MVC - asp.net

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.

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 multi-site design

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

.NET ASP webpage inheritance

I am new to .NET and ideally want to make several layers of abstraction for making a fairly complex website. Being the first layer handling login, authentication, etc, with another layer handling the built in apps (how they look, predefined functions, database connections), and the lower level will be specific app implementation details.
This favors uniformity as all apps will inherit from one place allowing for easier maintenance and rapid development of all the smaller apps once the overhead abstraction layers handle their responsibilities.
The only problem is I am not 100% sure where to start with .NET ASP webpage inheritance. I tried Google and searching but I may not be looking for the right thing. I am hoping with someone with experience on the matter may direct me towards resources to make this kind of webpage inheritance/abstraction easier!
I am using Visual Studio 2010.
Edit:
I also want to add the purpose to my question: Another individual is creating the base of the website which will handle authentication, portal, UI look, etc
I want to make an app base that uses their website framework and adds onto it standards that every app must meet, function library, any addition UI overrides not applicable from portal, etc.
From there a third layer that will directly inherit from the above app base framework (abstraction) and further specify based on the guide lines made.
I appreciate the feedback so far!
In ASP.NET you have 4 common ways to reuse code/abstractions to serve you application-wide
The first way is just using a base page, which will inherit the standard asp.net Page and share the common logic for all of your pages, as explained here
The second way is using a master page: a master page defines a common design (html / css - wise) for all the pages that use it throughout the application. It can also be accessed programmatically by pages that use it, and therefore share a common logic
The third way is using an http module: An http module is basically a class, which is responsible for handling an HTTP request before its handled by the expected pages code on the server, and it allows you to add any common logic you want your application to use (such as authentication / authorization handling, getting relevant user information from the DB, etc)
Global.asax: contains application/session wide event handlers, which allow you to handle those events in once place (everything from application starting to a user session ending)
Using modules and base page is the preferred way, if you want to build few applications, sharing common behaviour. A master page can be used as well, of course, if you want them to share the same design as well.
That's quite a broad question. Welcome to ASP.NET!
I would suggest researching these topics:
Web page inheritance -> Master Pages,
Skinning -> App_Themes,
separation of responsibilities -> MVP design
pattern for the Web Forms platform, or MVC if you have a choice.
Login, roles -> Membership

What's the right tier to obtain directory attributes for display?

I have an intranet application that needs contact information for various locations on our campus that are served by our IT lab support organization. We have an enterprise directory that contains contact information so I'm not keeping the actual contact information in the database, but rather an immutable identifier that serves as a key to look the person up in our enterprise directory (via a web service). I'll be looking contact information up via a publicly available web site.
The problem comes in that the id that is useful to the web-based directory lookup is only "sort of" immutable and is not the id that I will store in the database. Directory lookups are most easily performed using the person's Active Directory login id. What I will be using is called the Master Records Unique ID.
My question is: where is the most reasonable place to do the translation from MRUID to Active Directory login id for the link?
Right now I'm doing the translation in the presentation layer, with application-level caching to reduce look ups to the directory. Currently there is only a single web site, but I would expect that if there are other web sites that need to do this, I would migrate the helper class to a shared web controls library.
I considered putting the code in the data or business layer, but opted not to because of the caching. How and what you cache seems to be more a function of the application rather than these other layers.
I'd be interested in other opinions and ideas that I may not have considered.
When faced with something that needs to be in the presentation layer of an asp.net web site or web application, but it also may have value in other asp.net web applications I find it useful to create a special class library that has a dependency on the system.web namespace.
Specifically, it will make use of HttpContext.Current to interoperate with the web site that is hosting the library. I'm not sure, but I generally think of this as a business layer assembly, but one that assumes it is hosted in a web context.
I keep my true business code (code that might be used in a non-web application) in a third assembly.
Having an assembly that depends on the web context allows you to use HttpContext.Current to find out what is going on with request and response objects as well as allowing you to interact with the asp.net cache API and related stuff. But it also keeps the code portable for use in more than one web application too.
Generally this web-dependent assembly is also where my HttpModules and HttpHandlers live too.
Keep in mind though that "layers" are logical concepts, not physical ones. There is nothing wrong with an assembly that contains business, DAL, and even presentation layer classes together. The classes themselves shouldn't mix up their roles, but a single assembly can contain classes from different logical layer in your design.
You could place it in your business layer and still use caching, either using the Enterprise Library Caching Application Block in the business layer, or by caching the value returned by the business layer in the ASP.Net cache in your presentation layer.
As it's coming from a different location to your other data I wouldn't put it in the same data access layer as the other database code.
I discussed this issue with some other developers at work and we decided that the presentation layer was the right place to do the translation. Consider the case where different applications that use the same business/data access layers want to translate the data in different ways. Unless we have a clearly defined business rule that states that individual identities shall always be displayed in a certain form, I think I'll leave it where it is and migrate it to a web controls library as needed to support multiple front-ends.

Resources