Easy way to implement universal error handling in ASP.Net application - asp.net

Folks,
I have an application that is primarily one page with a lot of user controls and custom controls. ASP.Net WebParts are being used. There is almost no code in the web page and its master page: it's all in various components.
The design requirements include an error message display panel. The client would like the app to display any errors occurring in any part of the app on the error message display rather than going to a custom error page. (This was a recent decision: when we started we were thinking custom error page.)
As far as I can tell, WebParts don't provide any default error handling (no capture of errors and displaying of messages) and user controls don't necessarily fire their OnError event when an internal error occurs.
So I'm looking at wrapping absolutely everything in Try ... Catch blocks, at least at the presentation level, and doing the handling. So my question is: is there any easy way to implement a kind of global, or at least class-wide, error handler, that will handle an error in the way I choose, interrupt the routine that was executing, but return (after handling) to the caller of the method that failed?
I'm willing to adapt code to verify that subroutines did what they were supposed to and returned appropriate values (ex: non-null data objects.) What I don't want is for the whole process to be aborted up to the very top, with rendering skipped, or (of course) the famous yellow and white screen.
I guess this is a case for aspect-oriented programming, but I don't think ASP.Net provides anything like that yet. I didn't get the impression that EntLib 5.0 did, either.
I would adore it if it were possible to decorate a method with an attribute that meant "On error call such-and-such a static method of such-and-such a class". But I doubt it is, yet.
Any suggestions are welcome.
Thanks,
Ann L.

For starters, it's bad practice to put Try Catch handlers around every piece of code in your application. There is a slight performance hit every time you set that up, and this could slow things down really fast.
In your Global.asax.cs (or .vb) file, there is a method in there called Application_Error which is the global error handler. This will catch any error you haven't previously caught (or thrown up) within the application.
You could easily put your error handling code here. It could be as simple as dumping the error message to a log for future review, or check for the exception type (SQL vs. File vs. HTTP) and do the error handling task related to the type.

You need to take a look at elmah. If you google 'elmah' it has an error module/handler that does pretty much what you are looking for (although it will take some extra tweaking..)
You might want to consider letting your errors 'bubble up' though.. There are some serious performance issues with writing a bunch of Try..Catch..Finally blocks...

Related

Caliburn Micro - is it possible to intercept calls to execute a command?

I want to add error handling to my view-models so that when a command is executed and an exception thrown, the error is handled gracefully and a modal dialog displayed.
I've got this working but my approach is a too wordy. Errors are trapped within a command and then published via an IObservable. A behavior subscribes to the errors - creating an appropriate view model and passing to the WindowManager. While it works, I'd prefer something more declarative.
Instead I want to decorate or intercept calls to commannds (bound to a button) and provide generic error handling. The try-catch might call out to a method on the view model or command that is decorated with a Rescue attribute.
I understand this is possible within Caliburn but can it be done with Micro? Perhaps there's an alternative approach?
Have a look at this question I asked on SO and subsequently answered with help via the CM codeplex forum.
I slightly modified the RescueAttribute of this CM filters implementation to allow the error handling routine to be executed as a coroutine.
This in combination with the ShowModal IResult available in some of the samples should get you what you want.

asp.net mvc C# file upload value persistance

