3-tier architecture v. 3-server architecture - c#

I'm building a traditional .NET MVC site, so I've got a natural 3-tier software architecture setup (presentation in the form of Views, business layer in the controller, and data layer in the models and data access layer).
When I've deployed such sites, it usually goes either on one server (where the web site and db live), or two servers (a web server and a separate db server).
How does one go about a 3-server architecture (WEB, APP, and DB)? Would the web server just have the presentation (e.g. the physical View/aspx pages), the app server would hold the config file and bin folder, and the db server would remain as is?
My question is essentially, can you simply move the /bin and all app logic onto a separate server from the presentation views? If so, how do you configure the servers to know where to look? If there's a good primer somewhere or someone can give me the lowdown, I'd be forever indebted.

MVC is not a 3-tier architecture. Not every solution needs to be 3-tier or n-tier, but it is still important to understand the distinction. MVC happens to have 3 main elements, but those elements do not work in a "tiered" fashion, they are interdependent:
Model <----- Controller
\ |
\ v
---- View
The View depends on the Model. The Controller depends on the View and Model. These multiple dependency paths therefore do not function as tiers.
Typically a 3-tier solution looks like:
Data Access <--- [Mapper] ---> Domain Model <--- [Presenter/Controller] ---> UI
Presenter/Controller is somewhat optional - in Windows Forms development, for example, you usually don't see it, instead you have a "smart client" UI, which is OK too.
This is a 3-tier architecture because each of the 3 main tiers (Data, Domain, UI) has only one dependency. Classically, the UI depends on the Domain Model (or "Business" model) and the Domain Model depends on the DAL. In more modern implementations, the Domain Model does not depend the DAL; instead, the relationship is inverted and an abstract Mapping layer is injected later on using an IoC container. In either case, each tier only depends on the previous tier.
In an MVC architecture, C is the Controller, V is the UI (Views), and M is the Domain Model. Therefore, MVC is a presentation architecture, not a system architecture. It does not encapsulate the data access. It may not necessarily fully encapsulate the Domain Model, which can be treated as an external dependency. It is not tiered.
If you wanted to physically separate the tiers then it is usually done by exposing the Domain Model as a Web Service (i.e. WCF). This gives you improved scalability and a cleaner separation of concerns - the Domain Model is literally reusable anywhere and can be deployed across many machines - but comes with a significant up-front development cost as well as an ongoing maintenance cost.
The server architecture mirrors the 3-tier diagram above:
Database Server <----- Web Services <----- Application
The "Application" is your MVC application, which shares a Domain Model with the Web Services (through SOAP or REST). Web Services run on a dedicated server (or servers), and the database is, obviously, hosted on its own server. This is a 3-tier, 3-server architecture.

In some circles, I have seen this discussion phrased as the difference between n-tier and n-layer where a "layer" in this context potentially represents another machine. In order to have a middle layer using this definition, it must be hosted. For example, if you had a service layer which the presentation layer called to get its data, then the service layer could be on a different machine than the presentation or database. However, that service layer is hosted either as a windows service or as a web service. I.e., there is a process listening for requests on that machine. Thus, you cannot simply move the bin folder to different machine and hope to have this work. I would look at WCF (Windows Communication Foundation) for creating these types services.

ASP.NET MVC does not help you in setting up a 3tier system. This is realy only a frontend pattern.
The main issue you have to solve implementing a multi tier system is the transport of objects from one server to another. You have to find a way to serialize all objects depending on the transport channel. This gets slow and development gets more complicated.
There are reasons to have a separate app-server: You might have logic in it that other application need or the app-server might have different permissions than the Webserver. But its hard to imagine a high traffic website, where all requests lead to a call to a remote app - server.

Next logical scale up would be two web servers and one database server.
Eventually after adding many web servers it might be worth adding a service layer.
You might also want to add a distributed cache, session state server, email server, and other specialized servers at some point too as you scale.

