Patterns used for navigating between pages in ASP.NET:

ASP.NET offers different APIs and ways (like Server.Transfer, Response.Redirect etc.) through which you can navigate between pages in your web applications. But before choosing any of these ways, we must have an understanding about the pattern that we want to follow. Depending on the pattern used, our choice about selecting an API changes.

Broadly, there are two patterns used for navigating between pages depending on the requirement:

1. Loosely Coupled Architecture:
In this pattern, each page has its own processing unit. So if you have a page that has some input controls, its code behind will have all the logic to form SQL Queries based on input and get the result also from database. Then when it comes to displaying the result, another page (the results page) is invoked and the data of previous page are passed to the new page. This is called loosely coupled architecture since each page is given a responsibility and it performs its work without being dependent on any other parts of the system. So one page is given the responsibility to gather user input and prepare the result and another page is given the responsibility to display data. The picture given below illustrates this architecture in a better way:

fig1

When to use this pattern:

Now when we know that what this architecture means, we can appreciate the scenarios where we can use it. The scenarios are too wide, and one possibility that I can think of is the scenario where you want a decentralized approach. Whenever we have scenarios where processing logic is different for each page, we go for this approach since there is no point in delegating the processing logic to results page. If we delegate the processing logic to results page, we will have many results page so to avoid this, we choose to keep the processing logic in the input gathering page itself.

How to implement:

The default model of ASP.NET provides this facility where each page posts to itself until we specifically configure the controls to post to another page. The steps involved are:

a) Implement the input page with all the data preparation logic in its code behind. The controls on this page will post to itself.
b) Invoke another page when the processing is done and pass the processed data to the target page. This second step can be achieved in many ways depending on the requirements. Below I show few techniques that can be used.

a) On the first page’s code behind (having input controls), when all the processing is over, add the data to be transferred to next page into the “Context” collection (Context.Items.Add() method can be used for adding into Context collection) and then invoke the target page using Server.Transfer() . On the target page (the results page) retrieve the data from the Context Collection simply by using Context.Items[] collection and typecast it if needed. Context collection remains into scope this ways on the target page as well (remember we cannot use response.redirect() method if we want to use Context collection to store our data since context dies the moment the request thread leaves the server).

b) Another API to achieve this is to use Request property. This basically gives you reference to the current context and then using Request.Form we can access the source page.

c) If you want to use the data between multiple requests, you can store data into Session collection instead of context collection. Everything else remains same (and yes we can use response.redirect() method if we are using session to store our data).

d) A third way could be to get the reference of the source page on the target page. Whenever we use Server.Transfer() method to navigate to another page, we can access the source page from Context.Handler property. So all we need to do is to create storage on the first page (for example by creating a property called data on source page) and store the result in that property. Then, on the target page access the properties (in fact everything that is public on the first page including controls) by using Context.Handler. This approach is used in cases where we have many discrete data elements to be transferred to the target page. So instead of adding them to Context Collection on first page, we add into the page itself by creating properties. Then we can access all the properties of source page on the target page. Another good thing in this approach is that we do not need to typecast in contrast to Context/Session approaches. More can be found here:
https://msdn2.microsoft.com/en-us/library/6c3yckfw(vs.71).aspx

2. Coupled Architecture (Centralized approach):
In this pattern, we designate a central page for processing the input and displaying the results. We form separate pages for gathering input. The input pages gather data from end user and post it to central processing unit (the results page). This is the approach where you post the source page directly to another page (the cross post scenarios). The following figure illustrates this:

fig2

When to use this pattern:

This approach is used whenever we want to reuse the code. If the logic can be reused across multiple pages, then there is no point in writing the same logic on multiple pages and making code unmanageable. In that case we create a central processing unit (the results page) and all other pages just collect data from end users and post themselves to the results page.

How to implement:
 
We can use PostbackURL property of controls to specify the target page. In this approach, on the source page we specify the target page URL in the PostbackURL property of controls (for example a submit button). This ways, when end user clicks on the submit button all the data of the input page is sent to the target page directly. So no need to write any code behind on source page. A very clean way to implement this pattern.

Yet another model can be followed which involves, first posting to the source page itself and then source page transferring to the target page but no processing is done at source page. We can do this by using Response.Redirect() and then passing the input data using query strings.

Rahul's