I think error handling is a good idea. :) When debugging it can get in the way - especially with nice user friendly messages. In VB6 I could just check a box for the compiler to ignore my error handling. I found the dialog that allows me to do something similar in VS, but it's about 10,000 check boxes instead of one - which is too many to change every time I want a production compilation.
Is there a way to set VS up so when I am in debugging mode I get one set of conditions and when I am in production I get another? ...or is there just another method to handling errors and debugging more efficiently?
Thanks
Try the Debug Menu and look at Exceptions. You can set it to automatically break when an exception is thrown.
In code, I'd probably just do something like:
#if !DEBUG
try {
#endif
DoSomething();
#if !DEBUG
} catch (Exception ex) {
LogEx(ex);
throw new FriendlyException(ex);
}
#endif
Or. more generally and with less #if:
#if DEBUG
public const bool DEBUG = true;
#else
public const bool DEBUG = false;
#endif
try {
DoSomething();
} catch (Exception ex) {
if (DEBUG) throw;
LogEx(ex);
throw new FriendlyException(ex);
}
Or, general purpose (like the Exception Handling library from P&P):
bool HandleException(Exception ex) {
return !DEBUG;
}
But, if your real problem is just the Visual Studio GUI - just use a macro.
You can add this attribute to your methods:
[Conditional("DEBUG")]
You can also use #if #endif statements if you wish.
Related
I've been trying to get a build archived for IOS by using Visual studio and the "Pair to mac" functionality.
However, when I try and do a release build, I get this error:
Error processing the method 'System.Void ProjectName.iOS.Renderers.IOSWebViewRenderer::.ctor()' in the assembly 'TextFlowMobile.iOS.exe': Object reference not set to an instance of an object TextFlowMobile.iOS
My code for this renderer, that is for WKWebView is as follows:
namespace TextFlowMobile.iOS.Renderers
{
public class IOSWebViewRenderer : WkWebViewRenderer
{
public override WKNavigation LoadHtmlString(NSString htmlString, NSUrl baseUrl)
{
try
{
if(htmlString != null && baseUrl != null)
{
// Add additional HTML to ensure fonts scale correctly and don't appear extremely small and almost unreadable
var iOSHtmlWithScaling = htmlString.ToString().Insert(0, "<meta name='viewport' content='width=device-width,initial-scale=1,maximum-scale=1' />");
return base.LoadHtmlString((NSString)iOSHtmlWithScaling, baseUrl);
}
else
{
return base.LoadHtmlString(htmlString, baseUrl);
}
}
catch (Exception)
{
//System.Diagnostics.Debug.WriteLine(ex);
return base.LoadHtmlString(htmlString, baseUrl);
}
}
}
}
As you can see, I don't override the constructor at all. I really don't see why this happens, especially since it builds (and deploys on a simulator on the connected mac) perfectly fine for debug.
My current config is Release | iPhone | ProjectName.iOS | Remote Device
I really appreciate any help!
This error occurred because I had an Obfuscator running on the release version of the code. When I tried to archive this, I imagine it couldn't properly compile this renderer because it was obfuscated.
My intention is to log an error(I am using Log4Net) when an exception is caught and redirect to a pretty looking page with some error message. I have a class that returns a Type T object , mostly a DataSet.
In my Catch statement I wrote this, it works but I am not sure if there's a more appropriate way of handling, can someone please advice. Thanks. Note that the throw cannot be omitted because the class has a return type.:
catch (Exception ex)
{
log.Error(ex);
HttpContext.Current.Response.Redirect("~/errorPage.aspx");
throw ex;
}
It depends upon how you want to handle error on the page, In general , unhandled exception should be bubbled up to application_error in gloabl.asax file to it generic.Here is one simple way to handle this error.
void Application_Error(object sender, EventArgs e)
{
// Code that runs when an unhandled error occurs
// Get the exception object.
Exception exc = Server.GetLastError();
// Handle HTTP errors
if (exc.GetType() == typeof(HttpException))
{
// The Complete Error Handling Example generates
// some errors using URLs with "NoCatch" in them;
// ignore these here to simulate what would happen
// if a global.asax handler were not implemented.
if (exc.Message.Contains("NoCatch") || exc.Message.Contains("maxUrlLength"))
return;
//Redirect HTTP errors to HttpError page
Server.Transfer("HttpErrorPage.aspx");
}
// For other kinds of errors give the user some information
// but stay on the default page
Response.Write("<h2>Global Page Error</h2>\n");
Response.Write(
"<p>" + exc.Message + "</p>\n");
Response.Write("Return to the <a href='Default.aspx'>" +
"Default Page</a>\n");
// Log the exception and notify system operators
ExceptionUtility.LogException(exc, "DefaultPage");
ExceptionUtility.NotifySystemOps(exc);
// Clear the error from the server
Server.ClearError();
}
Some scenarios to ponder. There is a legacy code which has following implementation Example1 and Example2. If we try to implement MSDN recommendation then the legacy code fails.
Here is a Legacy code example:
Example 1:
void Page_Load() {
.... some code
if(condition) {
/// some condition
} else {
RedirectPage(url);
}
// another code block
// some other conditions.
}
Example 2:
a. File1.ascx
void Page_Load() {
try {
.. some code
base.CheckPreference();
RedirectPage(defaultPage);
}
catch(Exception ex) {
ExceptionHandling.GetErrorMessage(ex);
}
}
b. BaseClass.cs // this is the base class
void CheckPreference() {
try {
if(condition) {
RedirectPage(url1);
} else if(condition2) {
RedirectPage(url2);
} else {
// update session
}
}
catch(Exception ex) {
ExceptionHandling.GetErrorMessage(ex);
throw;
}
}
void RedirectPage(string url) {
Response.Redirect(url);
}
One possible way is to add a boolean field in the class e.g endExecution, set the field to true whenever RedirectPage is called.
We have to update RedirectPage code see code snippet below:
// Updated code - MSDN recommendation.
void RedirectPage(url) {
Response.Redirect(url, false);
this.Context.ApplicationInstance.CompleteRequest();
endExecution = true;
}
Please suggest some other better ways to improve the legacy code implementation.
Probably the most unintuitive thing for folks issuing a redirect is that in our minds we've already returned from the method what we call Respond.Redirect (or whatever the equivilent is in your language/platform of the day. All we've done is call a method.
Bottom line is that you have to stop processing the request to avoid trying to commit to responses for the same request. That would throw an exception on just about any platform I've worked with.
ASP.NET MVC improved this with the ActionResponse so that you are returning from the method (and terminating the remainder of request processing) with code that looks like this:
return Redirect(url);
Bottom line is that you need to get in the habit of returning from your event right after you perform your redirect. Any deviation from that habit needs to be documented in the code why. This will help make the application perform the way you expect.
The approach that you've taken is perfectly reasonable.
What's the correct way of ignoring ThreadAbortException when logging exceptions?
Is it safe to just catch it in an empty catch block to make it disappear?
If you need to stop a ThreadAbortException propogating further up the call stack, you can call Thread.ResetAbort. So try something like:
try
{
// some code
}
catch (ThreadAbortException ex)
{
// do some logging
Thread.ResetAbort();
}
As for "correct" - that depends on your usage scenario. I'd generally be cautious about catching these unless you understand exactly why it has been raised. In escence it is a "stop now, quickly, and drop what you are doing" signal. Resetting it and going on to do further processing should be done with caution.
Employ two catch blocks: one for ThreadAbortException and one for the rest, for example:
void MainLoop()
{ bool workdone;
try
{ while( IsWorking ) // cross-thread volatile variable
{ workdone = Process();
if( !workdone )
{ Thread.Sleep( 500 ); }
}
}
catch( ThreadAbortException )
{ // Forced termination. Exit silently.
}
catch (Exception e)
{ LogError( e ); }
}
It is safe to catch it in a separate catch block. As an alternative you can catch all Exceptions and then check if a given Exception e is ThreadAbortException
I leave this post just because of the comments. Obviously, I was not knowing much about that exception.
With newer .NET versions ignoring an exception can be simplified to
try
{ // ...
}
catch (Exception e) when (!(e is ThreadAbortException))
{ LogError( e );
}
But this might still not be enough. Some libraries tend to wrap all exceptions with their own exception. In this case it could happen that the ThreadAbortExceptiononly appears as InnerException. I would not call it best practice to wrap a ThreadAbortException but it is real world.
To come around this I recommend an extension:
public static bool IsThreadAbort(this Exception ex)
{
while (ex != null)
{
if (ex is ThreadAbortException)
return true;
ex = ex.InnerException;
}
return false;
}
Now you can check with:
catch (Exception e) when (!e.IsThreadAbort())
{ LogError( e );
}
I'm a little bit stuck with a asp.net project that i'm doing! I have got a class that is called from the code behind and many of its function have no return type ie, being void. How does one do exception handling then??? Also, if the function within the class does have a return type of, for instance, a dataset how would one then return an exception or indicate that an exception had occured? I have attached the following code from my class which is referenced from the code behind.
public void fnRecord(string []varList, string fnName)
{
try
{
String x;
StringBuilder SQLParameters = new StringBuilder();
SQLParameters.AppendLine("SELECT #{Function}(");
{
SQLParameters.Replace("#{Function}", fnName);
}
for (int i = 0; i < varList.Length; i++)
{
x = varList[i].ToString();
SQLParameters.Append("'" + x + "',");
}
SQLParameters.Remove((SQLParameters.Length - 1), 1);
SQLParameters.Append(")");
string SQLCMD = SQLParameters.ToString();
conn.Open();
NpgsqlCommand command = new NpgsqlCommand(SQLCMD, conn);
Object result = command.ExecuteScalar();
}
catch (NpgsqlException ne)
{
//return ne;
}
catch (Exception x)
{
//error code
}
finally
{
conn.Close();
}
}
Any help would be appreciated!
Thanks
Only catch the exceptions where you intend to handle them properly. If you want to reflect the errors in the UI, catch them at the UI. If you want to handle them and try to deal with the issue in the business logic, then catch them and handle them at that point.
By the way, your code is susceptable to SQL injection attacks. Best go learn something about parameterised queries.
You don't return exceptions. You throw them. That's the point of exceptions - you don't want exception handling cluttering your method signatures!
In your catch clauses, you don't actually do anything to handle the exceptions. Then you should not catch them at all, just let them bubble up to your code-behind, and catch them there - put a try-catch round the method call.
Alternatively, catch your SQL exceptions in your method, then throw a new exception with some sensible message, adding the SqlExceptions as the inner exception, like this
catch (NpgsqlException ne)
{
throw new Exception("Your explanatory message here", ne);
}
finally
{
...
}
Cool thanks for the answers... working with the obout library so have to try and work out their exception handling functions too.