So your questions seems to be ...
"can you simply move the /bin and all app logic onto a separate server from the presentation views?"
If I am understanding correctly, I believe the files in your bin folder will be the compiled code behinds for your asp.net pages. If that is the case then, no, I believe they need to be on the same machine as the asp pages.
If you want to have your business logic on a seperate machine from the presentation layer you would need to wrap that code into a seperate dll and expose it via soap or some other protocol .. and then call those SOAP exposed dlls on the other server from the code in your presentation layer.

Related

In a layered architecture, how can the Application layer know about Web URLs?

I'm currently working on a .NET 5 app that is using a layered architecture (Web / Application / Infrastructure / Domain). If I am to follow the onion/clean architecture pattern, the dependencies should flow in one direction only, e.g:
Web -> Application -> Infrastructure -> Domain
I now find myself needing to send several emails from the Application layer containing specific front-end URLs. This means that the Application layer will know about the Web layer, breaking the dependency flow.
A sample use case flow would be:
User makes a request, gets handled by a controller in the Web layer
Controller calls a handler on the Application layer
The Application layer uses an email service from the Infrastructure layer to send an email
On step #3 I'm in the Application layer but need Web URLs to construct the email body.
How can I solve for this issue?
I've recently solved this problem within my organization. In our case we have an API "market place" used by the company as a whole, then a reverse proxy used by closely integrated clients, and finally an internal load balancer for the API containers.
That's 3 layers of URL knowledge that my Web and App layers shouldn't know about (even at the Web layer it shouldn't know this because that would make our web layer have more than one responsibility rather than just be a router (e.g. via Mediatr)).
Using Rewriters in the Infrastructure
This is what Z. Danev's answer is all about. This works, but you must maintain all the rules for each of these layers, and each of those rewrites may add overhead. Also, those rules could get tricky depending on the complexity of the data you return.
It is a valid solution though. Depending on your organization this may be an easy thing, or it may be a hard one because it's maintained by other teams, need work tickets, and so on to get the job done.
Well, if you can't or don't want to do that, then...
Application Layer Dependency Inversion and Patterns
Disclaimer: This solution works great for us, but it does have one drawback: at some level, you have to maintain something that knows about the layers above. So caveat emptor.
The situation I described above is roughly analogous to your problem, though perhaps more complex (you can do the same but simplify it). Without violating your architectural principals you need to provide an interface (or more than one) that can be injected into your application layer as an application service.
We called ours ILinkBuilderService and created a LinkBuilderService that itself can be wired up through a DI container with individual ILinkBuilder implementations. Each of these implementations could be a MarketPlaceBuilder, a GatewayBuilder, etc. and will be arranged according to a Chain of Responsibility and Strategy patterns from outermost proxy to innermost.
In this way, the builders inspect the web context (headers, request, etc.) to determine which one should handle the responsibility of building links. Your application layer (e.g. your email sender) simply calls the link building service interface with key data, and this is used to generate client-facing URLs without exposing the application layer to the web context.
Without going into too many details, these builders inspect headers like X-Forwarded-For, custom headers, and other details provided by proxies as the HTTP request hits each endpoint. Chain of Responsibility is key, because it allows the application layer to generate the correct URL no matter at which layer the request originated from.
So how does this not break the one-way flow?
Well, you push these builders one-way down into your application layer. Technically, they do reach back up to the web layer for context, but that is encapsulated. This is ok and does not violate your architecture. This is what dependency inversion is all about.
Consider configuring "well known urls" at the web infrastructure level (gateway or load balancer for example) so you can have "mycompany.com/user-action-1" in the email and that will translate to the proper endpoint of your web app.

Application Service code in WebAPI

We are starting a new project and trying to implement some concepts from Domain driven design. We are planning to have following layers:
Web Interface (WebAPI)
Application Services (library)
Domain Services (library)
Data Access Services (Library)
We are thinking about merging Web interface and Application service together. So, our webAPI will be talking to repositories, domain model and domain services.
Is this fine or should we have separate project form application services and WebAPI should only communicate with Application services?
Thanks
HTTP should be seen as one of potentially many access ports to reach your application services. If you could be entirely sure that you will never have to speak to your application through another communication channel than HTTP then I'd say it's perfectly not to have a seperate application layer.
However, I'd also say that it's very hard to predict how application needs will evolve and since adding an additionnal layer of indirection to segregate the application layer right away shouldn't be very costly (it's just delegation) that's what I'd do.