i am using file upload on the user front. is there any way if some exception occurs the html file control is able to persist its value on post back(i know it can't) but any work around?. i am using server side validations.
This could get messy.
Just a couple of points,
If an exception occurs do you really think it is wise to save the file?
By its nature an exception is telling you an error has occurred and processing should not continue. I would think the only time you should save the file is when you can recover or handle the exception without any side affects.
In which case you have to ask yourself, can you not just prevent the exception in the first place?
Always, always do validation on BOTH client and server side.
Why? Well to prevent this sort of thing, at least as much as possible. Let the user know there is a problem before posting, much better experience for them.
It terms of the problem, the best thing you could do is potentially keep the file path, and if an error occurs put that value back into the input box.
This wont be pretty, the input type for files is one of those special cases where the browser is responsible for a lot of the user interaction.
Remember in most cases what is happening is the browser is collection the byte information from the file and passing that around as part of the request, this is not something you are going to be able to manipulate easily.

Problems with ASP.NET Session State / NInject / OnePerRequest behavior

This is quite a lengthy post, so bear with me. I'm not sure whether it is primarily about ASP.NET Session State behaviour, NInject, application design, or refactoring. Read on and then you can decide... :-)
Background
First, a bit of background. We are working on trying to refactor a large webshop into a more maintainable , structured design. The webshop is currently running on .NET 3.5, but the design is more of a hangover from the classic ASP days. Obviously we cannot tackle everything in one go, so many of the features / technologies / approaches have to be taken as a given. With that in mind...
The app maintains everything to do with the current session (user profile, cart, session choices, etc.) in a context object which is simply a large XML document that gets serialized to and deserialized from the Session as a string. The XML format is also important because the rendering is done via XSLT.
This has led to a number of problems :
It's a kind of God object with far
too many concerns.
It's loosely typed and relies too much on XML manipulation / XPath.
There is no standard way / pattern for retrieving the session xml document or for writing it back. We have a horrible mixture of methods that take the document in as a parameter, modify it and return it, methods that retrieve it themselves, modify it and save it back to session, etc, etc. This has lead to a lot of hard to trace bugs, over-use of serializing /deserializing from the Session, etc.
Our Solution
What we have done is try to introduce a strongly -typed wrapper around the xml document, which breaks it up into different concerns and to manage the lifecycle transparently to the rest of the app.
What we are aiming for is the following workflow:
Beginning of the request, we populate
the session document from the xml
string stored in the session.
The rest of the app interacts with it
only through the strongly typed
wrapper. The whole app uses the same
instance and does not have to worry
about when to retrieve or save the
state back to session.
At the end of the request, the underlying xml document is serialized back to the Session.
Since we are using NInject(v1) as the IOC of choice, we decided to use this to manage the lifecycle of our context object. The context object was wrapped with the OnePerRequest attribute and the dispose method was hooked up to a method that would save the xml document back to Session as a string.
It doesn't work...
We soon encountered a problem that the NInject OnePerRequest module didn't appear to have access to SessionState. The first thing we tried was a hack that we would keep the Session object in a variable to make sure we could still write to it. This appeared to work on a development machine but it became obvious it didn't when moving to out of process state.
It still doesn't work...
We tried inheriting from the OnePerRequest behaviour / module, and adding the IRequiresSessionState marker interface (OnePerRequestRequiresSessionState). However, this was not enough as the method which NInject uses to release references and clean up gets hooked up to the EndRequest method. Session is available in EndRequest but it has already been serialized to the out of process state server so changing something now is not reflected when the session string is retrieved at the beginning of the next request.
We then decided to change the even t to hook up to. We ditched EndRequest and hooked up our OnePerRequestRequiresSessionState "release all" method to the PostRequestHandlerExecute event, which is BEFORE the session data gets serialized out of process.
It works... then it doesn't...
This seemed to work. On a single server and on a web farm. Then we noticed weird behaviour. There seemed to be two different versions of the context and you would randomly switch between them. Add something to the cart, it's not there. Go to browse to another product and the previous product would show up in the cart.
After some tracing, we discovered the culprit: Response.Redirect. Sprinkled throughout the site in literally hundreds of places is Response.Redirect(url);. With this version of the redirect, the execution of the page is stopped immediately. This means that PostRequestHandlerExecute is not fired and the current version of the Context object is not thrown away by NInject... and everything falls apart. New versions are not created properly, etc. EndRequest is fired which is why the normal NInject OnePerRequest module works fine with it, just not our bastardized version that tries to use session state.
Of course, there is an override to Response.Redirect where you can pass a boolean value in to tell it whether to terminate the existing page or continue to execute - Response.Redirect(url,false). Continuing obviously fires our event and everything works but... it continues to execute the rest of the page! This means executing everything that comes after the call to Redirect and we have absolutely no idea what that means (since the existing site expects it to stop).
What next?
So, any suggestions on what to do? So far we've discussed :
Abstracting our redirect behaviour
and going through a central method
that controls the redirect (perhaps
hacking out a way to call the
PostRequestHandlerExecute even t or
maybe a custom Redirect event that
our NInject module can also
subscribe to and clean up).
Seeing if there is a way we can
force the Session object to save in
EndRequest if it hasn't been saved
previously in
PostRequestHandlerExecute, and do
the ninject clean up in EndRequest
Remove our dependency on Session
completely and use another storage
mechanism: DB, document DB,
distributed HashTable, etc. Any
advice? Suggestions we haven't
thought of? Things you've tried
that have / haven't worked?
I think you're on the right track. Here's some thoughts I had:
in addition to the strongly typed wrapper you have, I'd suggest a facade for accessing the context object that returns your wrapper, something like an IContextProvider. that way you can introduce it piece-meal, and then when it's fully integrated, you can refactor the provider without breaking the things that use it. I can't tell, but you might have already done this. it'll also be easier to change your persistence mechanism if you choose to. if you can do this, I would suggest once you get all the dependencies isolated from the context object, change it to not persist as XML. the SessionState will store a binary object much faster, and you can always serialize to XML if you need to do transforms.
I don't think that Ninject is the correct mechanism for what you're trying to do. it's difficult to signal end of the request in Ninject, since garbage collection can't be depended on. have you considered using an IHttpModule instead? you can use the AcquireRequestState and ReleaseRequestState or EndRequest to handle getting/setting the context in Session. only allow the app to get to the context object through the facade.
if you're on a webfarm, you're probably using a database for your Session storage anyway, so putting your context into a DB won't be much different.
Firstly, while it's good to demonstrate you've put in the work, (and I and others may not have replied if it wasn't clear how much you're interested in a resolution)... that's a massive wall of text! Here's a +1 on your way to investing in a bonus for a complete response that talks about the Ninject ASP.NET extensions and how they apply to each individual element of your issue. Having said that, hopefully someone will come along with a real resolution for you.
Even though it's [very] 2.0 specific, Nate's Cache and Collect Post is required reading. While it seems you're pretty au fait with the tradeoffs involved and have debugged deep in, the article is well worth a few reads.
I'd also consider moving to V2 of Ninject - a lot of this stuff has been revised significantly. It's not magically going to work, but represents a mature rewrite based on a lot of learning from V1. Have you read the (V1 or) V2 unit tests for Ninject? They'll show you the low level tools at your disposal in order to realise your goals.
Bottom line for me is that you need to work out a strategy for your state management independent of DI, and then by all means use the container/DI system as a part of the implementation.

How to catch all Exceptions from a WebService?

I have a Web Reference to a remote Web Service, which is called in several different classes. I'd like to catch all exceptions coming from this Web Service only.
How can I do that (for example extending it's base, auto generated class) without interfering and modifying all upper level code?
You can't, and why do you want to? It's almost always a mistake to "catch all exceptions" or "handle all exceptions". What are you trying to accomplish?
I'd suggest you log it on the server, not the client.
What will you be doing when you hide the exception from the upper layers? Pretending it didn't happen?
It might make sense to wrap the SoapException in one of your own. Maybe. That's only because SoapException is so specific to web services. In this case, yes, you need to wrap every call in a try/catch. The best way to do this would be in a facade class, which could also have the common code for wrapping the SoapException or translating it into one of your own.
Still, unless you're ready to take control of the code generation, you'll wind up doing this by hand.

InfoPath FormControl on STA worker thread

I have a .NET class that exposes two public methods: one to create an InfoPath form and another to Export to one of the supported formats. I’m using the Microsoft FormControl to do this. It’s hosted by a Form that does not get displayed. I get called by a Winforms app, but on an MTA worker thread instead of the UI thread. So I create an STA thread and execute on that, which works exactly once and then results in this exception:
System.InvalidOperationException was unhandled
Message="Unable to get the window handle for the 'FormControl' control. Windowless ActiveX controls are not supported."
Source="System.Windows.Forms"
StackTrace:
at System.Windows.Forms.AxHost.EnsureWindowPresent()
at System.Windows.Forms.AxHost.InPlaceActivate()
at System.Windows.Forms.AxHost.TransitionUpTo(Int32 state)
at System.Windows.Forms.AxHost.CreateHandle()
at System.Windows.Forms.Control.CreateControl(Boolean fIgnoreVisible)
at System.Windows.Forms.Control.CreateControl(Boolean fIgnoreVisible)
at System.Windows.Forms.AxHost.EndInit()
at InfoPathCreateStaThreadTest.FormControlHost.InitializeComponent() in C:\Windows\Temp\InfoPathCreateStaThreadTest\InfoPathCreateStaThreadTest\FormControlHost.Designer.cs:line 65
After some experimenting, I started to suspect this is a message pumping problem. I then came across this, which makes me more strongly suspect so: http://blogs.msdn.com/cbrumme/archive/2004/02/02/66219.aspx
I tried various methods of pumping messages with no luck. I should mention that the alternative of automating the InfoPath app is not viable unless I can figure out how to hide the app.
Any help would be much appreciated.
Are you creating your worker thread (the one calling the control) after the form is loaded? I was having this problem until I moved all of my calls to the FormControl within the Load event of the parent form. Since doing that I have not come across this specific error (though I have seen many others)
I'm researching the same error and found this: http://social.msdn.microsoft.com/Forums/en-US/clr/thread/9c36e5d3-a75c-4760-9070-5dbaf188992b/ which attributes the problem to DEP being unexpectedly turned on and provides a fix. I don't know yet if this will solve my problem.
Thanks for your reply. Sorry for the long delayed reply on my end. DEP is not causing the problem for me. I ended up automating the InfoPath app vs. using the FormControl. Best of luck getting your issue resolved!
Rob

Resources