If an exception was thrown in a page, would it be possible to be handled within the masterpage (assuming it wasn't handled before?)
If a method on the master page is one in the call chain above where the exception occurs, it can be caught in it.
What are you trying to accomplish? At a guess I would say that you need to explore the creation of a base page where you have your exception handling and inherit your other pages from it.
You could add handler to Page.Error event:
protected void Master_Init()
{
Page.Error += MyErrorHandler;
}
I am not sure, that there is Master_Init method in MasterPage class, but I believe, you got an idea.
Related
I have a question about the best way of using HandleErrorAttribute in my MVC 5 application.
As we know, we can add this attribute to global filters like that:
filters.Add(new HandleErrorAttribute{View = "Error"});
This involves the app to show the 'Error' view every time when an unhandled exception is thrown in any level of app.
But, if I have some logic in another global authorize or action filter, that produces some exception, then when the exception is thrown for first time, the app tries to redirect to the Error View, again other filters begin executing and produce the same exception again, so asp.net to avoid looping terminates the app.
So what is the best way to use this HandleErrorAttribute to avoid such behavior?
Thanks!
Edit:
After some debugging I found that this is not the usual behavior of HandleErrorAttribute, so looping happens for me only when I use custom Routes f.e.
{key}/{controller}/{action}
and when some error occurs in the filter logic, then the app tries to redirect to the Error View, but again another filter logic begins to exectue and I even see an "Error" value in the {key} route parameter, so it is unwanted behavior.
When I use the default route {controller}/{action}
this doesn't happen and I get exactly to the Error View without executing any global filter logic a second time.
You should wrap your action filter logic inside a try catch, then inside the catch block, redirect to the Error view and pass the Exception.
Your only other alternative is to ditch HandleError completely and use the Application_Error event inside Global.asax to manage your error handling. That way you can redirect to your Error action inside there regardless of where the error occured.
Matt is right about global.asax... this is the example I followed
http://www.digitallycreated.net/Blog/57/getting-the-correct-http-status-codes-out-of-asp.net-custom-error-pages
Then in each view I added: Response.StatusCode = 500; or which ever other code I wanted to show back to the client.
I have a custom error handler class like this:
namespace AccountCenterUserControls
{
public class EWHErrorModule : IHttpModule
{
public void Init(HttpApplication app)
{
app.Error += new System.EventHandler(OnError);
}
public void OnError(object obj, EventArgs args)
{
Page myPage = (System.Web.UI.Page)HttpContext.Current.Handler;
ctx.Server.ClearError();
}
public void Dispose() { }
}
}
I've instantiated this error handler in my web.config like this:
<httpModules>
<!-- EWH Custom Error Handler -->
<add type="AccountCenterUserControls.EWHErrorModule" name="EWHErrorModule"/>
</httpModules>
It traps errors ok. My question is, how can I let my trapped error pages benefit from my masterpage? I can get to the individual masterpages from my page, but I'm not quite sure how I set the contentplaceholder when I am in this deep.
In ASP.NET the app error event can be raised at any point during the page life-cycle you may be executing your error handler at a time it is entirely illegal to modify the Page. If it is allowable you can attain a reference to the element you wish to modify or replace using FindControl. Again, if the timing is legal you can modify the controls collection of the control or add or remove controls from the control's control collection to achive the eventual desired rendering.
I hope my assumptions are correct about your situation If they are I did wonder why you do not simply implement Application_Error in Global.asax/.cs? This would be automatically wired to the ASP.NET application's OnError event. Inside that handler you would have references available to Request, Response, and Session.
Also, you should be aware that HttpContext.Current.Handler can and will return null at certain stages of the life-cycle. For example an error has occurred before the request is handed off to the handler like during authenticate request.
I have an intermediary class extending System.Web.UI.Page for all of my pages that require authentication. The class mostly does custom authentication handling.
When a user with insufficient access attempts to visit a page, I try to redirect the user back to the login page while preventing any further page events from being executed (ie. Page_load). The first solution that came to mind was the default implementation of Response.Redirect. Of course the downside to this is the possibility of ThreadAbortExceptions being thrown.
So my question is this: When (if at all) during the page life cycle is it actually safe to execute Response.Redirect() without ThreadAbortException ever being thrown?
public class CustomPage : System.Web.UI.Page
{
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
if (!IsValid())
Response.Redirect("login.aspx", true);
}
}
It's never "safe" if you're passing true as the second parameter - it will always throw the exception. Internally, Response.Redirect() calls Response.End(), which directly aborts the current thread.
The only "safe" way to truncate an HttpRequest without having an exception thrown is by using HttpApplication.CompleteRequest(), but this will result in further code execution in the current request.
Curious, why are you doing this yourself? If anything, you should be using one of the authentication providers (ultimately, FormsAuthentication can be customized to handle almost any scenario you can think of).
Then, you can use the authorization element in your web.config file to indicate what pages/directories are not able to be accessed by anonymous users. ASP.NET will take care of the rest, redirecting the user to the login page you specify, as well as redirecting back when the user has logged in.
If you don't want a ThreadAbort exception you should pass False to the endResponse parameter. Of course this means you have to process the rest of the page, which is hard to get right.
Unless you are doing something really stupid like holding a lock, it is perfectly safe to throw a ThreadAbort exception in an ASP.NET page.
Another option is to use a Server.Transfer. This has better performance than a redirect, but it too uses ThreadAbort exceptions.
I am currently asking myself some questions about exception handling and eventhandlers, and i hope some of you will give me some help.
I will start to explain what i would like to achieve in my c# application:
I have a top-level method (lets call it the main method). This method calls an asynchronous method (wich is called connect), which connect to a FTP server.
An EventHandler object is associated to this connection, and a "callback" method is called when the connection is successful.
I want to handle exceptions that can be launched during the whole process. So i would like to catch it in the top level method. It works fine for exceptions launched by the connect method (which is called inside the top level method).
However, it does not work for exceptions called inside the "callback" method: the top level method does not catch them and the execution fails.
What can I do to make these exceptions beeing caught by the top level method ? I don't want to handle these exceptions in the callback.
Take a look at how the Backgroundworker deals with this: the Exception is propagated to the Completed event handler.
I assume you have some form of State object that is passed to/from the delegate, that's where you can add such a property. And you will have to catch all exceptions in the thread, at the outermost scope. But 'handling' just means passing it along.
There is a standard pattern for the RunWorkerCompleted event, see this MSDN page.
Consider the below code fragment for wrapping all of your code in a global exception handler:
namespace MyClient
{
class Program
{
static void Main(string[] args)
{
try
{
bool isSuccess = SubMain(string[] args);
}
catch (Exception e)
{
HandleExceptionGracefully(e);
}
}
static bool SubMain(string[] agrs)
{
// Do something
}
static void HandleExceptionGracefully(Exception e)
{
// Display/Send the exception in a graceful manner to the user/admin.
}
}
}
Also, don't forget to make your error handling user-friendly.
There is an event handler in the Application class called ThreadException. This event will be fired whenever an exception is thrown an not caught anywhere in the current call stack.
Edited:
Sorry, I misread the question - I didn't realise that the "main" method in your example isn't the actual main method. In that case you may want to catch the exception inside the callback, but not handle it - instead simply pass it back up to the main method as part of the event args.
The BackgroundWorker in Winforms does something similar.
Thanks for your answers.
It seems that using the BackgroundWorker solve this problem.
I did not try it, because i chose to avoid this implementation burden. So I took away my asynchronous call and made my application behaving synchronously.
One tip for people using the Compact Framework instead of the full .NET Framework:
the BackgroundWorker is not available in CF, but a similar solution is provided by OpenNETCF (see the BackgroundWorker class in the Smart Device Framework).
A more convenient way to deal with this problem of top-level exception handling is to use delegates.
These c# delegates allow to call methods in a asynchronous way. And delegates allow also top-level exception handling. Indeed, exceptions thrown inside delegates are re-thrown on the original thread.
I don't know why i did not think about delegates before.
I hope it will help.
See these nice articles about delegates:
Article 1
Article 2
The questions says everything, take this example code:
<ul id="css-id">
<li>
<something:CustomControl ID="SomeThingElse" runat="server" />
<something:OtherCustomControl runat="server" />
</li>
</ul>
Now if an error gets thrown somewhere inside these controlls (that are located in a master page) they will take down the entire site, how would one catch these exceptions?
You can catch all exception not handled elswhere in the Global.asax page / class.
Look at:
protected void Application_Error(Object sender, EventArgs e)
method.
Unfortunately an unhandled exception will always error your site.
YOu can prevent this a few ways though.
Use the section in your web.config to show a user friendly message
In your Global.asax - or a Custom Handler - catch your unhandled exception and react accordingly - like this
best solution
Make sure you controls don't throw unhandled exceptions!
Add a global.asax en implement the Application_Error handler. Use the Server.GetLastError() function to get a handle on the exception thrown.
Using the global.asax Application_Error method, as described in How to create custom error reporting pages in ASP.NET by using Visual C# .NET.
An alternative approach would be to use a HTTP module; this gives you some more flexibility (you can handle errors from multiple applications, for example).
Do you want to catch the exception and handle it?
Or do you want to prevent the Yellow Screen Of Death? If you are trying to prevent the Yellow Screen Of Death, look at handling the Error event on the HttpApplication (in other words, in your Global.asax).
See the following MSDN page for more details:
http://msdn.microsoft.com/en-us/library/system.web.httpapplication.error.aspx
Specifically this paragraph:
The exception that raises the Error event can be accessed by a call to the GetLastError method. If your application generates custom error output, suppress the default error message that is generated by ASP.NET by a call to the ClearError method.