How to detect postback in Razor Page? - c#

I'm using a single razor page (cshtml) that has a form and #functions{} section to capture an OnPost(). All of that works fine.
In the HTML section, I need to know when a post back has occurred and display a message. I'm not sure where or how that is done in a Razor Page. I've tried IsPost but that isn't available.
I created a string property in the class and set a value on it in OnPost but once I'm in the view, the property is null.
I assigned a value into ViewData["mystring"] but it is also null once I get into the view.
-- EDIT --
It seems the issue is that I'm trying to set a property in OnPost, which is the request. After OnPost, OnGet will always fire. OnGet is the Response. I can see the flip from POST to GET in this.Request.Method. So I lose any indication that a postback happened.
Any suggestions on how that is done?

You should use use Post-Redirect-Get pattern. The message can be stored in TempData

Related

Possible to abort MVC action and keep view the same (without re-writing the view's GET "load code")?

Working on MVC5 web app.
I have a view based on a complex viewmodel. In the main GET method I'm filling this viewmodel, setting certain ViewBag items, etc.... I'll refer to this as the "load code" for now.
So, my view is basically a data entry form. Business rules are fairly complex. When the user hits the save button I do a POST and run some c# code which checks rules, etc... If it FAILS, I simply want to "abort" the action and show the user the same GET view.
My question involves all that was done to initially load the view: The ViewBag code, filling of viewmodel, etc.... Do I have to write this "load code" again in my POST? This seems very redundant. Is there a way I can just "abort" the ActionResult/POST and show the GET view?
I hope this makes sense. Thanks!
**** update/clarification - based on comments ****
I suppose this question is more of a "general" one. Can you "abort" the POST and go "back" to the GET View without re-running all the "load code" (for the dropdowns, populating the viewmodel, etc....)
If you want to go to server and validate and then decide if you want to accept the POST or Fails/Abort and keep the previous page with all the values
then I'll suggest you to handle this in AJAX.
Create a third action/API Method and keep your validation logic there. then on the form submit hit the validation action using ajax and server will return True/False (with any error message) if you get True from server then let the javascript post your form otherwise show any error message and return false to stop posting the form and stay on the page.
For example use a javascript method to validate.
<form onsubmit="return isValidForm()" />
function
function isValidForm(){
//// hit the server and see if you want to proceed with the POST
//// if fails return false so your form will not be posted and all of your values will remains the same, here before return false you can clear the form if needed.
}
let me know if you need more information.

How Postback is detected on serverside of a webform

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

PreviousPage in .ashx handler

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.

Unable to get updated value of session variable and Textbox

I am building a web application in asp.net and c#, I am storing text of textbox in Session variable like this:
Session["data"]=TextBox1.Text;
and on the button click event I am redirecting user to another page.In the second page I am using this variable Session["data"] and in page2 there is a back button where I am again Redirecting to page1 where the textbox1 is present.Now on the button click event where I am redirecting to page2 and event is code like this,
Session["data"]=TextBox1.Text;
Response.Redirect("page2.aspx");
now when I am accessing the value of the Session["data"] it is giving me the previous value.As the content of TextBox1 may get changed,these changes have not been shown.
Please tell me where I am going wrong.
I dont think the code you are using is worng. You please make a break point and check it again that the values are assigning correctly
Or
You just set the session to null and then assign the textbox value to it on the click event.
Read this I think Respone.Redirect might be causing you to lose your session data
Don't redirect after setting a Session variable (or do it right)
A problem I see over and over again on the ASP.NET forums is the
following: In a login page, if the user and password have been
validated, the page developer wants to redirect to the default page.
To do this, he writes the following code:
Session["Login"] = true;
Response.Redirect("~/default.aspx");
Well, this doesn't work. Can you
see why? Yes, it's because of the way Redirect and session variables
work. When you create a new session (that is, the first time you write
to a Session variable), ASP.NET sets a volatile cookie on the client
that contains the session token. On all subsequent requests, and as
long as the server session and the client cookie have not expired,
ASP.NET can look at this cookie and find the right session. Now, what
Redirect does is to send a special header to the client so that it
asks the server for a different page than the one it was waiting for.
Server-side, after sending this header, Redirect ends the response.
This is a very violent thing to do. Response.End actually stops the
execution of the page wherever it is using a ThreadAbortException.
What happens really here is that the session token gets lost in the
battle. There are a few things you can do to solve this problem.
First, in the case of the forms authentication, we already provide a
special redirect method: FormsAuthentication.RedirectFromLoginPage.
This method is great because, well, it works, and also because it will
return the user to the page he was asking for in the first place, and
not always default. This means that the user can bookmark protected
pages on the site, among other things. Another thing you can do is use
the overloaded version of Redirect:
Response.Redirect("~/default.aspx", false);
This does not abort the
thread and thus conserve the session token. Actually, this overload is
used internally by RedirectFromLoginPage. As a matter of facts, I
would advise to always use this overloaded version over the other just
to avoid the nasty effects of the exception. The non-overloaded
version is actually here to stay syntactically compatible with classic
ASP.
I don't really see what you want to do here. You say it works (the Session["data"] contains the text of TextBox1?) but you don't see any changes? What changes did you expect? Please give us some more information about this part of the question:
As the content of TextBox1 may get changed,these changes have not been shown.
Thanks.
Update:
Try clearing or remove the session and then refill it.
Session.Remove("data");
Session.Clear();

ASP.net not posting back to correct page

So I have a slightly unorthodox application type.
I have an aspx page called AddNewBlog.aspx. This page generates XML data from database queries and it include the file AddNewBlogXSL.aspx which is an xsl style sheet.
The effect is that the AddNewBlog XML data is transformed by AddNewBlogXSL on the client side into XHTML.
So although the requested page is AddNewBlog.aspx, the layouts and controls and forms are on AddNewBlogXSL.aspx since it contains all the layout and formatting.
When on AddNewBlogXSL.aspx I do an asp:button it tries to post back to AddNewBlogXSL.aspx as is understandable.
The problem is that page is an xslt stylesheet not a webpage.. I need it to post back to AddNewBlog.aspx as this is the proper page which includes AddNewBlogXSL.aspx
The only thing I seem to be able to do is allow the default behaviour which is to submit to AddNewBlogXSL.aspx, process the page, and redirect them to the proper page AddNewBlog.aspx but then it makes it hard to handle error messages and such since I have no control over AddNewBlog.aspx after I have simply redirected to it from AddNewBlogXSL.aspx
Any ideas at all?
You are looking for PostBackUrl property.
<asp:button id="Button2"
text="Post value to another page"
postbackurl="~/Path/To/AddNewBlog.aspx"
runat="Server">
</asp:button>
EDIT:
To address your comment, IsPostBack will not be true in this scenario because it isn't a postback, it's just a post to another page. You have to access the values via the Page.PreviousPage property as outlined in the MSDN article I listed.
During a cross-page postback, the contents of the source page's controls are posted to the target page, and the browser executes an HTTP POST operation (not a GET operation). However, in the target page, the IsPostBack property is false immediately after a cross-page post. Although the behavior is that of a POST, the cross-posting is not a postback to the target page. Therefore, IsPostBack is set to false and the target page can go through its first-time code.
Also per MSDN, you would check the PreviousPage.IsCrossPagePostBack property instead of the Page.IsPostBackProperty
if(PreviousPage.IsCrossPagePostBack == true)
{
//Get values from PreviousPage
text = ((TextBox)PreviousPage.FindControl("TextBox1")).Text;
}
Cross Page Posting Details
I went ahead and wrote a little test harness (aka, I took the example off the MSDN page, :-0 )to verify and results are as follows when cross page posting:
It's not an ideal situation and it kludgey to access your values as listed, but for the model you have designed, it's the best I can think of.
In addition to the above answer, Can you please confirm that the "AutoEventWireUp" is false in this page. If so, override the page load method in this case.

Categories