Essentially I want to be able to catch when a user lets their session timeout and then clicks on something that ends up causing an Async postback. I figured out that if I put this code in my Session_Start (in Global.asax) then I can catch a postback that occurred during a session timeout:
With HttpContext.Current
If TypeOf .Handler Is Page Then
Dim page As Page = CType(.Handler, Page)
If page IsNot Nothing AndAlso page.IsPostBack Then
'Session timeout
End If
End If
End With
This works fine. My question is, I would like to be able to inject some javascript into the Response and then call Response.End() so that the rest of the application does not get finish executing. The problem is that when I try Response.Write("<script ... ") followed by Response.End() then javascript does not get written to the response stream. I'm sure there are other places in the application that I can safely write Javascript to the Response but I can't let the rest of the application execute because it will error when it tries to access the session objects.
To sum up: I need to inject javascript into the response in the Session_Start event in Global.asax
Note: You may be wondering why I'm not doing this in Session_End...we don't use InProc sessions and so Session_End doesn't get called...but that's beside the point...just wanted to make it clear why I'm doing this in Session_Start.
Writing to the response stream outside of an HttpHandler is generally not a good idea; it may work in some corner cases, but it's not how things are intended to work.
Have you considered using either a Page base class or a Page Adapter to do this? That way, you would only need one copy of the code, and it could be applied to either all pages or just the ones you select.
Another option would be to use URL rewriting to redirect the incoming request to a page that generates the script output you need.
Related
Working in asp.net, in VB I want a site visitor to be able to see a Member's page by going to i.e. almosbarn.com/tom. I need to extract the "tom" part, look it up in the database, then open tom's webpage. The lookup, database, and view page parts work. My problem is I've tried setting it up in the global.asax application_start to get the "tom" segment but I get the error "request is not available in this context". My code to capture it in the global.aspx application_start is:
Dim vMbrID = Httpcontext.Current.Request.URL.Segments.Last()
This works and gives me "tom" on a test page, but not the global.aspx page, where I get the error.
The Application_Start event is fired when an HttpApplication instance is first created. At this point, the request information is not available; there might not even be a request in progress.
You want your code to fire at the start of a request, so move it to the Application_BeginRequest event.
What you want to do is set up routing in your global.asax to let you handle these kinds of situations.
MSDN on routing
MSDN walkthrough on routing
I have a webform that has a single page method. My other web apps log unhandled exceptions to the system event log on the web server. Since the other developers that I work with expect to see entries for app errors in the event log, I would like this app to do the same.
However, I have the app send error emails when an exception is caught from calling code inside the page method. It is not writing to the event log when this occurs. Note: the page method re-throws the exception after calling my email notification method.
From what I've read so far it seems that ASP.Net logs errors to the event log by default. I imagine that the same is not true for Page Methods/WebMethods because they basically throw the exception to the client code calling it.
Is there a trivial way to have that exception bubble up properly so that it writes to the event log? No other apps write to the event log directly from what I've seen so I don't think the application could create a new source since our security people keep a lot of things locked down (with good intentions, yay security).
[WebMethod]
public static object MyPseudoWebMethod()
{
try
{
// My exception spawning unreliable code here
}
catch(Exception ex)
{
// Cleanup ...
this.SendErrorNotification(ex);
throw; // <-- This doesn't bubble up but I'd love for it to!
}
}
Hmm interesting problem. You are right in that WebMethod exceptions do NOT follow normal exception flow.
The Application_Error event is not fired if your web method throws an
exception. The reason for this is that the HTTP handler for XML Web
services consumes any exception that occurs while an XML Web service
is executing and turns it into a SOAP fault prior to the
Application_Error event is called.
(from here)
The above page suggests using a SOAP extension to catch that exception before its swallowed, but here's how I'd do it if you don't want to do that:
1) Make a new 'error recieving' ASPX page that you will build that will take whatever params you want to record in your error log. So for example, have this page take in a POST named "ExceptionDetails" or whatever else you wish to capture. This page will NOT be viewed directly in a browser, so it doesnt need any ASPX controls or anything, but using a MasterPage on it won't hurt anything.
2) In the code behind of this new page, grab whatever POSTS you are sending in and new-up an Exception with whatever details you need. Immediate throw this exception. Doing this means that this exception will follow whatever flow other unhandled exceptions follow in the app (logging, emailing, etc).
3) On the page that calls the WebMethod JS, Wrap the calls to the WebMethod in a try-catch
4) In the catch block, print out whatever message you want in the browser, and initiate a new AJAX post to that new error receiving ASPX page, passing along whatever POST stuff you made that page look for.
The new AJAX call will NOT change ANYTHING in the user's perception by default. The AJAX call fires off a new request to that page, and the ASPX page itself is actually totally unaware that its AJAX and not a normal browser request. Any cookies/session/authentication data that's currently set are available to the AJAXed page as well, if you are recording a user's ID or anything. If you look at the returned response from a tool like Firebug, you will see that its actually the YellowScreenOfDeath's HTML (unless you have a custom 500 page, in which case its that HTML that comes back).
This is simply how the legacy ASMX web services work.
The only workaround is to stop using them (which you should do anyway, unless you're stuck with .NET 2.0). WCF doesn't have this problem.
which event is the most suitable to check for Session expired? i'm trying to trap each server request, and if Session is null, redirect to a different page.
You can determine if a new session is being created by hooking Session_OnStart - http://msdn.microsoft.com/en-us/library/ms178583(VS.80).aspx
You can handle the Session_OnStart
event by adding a subroutine named
Session_OnStart to the Global.asax
file. The Session_OnStart subroutine
is run at the beginning of a request
if the request begins a new session. A
new session will be started if a
request is made that does not contain
a SessionID value or if the SessionID
property contained in the request
references a session that has expired.
This will tell you effectively when a new session is being created, regardless of if the user just arrived or the session had expired.
It would be hard to reliably differentiate between both scenarios. I guess you could try to get a hold a the session id in the either the session cookie or embedded in the url (cookieless), but you would need to check it before getting to the above event, and later check whether the request had a session id originally. Check if you can get to the session id in the cookieless version, because it is stripped out of the urls asp.net gives you (not sure if early in the lifecycle you get to see it).
This is often best achieved by using a base Page class for all otehr classes, and implementing this in the Page_Load method.
Use BasePage class, which inherits from Page class. Let every aspx page inherits that BasePage class. In BasePage class, override OnInit event, in which you can check for Session or Cookie, and redirect user to login page (for example).
I use this approach for all mine webforms apps, because it's easy to implement and use.
I am getting a " Thread was being aborted " Exception in an ASP.NET page.I am not at all using any Response.Redirect/Server.Transfer method.Can any one help me to solve this ?
This can happen if the web app is being shut down or forcefully restarted while your code executes. I have seen this happen when your web app writes files to the web directory in which it's hosted, causing a recompile of the web app.
The bad solution is using
Response.Redirect(URL, False)
which will cause not to Response.End() current page, however be careful this might lead problems because rest of the page will get executed and might cause login bypass and similar security and performance issues.
Edit : Apparently you are not using Response.Redirect and you can't catch AbortThreadExecution with Try Catch, which means this answer is totally useless now :)
Although to able to get an answer you need to learn how to ask a question. you need to provide information such as :
Exception details
When it, what are the symptoms
What have you tried and didn't work
Have you manage the isolate the problem?
Error:
Thread was being aborted. at System.Threading.Thread.AbortInternal() at System.Threading.Thread.Abort(Object stateInfo) at System.Web.HttpResponse.End()
This error occurs mainly If You Use Response.End, Response.Redirect, or Server.Transfer
Cause:
The Response.End method ends the page execution and shifts the execution to the Application_EndRequest event in the application’s event pipeline. The line of code that follows Response.End is not executed.
This problem occurs in the Response.Redirect and Server.Transfer methods because both methods call Response.End internally.
Resolution/Solution:
You can use a try-catch statement to catch this exception
or
For Response.End, call the HttpContext.Current.ApplicationInstance.CompleteRequest method instead of Response.End to bypass the code execution to the Application_EndRequest event.
For Response.Redirect, use an overload, Response.Redirect(String url, bool endResponse) that passes false for the endResponse parameter to suppress the internal call to Response.End. For example:
ex: Response.Redirect (“nextpage.aspx”, false);
If you use this workaround, the code that follows Response.Redirect is executed.
For Server.Transfer, use the Server.Execute method instead.
I'm looking to rewrite a pretty intensive CRUD type ASP.NET page to utilize ajax calls (specifically jQuery ajax). My concern in doing this is that the user may be on this page longer than the forms authentication timeout. Because of this, I'm thinking that I should extend the forms authentication ticket with each ajax call (basically how it does in a normal web forms submit model). So the questions:
Is this even a valid concern? If so, would writing a jQuery plugin to extend the forms authentication timeout be possible? Does one already exist? Would using ASP.NET AJAX be a better approach?
Any comments\help would be appreciated.
I can confirm that making a web service or page method call through jQuery will extend an ASP.NET session expiration in the same way that a regular postback will.
I often use a five minute setInterval() to call a "keep-alive" service, which will preserve the user's session indefinitely even if they leave the application idle.
You should be able to use MS Ajax without the Script manager and use jQuery to consume the WebMethods. More info doing so here
As far as I know, calling a WebMethod will extend the user's session timeout. So this approach may be a best of both worlds.
I use this for my keepalive webservice.
Modify this to your liking and let me know if it works...
Note: session("UID") is a variable I setup at login. I name my ticket the same
<WebMethod(CacheDuration:=0, EnableSession:=True)> _
Public Function keepSessionAlive() As String
If Session("UID") Is Nothing OrElse Session("UID") = 0 Then
Throw New ApplicationException("Login")
End If
Session("lastKeepSessionAlive") = DateTime.Now
If Not (Context.Request.Cookies(System.Web.Security.FormsAuthentication.FormsCookieName) Is Nothing) Then
Dim ticket As System.Web.Security.FormsAuthenticationTicket
Try
ticket = System.Web.Security.FormsAuthentication.Decrypt(Context.Request.Cookies(System.Web.Security.FormsAuthentication.FormsCookieName).Value)
If ticket.Name = Context.Session("UID") Then
System.Web.Security.FormsAuthentication.SetAuthCookie(Context.Session("UID"), False)
Debug.WriteLine("keepAlive:AuthenticationReset")
End If
Catch ex As Exception
Debug.WriteLine("keepAlive:AuthenticationReset FAILED!!!")
Throw New ApplicationException("Login")
End Try
Else
Debug.WriteLine("keepAlive.Load: No Authentication Cookie. Error")
Throw New ApplicationException("Login")
End If
Return Session.SessionID.ToString
End Function
Use Fiddler or some other utility to see if Microsoft was smart enough to make sure the cookie gets updated between AJAX calls. You may have better luck (with regard to automatic updating of the forms auth tickeet) if you use Microsoft's baked-in asp.net AJAX (which is substantially similar).
Forms auth works via a cookie. Cookies are sent with XMLHttpRequest requests, so I don't think there's a problem here.
Note that there is an issue related to the FormsAuthTicket expiring, and being forced to redirect to login.aspx or some such. But that's an entirely different scenario than what you're talking about.
I don't think I completely understand what it is you're asking but in terms of the jquery ajax timeout, you can set the local timeout in the ajax call.
Example:
$.ajax('ajax.php',{timeout: 60000},function (data) {
alert(data);
}