I have a simple ASP.Net login page. When the login button is clicked, the page should post back and the even should be handled by my server-side event handler. Instead, the page simply reloads. Page.IsPostBack is false.
I've put breakpoints in the Page_Load/Init (where applicable) handlers of the Master page, the ASPX page and the UserControl (ascx). When I hit the Login button, instead of getting a post back and having my event handler called, I simply get the page load as if it was a fresh request.
But that's not the end of it! The login page takes a single query string parameter: Login.aspx?id=123456. The above failure occurs when using this parameter. However, if I enable URL Rewriting in order to make the query Login/123456, the error does not occur; I get a post back and my event handler is called in this instance.
So why am I not getting the expected behaviour from my page? What about the rewritten URL is making the problem go away?
Login Button is declared in LoginUserControl.ascx:
<asp:Button ID="SubmitLinkButton" runat="server" Text='Log In' OnClick="SubmitLinkButton_Click"></asp:Button>
And the handler in the code behind:
protected void SubmitLinkButton_Click(object sender, EventArgs e)
{
Authenticate();
}
SubmitLinkButton_Click is never called. :(
Edit (more code):
//Page_Init on the Master page
protected void Page_Init(object sender, EventArgs e)
{
if (HttpContext.Current.User.Identity.IsAuthenticated)
{
try
{
if (SessionFacade.User != null)
{
loginlabel.Text = "Logged in |";
LoginLink.Visible = true;
}
}
catch
{
FormsAuthentication.SignOut();
CacheFacade.RemoveSessionValues();
Session.Abandon();
Session.RemoveAll();
HttpContext.Current.Response.Redirect("~/Login.aspx");
}
}
else
{
loginlabel.Text = "";
LoginLink.Visible = false;
}
}
Page_Load on the ASPX page:
protected void Page_Load(object sender, EventArgs e)
{
if (this.IsPostBack.Equals(false))
{
/* Some business stuff that boils down to this: */
Session["company"] = Request["company"];
}
}
Page_Load on the Login Control:
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
//honestly, there's no code here
}
}
P.S: I need to keep the non-url-rewrite way of accessing the login page, because many users are still navigating to that URL.
P.P.S: Even if URL rewriting isn't enabled, the error still occurs.
Whenever I've seen this problem in the past it has usually been attributed to URL re-writing. I would usually reach for Fiddler to trace the HTTP activity. My hunch tells me after you click the button and see the POST request it will quickly be followed up by a 302 redirect to the login page.
You note that "The above failure occurs when using this parameter" of the login.aspx page. Are you certain there is no url-rewriter configuration that for example, may strip out any querystring values and do a redirect?
Try to check your caching policy. Possibly your request is cached
I cleared the history on my IE browser and the problem went away.
Did you try to use a different browser? Once I had a similar problem, and it solved by re-installing Firefox!
Related
I control if a user exist in database. If it dont exist, I want to stay login page. If it exist, I want to go Default.aspx page.
protected void BtnLogin_Click(object sender, EventArgs e)
{
if(condition is okey)
{
// go default.aspx
}
else
{
//stay this page
}
}
What can I write on comment lines to achive this?
Thanks!
Sounds like you just want to do a redirect:
protected void BtnLogin_Click(object sender, EventArgs e)
{
if(myCondition)
{
Response.Redirect("/default.aspx");
}
else
{
//stay this page
}
}
If you want to retain the POST data, you can use Server.Transfer instead (note: based on your edits, it doesn't sound like this is what you need - I think you just need Response.Redirect):
Server.Transfer("/default.aspx");
Note that transferring the handler of the POST like this will not cause a browser redirect and therefore will not change the browser URL.
If you need to actually POST to a different URL and have the browser update, you'll need to post directly to that URL using a cross-page postback (using the action attribute on the form element), validate on that page and then redirect back to the original page if validation fails.
If I click on a link(Without logging into the site) I am navigated to this page:
http://localhost:59196/Login.aspx?ReturnUrl=%2fTest%2fContacts.aspx
When I login to the site I want to be redirected to my Home page rather than Test Contacts.aspx page.
How can I resolve this?
If i do this then I'm not logged in.
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Login1_LoggingIn(object sender, LoginCancelEventArgs e)
{
Response.Redirect("Home");
}
Just change link url you clicking on to:
http://localhost:59196/Login.aspx?ReturnUrl=Index.aspx
I think you clicked on Test Contact.aspx page with out logging in and hence you have been redirected to the Login page with a query string as ReturnURl = test contact.aspx, which might be used to redirect from the login page.
So instead of using return url query string you can redirect directly to your page page from the log in button click in the login page.
Hope it works.
I mean in
Loginbutton_click()
{
//login validation code here
//after successful validation
Response.redirect("Yyourhomepageurlhere");
}
You want to redirect to
http://localhost:59196/Login.aspx?ReturnUrl=%2fTest%2fIndex.aspx
rather than
http://localhost:59196/Login.aspx?ReturnUrl=%2fTest%2fContacts.aspx
In other words the link that you click on should point to the first link above rather than the second.
The question that remains is how are the links generated? Are they hard coded or are you using MVC and generating the link somehow? Is the link even in your control to generate?
It would appear your code looks at the ReturnUrl query string parameter and on successful login redirects to it.
Did you come to the Login page from the Contacts page? If so then the ReturnUrl might have been generated dynamically depending on where you came from. You may require this to be fixed to being the Index page (I assume this is what you have called it). Be careful though, other developers may want to have this link be dynamic.
I must changed the event.
protected void Login1_LoggedIn(object sender, EventArgs e)
{
Response.Redirect("Home");
}
I'm a bit puzzled by the behavior of the default ASP.NET Authentication controls, by its lifecycle to be precise.
In my MasterPage, I added a LoginView Control which displays the nice [Login] or [Logout] links. When I am logged in and click on [logout], I set up the control to perform a redirection to the homepage of the application.
Internally, when a click on "logout" happens, a postback is triggered. The following steps happen (among others of course):
The page that fired the postback is reinitialized
The page that fired the postback is reloaded
The LoggingOut event is fired
The LoggedOut event is fired
The page that fired the postback is PreRendered
The redirection happens
The target page is loaded (LoggedOut.aspx in my case)
On most of the pages, this works fine. But some pages expect some data to be initialized for their rendering to happens correctly. When this loggout postback occurs, the data isn't correctly initialized, but the page is still PreRendered which leads to some... "unexpected behavior" >_<
My question is thus twofold:
Why does this rendering step happens since the page won't be displayed at all?
Is there a way to prevent the rendering to happen?
Thanks a lot.
Tim
PS: here's a small VS2010 sample project showing you the call sequence & page lifecycle if you want to try it out for yourself http://dl.dropbox.com/u/11764136/LoginTest.7z
There is a way to prevent the actual rendering of the page.
Stop processing the current request when you redirect the page. This can be done by giving a true parameter to the Response.Redirect method:
Response.Redirect("http://somewhere", true);
You can also do this manually by calling Response.Close();
Are you using if(!isPostBack) test to control what should be rendered/re-initialized and what shouldn't?
Venemo's answer gave me an idea that seems to be working.
Instead of relying on the LoginStatus component to perform the redirection, I registered the MasterPage hosting the LoginStatus components to the LoginStatus.LoggedOut event and fire the redirection "per hand" before the PreRender step can be called.
protected void Page_Load(object sender, EventArgs e)
{
MasterLoginStatus.LoggedOut += new EventHandler(OnUserLoggedOut);
}
private void OnUserLoggedOut(object sender, EventArgs e)
{
Response.Redirect("~/LoggedOut.aspx", true);
}
I was concerned the LoginStatus component might remain dirty by doing this but sofar I haven't found any issue with it e.g. "works until proven otherwise".
Remains the question of "why the component behaves like this" but I guess it was a design decision that will remain unanswered.
Edit: this works fine until you get the same problem for the "login" action. Haven't found a way around this one yet.
I've got a serious problem with a DevExpress control (The report DocumentMap) which sometimes requests the whole report, bypassing the caching mechanism, when the end-user clicks on the logout link on the LoginStatus control. I've tried a lot of approaches to stop dead the "logout" postback so that the report won't get generated (some reports took 5 minutes to render, so the logout action sometimes took that long). I think this is similar to your problem: you don't want to do any heavy processing if the user is logging out. So I've tried a different approach: why didn't I recognize that the postback is indeed a logging out postback? All my pages inherit from a base page, so I've set this code in the base page:
public bool IsLoggingOut { get; private set; }
protected override void OnPreInit(EventArgs e)
{
base.OnPreInit(e);
var eventTarget = Request.Params.Get("__EVENTTARGET");
IsLoggingOut = eventTarget != null && eventTarget.Contains("HeadLoginView$HeadLoginStatus");
}
Now all I need to do in my page is to surround any heavy processing with a test of !IsLoggingOut... You could even do you redirect to the LoggedOut page without having to handle any events, just like this:
protected override void OnLoad(EventArgs e)
{
if (IsLoggingOut)
Response.Redirect("~/LoggedOut.aspx", true);
}
Even if you prefer to use the event handler to do that redirect, being able to know that the postback is indeed due to a logout click is a nice thing!
In my case, I was having this problem with the LoginStatus control. I can't see why it is a useful design to post back and Render the page when the user has clicked "logout". Through some tests, I found that I had to let the page go through its entire lifecycle, so Reponse.End() and Response.Transfer() did not work.
My solution was to add event handlers for the LoginStatus LoggedOut event, and then override the Render() method in the master page to do nothing if the user has logged out. I actually had the LoginStatus nested inside a user control that was then in the master page, so I had to bubble the event.
In my user control containing the LoginStatus control, I added an event handler for the LoggedOut event. In the UserStatus.aspx file:
<asp:LoginStatus runat="server" ID="loginStatusDefault" OnLoggedOut="loginStatusDefault_LoggedOut" ... />
Then in the code-behind:
public event EventHandler LoggedOut;
protected void loginStatusDefault_LoggedOut(object sender, EventArgs e)
{
if (this.LoggedOut != null)
this.LoggedOut(sender, e);
}
Now in the master page default.master, I have already included the UserStatus control:
<c:userstatus ID="ctlUserStatus" runat="server" />
and in the code-behind:
protected void Page_Init(object sender, EventArgs e)
{
ctlUserStatus.LoggedOut += ctlUserStatus_LoggedOut;
...
}
bool IsLoggedOut { get; set; }
void ctlUserStatus_LoggedOut(object sender, EventArgs e)
{
IsLoggedOut = true;
}
protected override void Render(HtmlTextWriter writer)
{
if (!IsLoggedOut)
base.Render(writer);
}
For me, the page rendering is what was bombing out when the user clicked "logout", so this took care of the problem for all pages.
What I did was have the logout link or onloggingout control just redirect to another page, "Logout.aspx" which then handles the log out code. Works great actually.
protected void LoginStatus1_LoggingOut(object sender, EventArgs e)
{
Response.Redirect("~/Logout.aspx");
}
I've written a custom widget to allow a user to select a location from a database of locations. This is my first ASP.net custom control. It seemed like everything was working fine, but now there's a problem.
My control implements the RaisePostBackEvent function as follows:
public void RaisePostBackEvent(string eventArgument)
{
SelectedLocationId = eventArgument.Split('|')[0];
SelectedLocationDescription = eventArgument.Split('|')[1];
}
I wrote a test page and included the following in my ASP code:
<%= locationSelector.SelectedLocationId %>
That worked fine.
However, in my web application, the following code does not work:
protected void Page_Load(object sender, EventArgs e)
{
if (Page.IsPostBack)
Response.Write(locationSelector.SelectedLocationId);
// SelectedLocationId is null here!!!
}
When I run this code in the debugger, I see that my Page Load event fires before the Post Back event! Therefore, the data is not yet read from the postback. I know that using the MS provided text field control, the text is available at Page Load, so I think I must be doing something wrong.
How can I read the location that the user selected when the Page Load event fires? To clarify, I'm refering to the Page Load of a web application page.
You're setting SelectedLocationId on a postback event and at the same time you are trying to retrieve its value on the first load. SelectedLocationId will be null all right.
Try:
protected void Page_Load(object sender, EventArgs e)
{
if (locationSelector != null)
Response.Write(locationSelector.SelectedLocationId);
}
I use the following MSDN code on my master page to detect if the browser accepts cookies:
protected void Page_Load(object sender, EventArgs e)
{
if(!this.IsPostBack) {
if(Request.QueryString["CookieTest"] == null) {
Response.Cookies["TestCookie"].Value = "Test";
Response.Redirect("CookieCheck.aspx.redirect=" + Server.UrlEncode(Request.Url.ToString())));
}
else if((string)Request.QueryString["Test"] == "passed") {
// my stuff...
}
}
}
The CookieCheck.aspx contains the following:
protected void Page_Load(object sender, EventArgs e)
{
if(Request.Cookies["TestCookie"] == null)
Response.Redirect(Request.QueryString["redirect"] + "?Test=notPassed", true);
else
Response.Redirect(Request.QueryString["redirect"] + "?Test=passed", true);
}
Within the web.config i have defined the following:
<customErrors mode="On" defaultRedirect="Error.aspx" />
Now the recognizing of the cookies works well, but I have this problem: Whenever an error occurs on the page and I should be redirected to Error.aspx (and this worked before the whole cookie detection thing), the redirection seems stuck in an infinite loop and appends more and more "?Test=passed" to the URL. I should mention that the Errors.aspx also has the same masterpage and thus also performs the cookie check. However I have no clue why the redirection doesn't stop. Is there a way to solve this problem other than to exlude the Errors.aspx page from having the master page? Thank you very much.
If the CookieCheck.aspx page also uses the same Master page it will keep redirecting recursively, make sure that CookieCheck.aspx is not using the same MasterPage.
I'd rather recommend not using MasterPages for this, Master Pages by design are for Visual Inheritance not code Inheritance, if you wish to make some special type of pages that checks for the the browser ability to use cookies, you can have a new base class for these pages
public abstract class CookieEnabledPage : Page
{
}
and add your logic to this class, then whenever you need to make a new page with this behavior you inherit from this base class. I think this is a much cleaner way of doing what you want.
I guess the masterpage (or the combination masterpage-error.aspx) is raising an exception which triggers a redirect to error.aspx, which in turn causes the masterpage to restart its lifecycle and raise a new exception. The concatenation of "?Test=passed" is almost certainly a side effect of reinvoking the cookie test every time an error redirect occurs.
I suggest firing up the debugger and setting a breakpoint at Page_Load in Masterpage.aspx.cs and step through until you are redirected to the error page (the last line which gets execued is the one raising the exception).