I'd like to implement some kind of automatic "logging" in my ASP.NET MVC application when a page execution (incl. database calls etc.) takes longer than 3 seconds, and then gather some 'circumstantial evidence', e.g. which action was called, what the parameters were, session information etc. so I can then store that info for review/send it via email and so forth.
How could I do this, preferably on a global level without editing/adding code to each of my many controller actions?
BeginRequest and EndRequest in global.asax is the most basic way, record a start and end time then log from there. Another (more reusable) way may be to create your own custom provider such as demonstrated on MSDN
Start by looking at the global.asax methods that hook into the following events:
-- Application_BeginRequest
-- Application_EndRequest
Record the time in the fist, compare it to current time in the last - if it's too long log it. You can probably get the action etc from the HttpContext.Current.
Related
I've created web application that has a sub that builds a contacts list. This sub fetches phone numbers and email address from a contacts db based on ids that are provided by a user. At it's fastest, the application will process about four ids per second. With 200-300 ids at any given time, the completion time is long.
Time is not really the problem, it's end user status updates. I've created a very crude web service that reads the "CurrentRecordNumber" that is stored in a session variable as the app loops through the ids. I intend to use javascript to call the webmethod from the app periodically to update status.
My problem is that when debugging, the webmethod call will complete successfully, but not until the app is finished processing.
This seems like a very simple problem. I must not be using the right terms because my results seem overly complicated.
I'm very new to asynchronous features of ASP.NET so please forgive. I have, however, written some Winforms that incorporate multiple threads so I have a basic understanding of threading.
This is due to the way ASP.NET treats session. You haven't said whether you are using webforms or MVC, but MVC has a quick workaround for this.
First, the problem:
SessionState is designed to be accessed by one request at a time, in the order received by the server. Think of this as a queue at the bank with only one bank teller available. The first person in line is the first to be helped (though this is on a per-session basis, not a per-user).
ASP.NET locks all other requests that require SessionState from executing until the previous one is done.
I haven't tried to correct this problem in web forms, but the easiest way I know of would be to not require SessionState on your progress check.
In MVC, there's a SessionState attribute that can be applied to the controller or method, indicating that there's no chance of a call to that method overwriting SessionState. As long as your call is read-only, you can make your controller code use this attribute to allow multiple async requests simultaneously:
<SessionState(SessionStateBehavior.ReadOnly)>
Public Class MyController
I need to check some stuff (Cookies) for each request coming to my application.
In ASP.NET we've used HttpModule for this task , the question what should be used in MVC ? Some Global Filter , or I can Use HttpModuler as well, is there Any difference in Request PipeLine between MVC and regular ASP.NET ?
MVC is an abstraction over ASP.NET and therefore their "hooks" really depend at which level you want to inject your logic. An action filter will allow you to hook into MVC specific events:
OnActionExecuting – This method is called before a controller action is executed.
OnActionExecuted – This method is called after a controller action is executed.
OnResultExecuting – This method is called before a controller action result is executed.
OnResultExecuted – This method is called after a controller action result is executed.
Whereas an HttpModule only allows you to hook into ASP.NET (upon which MVC is built) specific events:
BeginRequest - Request has been started. If you need to do something at the beginning of a request (for example, display advertisement banners at the top of each page), synchronize this event.
AuthenticateRequest - If you want to plug in your own custom authentication scheme (for example, look up a user against a database to validate the password), build a module that synchronizes this event and authenticates the user in a way that you want to.
AuthorizeRequest - This event is used internally to implement authorization mechanisms (for example, to store your access control lists (ACLs) in a database rather than in the file system). Although you can override this event, there are not many good reasons to do so.
PreRequestHandlerExecute - This event occurs before the HTTP handler is executed.
PostRequestHandlerExecute - This event occurs after the HTTP handler is executed.
EndRequest - Request has been completed. You may want to build a debugging module that gathers information throughout the request and then writes the information to the page.
So it really depends on when you need to hook in your event and which events you need.
If the HttpModule worked well for you before then it will continue to with Mvc.
The other parts of your question are quite broad in scope and think you'd be as well reading a good article on asp.net-mvc pipeline and extensibility.
I've done similar things using a global action filter. It works quite well, and keeps your code integrated within your application.
An HTTP module works as well, of course, but this will mean seperating the code from your main application and maintaining it seperately. Unless your code spans multiple sites or is used in multiple applications, or needs to work with web forms sites, then I would use a global filter.
Can you give an example of what might be best suited to place in the Application_Start and Session_Start subroutines?
I know when each subroutine is called.
Application_Start when the first user first accesses the web application.
Session_Start when a user opens a session with the application.
But what code belongs in each of these subroutines. What should the code in each subroutine do?
Just any examples? Well, in an MVC site the routes are registered in Application_Start. That's also a good place to initialize an IoC container such as StructureMap. Maybe initialize some singletons you have in your application if you want them to be readily available rather than late-bound when a user accesses them (like if they have a high initialization cost and you'd rather do one slow initial hit on the website yourself than bother a customer or two with it).
Session_Start is generally used less often, but could be a good place for per-user (or per-session, realistically) tracking of some kind.
Application_Start is often used to initialize application wide settings which need to be done once per application domain like registering object containers, reading some config initialization values, ... In Session_Start you could place some code which is tied to the specific user who started the session.
Be careful with exception handling in Application_Start. In IIS7 Integrated mode you won't have the response object or HTTPContext. See this thread: Request is not available in this context
I'm trying to use the HttpContext.Current.RewritePath method to serve up different versions of an application to different customers. I would love to be able to look at the HttpContext.Current.Session object to know who it is making the request. Oddly when I go to look at this at the BeginRequest handler, the Session always shows null. I've tried various other events and have had no luck. Any ideas on this?
You should look at the ASP.Net Application Life Cycle Overview and the Session State Overview pages on the MSDN.
I believe you can do what you're wanting to do by hooking into the Session_OnStart event, which is fired any time a new session is created.
I need to display an alert to a user, if they have been on my site for five minutes and have not logged in.
How do I do that?
Would I add soemthing to session on Application_Start? Is there a way to just check the length of someone's session? Perhaps put something in the header/master page and if it exceeds five minutes throw up the alert?
Any help would be appreciated.
Thank you.
EDIT ---
What I ended up doing was using the asp:Timer control found with the AjaxControlToolKit.
Application_Start fires when the IIS Application initially gets loaded.
Session_Start would fire for each new Session that gets started.
If you store the current time in the Session in Session_Start then you can check on either a page load or with an ajax call to determine if five minutes have passed without them logging in.
The answer does lie in Globals.asax, but Application_Start is not it. That is used for when the ASP.NET application actually starts.
I would add DateTime.Now to the session in the Session_Start method in Globals.asax. Then, you can either check it on each page load (for instance, in a base page or Master page's onload event), or use Ajax to poll the server.
If you truly want a 5 minute check, you need to register a 5 minute ajax callback from Session_Start. The tricky part is having a page loaded and ready that can receive it when it fires.
Polling the server with AJAX is probably the more common approach.