Domain Driven Design Windows Azure Web Job

Certain behaviors of my domain model qualifies to be delegated to Azure WebJob. If I continue to use same domain model class across Website & Web Job,
it seems like violating separation of concerns. There will be tight coupling between two different processes.
Should a background process, Web Job in this case, always have its dedicated Domain Model & behaviors exposed by this should only be consumed by one process?
If your domain model is free of any dependencies to the environment (which it should be), then I don't see a problem with that.
On the contrary: Using the same domain model within a bounded context is preferable, because you are able to capture the business rules in one place. Like this, you are sure you don't run into impedance mismatch problems between two models.
If you are using domain events, you already have a basis for the communication with the web job. This is exactly what we've been doing for over a year, and it works great:
Web apps publish domain events to an Azure Storage Queue
The web job receives them and performs the background processing on the same model
So all you need to do is create two separate application / service layers (one for the web application, one for the background worker) and make sure all domain logic is in a reusable library.

Use of database for multiple Places in windows application in c#

I have a developed a application that is gonna to be used at multiple places.
So how should i maintain one database for all?
Or is there only one way of using remote database for this software.
If i use remote database, i am facing problem with loading controls in forms.
Please Suggest Solution.
Thanks
Typically you'd design a system leveraging multi-tiered architecture, which often consists of:
Front-end user interface
A database back-end
Middle tier/business layer that let's your web pages access the database and provides additional business logic (perhaps a web service?)
You don't give much to go on as far as details go, but it seems like you have several physical locations that need to access a single database. So you can:
Develop an (web or desktop) application that handles the front-end UI and the middle tier (which will access data and do other stuff)
Develop an application that handles only front-end UI, but calls a web service that accesses a database and does other stuff. In this case, you may have several locations with different front-end applications that consume the same centralized web service.

How to expose a service layer to UI components

We have an application in which we have created a service layer with most of the business logic and utility services (logging, exceptions, caching etc). We have to come with a way to expose this service as an API to the UI components. Here are some of our requirements:
We would like to create multiple
components based on the service.
We would like third party developers
to use our service to create their
own components or utilize our data.
For scalability we would like to have
a multiple instances installed on
different boxes. Similarly there
could be more than an instance of the
same UI component.
One way to expose the service layer is to host it under a REST based WCF layer.
The other way is to host the service in model layer of an ASP.Net MVC project. The UI components will be hosted in MVC projects of their own. The Javascript in the views of UI components will directly call the controllers of service project.
WCF is supposed to be very heavyweight option. On the other hand I am not too convinced with the MVC approach as I feel that this is not purpose it is meant for.
Could you please recommend me a way in Microsoft world to expose our service layer.
WCF seems to be the way to go here. Although WCF started out (in my oppinion) as a beast, it got tamed over the years with better HTTP and JSON support and less custom configuration (although still allowing you to modefy basicly every little aspect of your service).
Exposing your current service layer as a REST Service is a breeze and allows your customers/yourself to easily consume it on any device that supports HTTP.
See: http://codebetter.com/glennblock/2010/11/01/wcf-web-apis-http-your-way/
Models are not services. Models are POCOs that hold data.
You can expose your service through a WCF Service, and let your ASP.NET MVC app consume it. If you're always sure that the service will run on the same box as the client app, you can use named pipes for transport -- then the overhead of WCF is minimal, compared to the advantages.
WCF seems to be the direction that Microsoft is headed for this and for good reason. WCF services are the best option here because you mentioned third-party development support. Because these web services are defined by a WSDL, they are cross platform and can be consumed by non .NET applications.
It perfectly seperates your service layer to be consumed by ANY components.

Categories

Resources