Is it possible to retrieve the equivalent of Page.PreviousPage within a generic .ashx handler, following a cross-page PostBack from an .aspx page?
I need to access some POST values from the Page performing the PostBack and - while I could simply use Request.Form - the values in question come from WebControls and, as such, have rather obscure (and not very robust) names (e.g. ctl00$WebFormsContent$SomeControl$SomeOtherControl$txtWhatever).
I have tried the following:
public void ProcessRequest(HttpContext context)
{
Page previous = context.PreviousHandler as Page;
if (previous != null)
context.Response.Redirect("http://www.google.com");
}
However, this does not work - upon debugging, I can see that context.PreviousPage is null.
Is there a way to retrieve this information and cast it as a Page?
The PreviousHandler will not help you here. To get your HttpHandler to receive a cross-page PostBack, you have to understand the underlying workings of this.
Refer: Redirecting Users to Another Page
Cross-page posting is similar to hyperlinks in that the transfer is
initiated by a user action. However, in cross-page posting, the target
page is invoked using an HTTP POST command, which sends the values of
controls on the source page to the target page. In addition, if the
source and target page are in the same Web application, the target
page can access public properties of the source page. As always, all
of the pages in the application can share information stored in
session state or application state.
As will be clear after reading that bit, all the values you are looking for are actually sent to your handler as POST variables.
You can find them in the context.Request.Params collection.
Now that you have the request from your page, lets say Page1.aspx in your handler; we need to create an object that can handle and processing this request. This is an instance of your Page1 object.
string pagePath = "~/Page1.aspx"; //virtual path to your page
Type type = BuildManager.GetCompiledType(pagePath); //find the type
//create an object of your page
Page myPage = (Page)Activator.CreateInstance(type);
myPage.ProcessRequest(HttpContext.Current); //process the request
After you have processed the current request using your object, you will find the Controls collection is populated and filled with the input data. You can now use exposed properties or FindControl to find the necessary controls and fetch input from them.
Related
I wonder how postback is detected on serverside?
Generally, the state of controls on a page are stored in Viewstate and they traverse back and forth on every postback to the server.
Since http is stateless, how will the server differentiate between a postbacked page and Initial Page load.
we can use Page.IsPostback property which is auto set to true or false for postback and initial load respectively. But my question is what controls this assignment of true and false to Page.Ispostback property and how server figure out a form postback?
Is there any hidden field that server uses to detect a postback of a Page?
In the context of ASP.NET, first page load is a HTTP GET request, after that they are POST requests.
Similar question here.
Technically, first page could be made as a POST, but this is not typical.
It's somewhat complicated. System.Web.UI.Page weighs in at roughly 6500 lines with numerous public/internal dependencies.
http://referencesource.microsoft.com/#System.Web/UI/Page.cs
From your earlier comment:
just like we expected, client sends some hiddenfields to server to
detect the postback and based on this the IsPostback is set to true.
You are correct that hidden fields are used. IrishChieftain was also correct in pointing out that the HTTP verb is used in the determination.
The overall process is stateless.
Page proceeds through a number of steps to make the determination.
Starting with ProcessRequestMain():
Check if the page uses a PageAdapter.
Call the PageAdapter's DeterminePostBackMode() method, or call DeterminePostBackMode() on the page itself.
...which calls GetCollectionBasedOnMethod()
Is the request a POST? try to return the Request.Form collection.
Do we get a collection from GetCollectionBasedOnMethod()? if so check for certain hidden fields.
Check for a cross-page postback, and set _pageFlags[isCrossPagePostRequest] accordingly.
Those appear to be the prerequisites necessary to call IsPostBack.
public bool IsPostBack {
get {
if (_requestValueCollection == null)
return false;
// Treat it as postback if the page is created thru cross page postback.
if (_isCrossPagePostBack)
return true;
// Don't treat it as a postback if the page is posted from cross page
if (_pageFlags[isCrossPagePostRequest])
return false;
// Don't treat it as a postback if a view state MAC check failed and we
// simply ate the exception.
if (ViewStateMacValidationErrorWasSuppressed)
return false;
// If we're in a Transfer/Execute, never treat as postback (ASURT 121000)
// Unless we are being transfered back to the original page, in which case
// it is ok to treat it as a postback (VSWhidbey 117747)
// Note that Context.Handler could be null (VSWhidbey 159775)
if (Context.ServerExecuteDepth > 0 &&
(Context.Handler == null || GetType() != Context.Handler.GetType())) {
return false;
}
// If the page control layout has changed, pretend that we are in
// a non-postback situation.
return !_fPageLayoutChanged;
}
}
System.Web.UI.Page class uses various methods to check whether the current request is a post back (setting the IsPostBack property). Some (not all) of these are:
Check whether the current request is a cross page post back, ie, whether it is a post request to the current page from another page. If so the request is treated as a post back.
There is a __VIEWSTATEGENERATOR hidden field in every HTML page rendered by .Net. If in a request received by the page, this hidden field is absent, or there was some error in the validation of the field's content then the request is not treated as a Post back.
If the request to the page is via a Server.Transfer, then it is not treated as a post back. There is an exception to this case, if the Server.Transfer to this page was initiated from this page itself then request is treated as a post back.
If the layout of the current page has changed since the last response, Page class will pretend that the request is a non-post back request. The layout changes are identified using the view state information received from the request. There are 2 view state related, .NET hidden fields in every response which assist in determining layout changes.
__VIEWSTATEGENERATOR
__VIEWSTATE
More information can be obtained from the source code for System.Web.UI.Page.IsPostBack property
The Visual Studio solution for this source code is also available for download
Problem
I have some pages that need dynamic data from website to generate output to users.
A simple solution is an aspx(php, ...) page to generate data and create another html page serving as GUI retrieving data from first page and showing it to users. in this method I can call my GUI page for example form1.aspx and my data page form1.json.aspx.
although I personally like this method, it is not suitable when creating components for it.
Another method that currently I'm using is using same GUI page call itself with a querystring to retrieve data. this page should check for that query string and if it exists, only generate data and remove everything else from page. As an example for this method if I call my page form1.aspx, to retrieve data, I need to call it like form1.aspx?JSON
Here is an example of what I'm doing:
protected void Page_Load(object sender, EventArgs e) {
if (Request.QueryString.ToString().IndexOf("JSON") == 0){
this.Controls.Clear();
Response.Clear();
// send pure data to client
} else {
// render page as GUI
}
}
However this method becomes too messy if I add master page and/or inherit my page from some template page. Master pages can only removed in Page_PreInit and that adds another extra method.
Security controls cause another problem, if user leaves page open for long time until session expires any attempt to retrieve data will fail cause security module will redirect the request to login page.
Next problem is I cannot consolidate my component in package because it needs modification in page (removing master page, clearing page components ...).
What I'm looking for:
1- I'm looking for a solution that I can call my page and get pure data (JSON or XML format) and doing so run a server side method that generates data, so I don't have to worry about what another designer puts in their master page or template.
2- I think it is possible to use axd extension to do this but I don't have a clue about it and couldn't find a helping document either.
3- Is there any better way of doing this. any suggestion or solution to improve this much appreciated.
Page methods. Check this article: http://weblogs.asp.net/craigshoemaker/archive/2008/09/29/using-jquery-to-call-asp-net-ajax-page-methods.aspx or http://encosia.com/using-jquery-to-directly-call-aspnet-ajax-page-methods/
WCF JSON service: http://www.codeproject.com/Articles/327420/WCF-REST-Service-with-JSON
Other ways of doing is using an HTTP Handler. Implement IHttpHandler interface and register your implementation in your Web.config file. Later call it using jQuery ($.get / $.post):
http://msdn.microsoft.com/en-us/library/46c5ddfy.aspx
EDIT
As OP pointed out, in order to access session state in a page method you should use WebMethodAttribute this way:
[WebMethod(EnableSession = true)]
I think you can use webservice instead of aspx page to return a JSON or XML string and then the caller page (any aspx page) will response after process is success.
So with this webservice, any third party page will have access to your server side method.
To create a webservice pls Check this link: Create and use Asp.net web service basic
Regards
I googled this about 1/2 a hour no hit's. Scenario is that, dynamic scripts are saved in string builder whose "string" representation is stored in session. It just happens that when user navigates away from one page to another the script[from session] gets registered using "RegisterStartupScript". The script is registered in PreRender event of the Page. So i would like to clear this script in session while the page navigates away btw rule out a option to create another session variable and clear previous one. It's a overhead :(
Why are you storing this in Session, do you need to maintain this script in between GET requests?
If only postbacks are relevant you could store it in viewstate as this is maintained only when doing a postback.
If you want this string to be available on GET requests too you might want to introduce a different variable which has an identifier identifying the page for which the script is generated. If the requested page doesn't match the control variable you will have to generate a new script.
How is the user navigating away from the page? Can't you use an ASP.NET button instead of a hyperlink, and then do a Redirect in code once you have cleared your session variable?
protected void btnDoSomething_Click(object sender, EventArgs e)
{
Session["Value"] = String.Empty;
Response.Redirect(strURL, false);
}
OR You could add a variable in the query string and check it in the Page_Load event of the target page:
Webform1.aspx?reset=true
Since I cant comment yet, use onUnload().
It fires on full postbacks too. Ajax postbacks dont fire!
What you need to do, is guaranty inside the onUload function that you only clear the session when you want. Like setting a variable isPostBack to true before the postbacks so onUnload sees the variable and doenst send a request to clear the session.
You may use the JavaScript onUnload() and call an AJAX service, that will clear the server side session.
I have a webpage 'WPwp1.aspx' and another webpage 'FLcourt.aspx'
In WPwp1.aspx i have DropDownList2,DropDownList3,TextBox1,TextBox2,TextBox3 and a LinkButton1
On click of a link button i want to
redirect to FLcourt.aspx.
FLcourt.aspx also has the controls
that are there in
WPwp1.aspx(DropDownList2,DropDownList3,TextBox1,TextBox2,TextBox3)
When user input value in the controls present in WPwp1.aspx and clicks on LinkButton1, the user should be able to see all the values that were being given as input in 'WPwp1.aspx' into the asp.net controls in 'FLcourt.aspx'.
How is it possible to pass values being input in some controls in a webpage to similar controls in another webpage?
Yes, you have several options:
Use Session variables. This is the less scalable way. Just before Response.Redirect, store
your values in Session and get them in the Page_Load of the target page.
Using QueryString. Pass the values in a query string:
Response.Redirect(
string.Format("FLcourt.aspx?value1={0}&value2={1}",
HttpUtility.UrlEncode(value1),
HttpUtility.UrlEncode(value2)));
And in the second page:
var value1 = Request.QueryString["value1"];
UPDATE
Using cookies (the client's browser must have them enabled). Set cookies before Redirect:
Response.Cookies["MyValues"]["Value1"] = value1;
In the target page:
if(Request.Cookies["MyValues"] != null)
{
var value1 = Request.Cookies["MyValues"]["Value1"];
//...
}
(but you have to check that Request.Cookies["MyValues"] is not null before)
You can try this out.
In your source page ("WPwp1.aspx") create properties for each control i.e. DropDownList2,DropDownList3,TextBox1,TextBox2,TextBox3.
Give "PostBackUrl" property of the linkbutton to the page you want to redirect, in your case it will be "FLcourt.aspx".
In the destination page ("FLcourt.aspx") access the previous page with the help of "PreviousPage" class. This class will give you the properties which you have written in point1.
Hope this helps!
Regards,
Samar
See: http://msdn.microsoft.com/en-us/library/6c3yckfw.aspx
To summarize and answer your question directly, you can:
Use a query string.
Get HTTP POST information from the source page.
And since both pages appear to be in the same Web Application, you can also:
Use session state.
Create public properties in the source page and access the property values in the target page.
Get control information in the target page from controls in the source page using the PreviousPage object. This option has a particular performance disadvantage as a call to PreviousPage results in the instantiation of the object and the processing of its life-cycle up to, but not including PreRender.
Sometimes, though, it is simpler to avoid cross-page postbacks and simulate the multiple pages/stages with Panel or MultiView controls.
Use sessions
Use cookies
Use Applications (global)
Post Back URL
Query String
Server.Transfer
Static Variables (global)
http://www.herongyang.com/VBScript/IIS-ASP-Object-Example-Pass-Value-between-Pages.html
its shown how you do it between two pages.
I have a text string value that I'd like to persist from one web page to another without using query strings or the session/view states. I've been trying to get the ASP http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.hiddenfield.aspx">HiddenField control to pass information from one web form to a different form.
All the hiddenfield control examples that I've seen is to preserve round trips from the client to the server for the same form.
Is there way for a form to access the ASP controls (and their values) from the previously-rendered form? Or is the initial form simply disposed of in memory by the time the second form executes it's OnLoad method?
Quick answer is no. As others have noted, you can use Server.Transfer and then you can - however this is to be used with caution. It is a "server side redirect" eg.
Your user is on http://mysite.com/Page1.aspx they click a button and you perform a Server.Transfer("Page2.aspx"). Page2.aspx will be rendered in their browser, but the URL will still be Page1.aspx, this can cause confusion and mess up back/forward navigation.
Personally I would only use Server.Transfer as a last resort - in the world of the web, sharing data across pages generally means you need to use a storage mechanism; Cookie, QueryString, Session, Database - take your pick.
You can't get the previous page fields with Response.Redirect.
You can with cross page posting :
if (Page.PreviousPage != null)
{
TextBox SourceTextBox =
(TextBox)Page.PreviousPage.FindControl("TextBox1");
if (SourceTextBox != null)
{
Label1.Text = SourceTextBox.Text;
}
}
If both pages live in the same application you can use Server.Transfer:
firstpage.aspx:
protected void Page_Load(object sender, EventArgs e)
{
Server.Transfer("~/secondpage.aspx");
}
secondpage.aspx:
protected void Page_Load(object sender, EventArgs e)
{
Page previousPage = (Page) HttpContext.Current.PreviousHandler;
Label previousPageControl = (Label) previousPage.FindControl("theLabel");
label.Text =previousPageControl.Text;
}
A somewhat better solution would be implementing an interface on your first page where you expose properties for the values needed by the second page.
I would presume that the Response.Redirect() sends a Location: HTTP header to do a redirect.
As HTTP is stateless, I'd also presume that these variables are inaccessible.
There are however, solutions.
Print a form with hidden fields, and use javascript to submit it
Redirect in the code internally (load up the thing it needs to get to manually)
Store the data in some temporary database table somewhere, and pass along a unique ID
However, from my experience, I can't understand why you might need to do this (other than re-submitting a form after a user authentication - which hopefully you should be able to use method 2 for
Remember, a Response.Redirect instructs the browser to issue another request to the server. So far as the server is concerned, this next request is indistinguishable from any other incoming request. It's certainly not connected to a previous form in any way.
Could you explain your aversion to storage in the session, so we can propose some viable alternatives?