How to suppress Indy IdHTTP error message box? - indy

I have an IdHTTP component and when I get a HTTP error (for example 404) Indy shows a message box. I want to handle this "silent" and prevent Indy from showing this.
I have not found any parameter to turn this off. Any ideas?

Indy does not display message boxes. It throws exceptions. There are default exception handlers inside the VCL/FMX framework that will display a message box to the user if an exception is not caught in your code. So simply catch the exception in your code, eg:
try
{
IdHTTP1->Get(...);
}
catch (const Exception &)
{
// do something...
}
If you need finer control over the exception filtering, all Indy-specific exceptions are derived from EIdException, and there are many descendants (like EIdHTTPProtocolException), eg:
try
{
IdHTTP1->Get(...);
}
catch (const EIdHTTPProtocolException &)
{
// an HTTP error occured, do something...
// details about the HTTP error are in the exception object
}
catch (const EIdException &)
{
// a non-HTTP Indy error occured, do something else...
}
catch (const Exception &)
{
// some other error occured, do something else...
}

Related

Guidewire Exception handling in UI

when internal Guidewire code throws an exception you get a nicely formatted error message box. However, when custom code throws an exception you are directed to the error page (with the red stack trace text & back to application button). Is there anything in the Guidewire framework to make proper UI handling of errors nicer?
such as: < TextBox value="user.someMethod()"/>
//someMethod code...
try{
return user.someOtherCode()
}catch(e : Exception){
//TODO: gracefully display erorr mesage on page
//e.g. showErrorMessage()
return null
}
You have a simpler way to do this,
The below piece of code can be written in helper class or any Enhancement or even in PCF code tab, this will return a nice formatted error message.
gw.api.util.LocationUtil.addRequestScopedErrorMessage("Your error message")
After some searching through Guidewire OOTB code UserDisplayableExceptions are what you need - answering myself in case someone else has this thought.
function goToPolicy(bulkDocumentDownload : BulkDocDownload_Avi) {
try {
throw new IndexOutOfBoundsException("Ops! some index out of bounds exception was thrown")
} catch (e : Exception) {
throw new com.guidewire.pl.web.controller.UserDisplayableException(e.Message)
}
}

Suppress error message at DoDataExchange

I want to suppress the MFC error message on data validation:
void CMotorView::DoDataExchange(CDataExchange* pDX)
{
DDX_Text(pDX, IDC_AMBIENTTEMP, m_pSet->m_AmbientTemp);
}
If the text in editcontrol IDC_AMBIENTTEMP is non numeric on saving data to variables, the framework will show a messagebox prompting the user to enter a number. I want to suppress this message, and handle the error in my own code.
I assumed the framework will throw an exception in case of validation error, but this appears not to be the case. Neither does DDX_Text return a value What am I doing wrong?
void CMotorView::DoDataExchange(CDataExchange* pDX)
{
try
{
DDX_Text(pDX, IDC_AMBIENTTEMP, m_pSet->m_AmbientTemp);
}
catch(CUserException* ex)
{
// nothing caught here
}
catch(...)
{
// nothing caught here either
}
}
In case of an error DDX_Text first displays an error dialog, then it throws an exception. You can catch this with catch(CUserException *e). Please note that a pointer is thrown!
I'd suggest that you either DDX_Text to a string. This does not fail and you can then check if the string is really a number. Or you can write your own DDX_TextMyFn to do what you want. You can use the MFC original function as a base implementation.
Set ES_NUMBER as a style for the edit control. This will reduce errors user can make.
The message boxes inside the DDX routines can't be suppressed or redirected.
Here is some pseudocode that uses a class CEditInt that has a member unction GetValue/SetValue.
You can also write a DDX_EditInt routine that works on a CEdit control and use Get/SetDlgItemInt.
void AFXAPI DDX_EditInt(CDataExchange* pDX, int nIDC, int &iValue)
{
// Get pointer to control
HWND hWndCtrl = pDX->PrepareEditCtrl(nIDC);
CEditInt *pWnd = (CEditInt *)CWnd::FromHandle(hWndCtrl);
// Must be an CEditInt
ASSERT(pWnd->IsKindOf(RUNTIME_CLASS(CEditInt)));
// get the information from the defined window
if (pDX->m_bSaveAndValidate)
// Get the Value
iValue = pWnd->GetValue();
else
pWnd->SetValue(iValue);
}

Unable to throw httpResponseException

When I try to throw the below forbidden ResponseException from my controller. An exception stating "Processing of the HTTP request resulted in an exception. Please see the HTTP response returned by the 'Response' property of this exception for details." is catched in the catch block of the controller method. Need help in resolving this
throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.Forbidden));
Just change your controller implementation to re-throw if it's an HttpResponseException:
try
{
// action implementation
}
catch (Exception e)
{
if (e is HttpResponseException)
{
throw e;
}
// error handling logic
}
But the better answer is that #1 - you should avoid be catching all exceptions, that's bad practice. And #2 - you should use an exception filter instead to do your error handling and not catch exceptions yourself.

Log to Elmah in async Task

I need some Elmah logging in a async task executing on my webserver. But when I try to log the error it fails because of the HttpContext.
var httpContext = HttpContext.Current;
Task.Factory.StartNew(() =>
{
HttpContext.Current = httpContext;
try
{
//Execute some code
}
catch (Exception ex)
{
//Generate some error for the user and log the error in Elmah
try
{
ErrorLog.GetDefault(HttpContext.Current).Log(new Error(ex));
}
catch(Exception ex)
{
}
}
});
To get the progress for the task I implemented some polling mechanism. Currently none of the errors are logged to Elmah which make it difficult to solve them.
Also providing the context as parameter doesn't work.
It doesn't work. I get an ArgumentException telling me the expected value doesn't fall within the expected range. With the following stacktrace:
at System.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal(Int32 errorCode, IntPtr errorInfo)
at System.Web.Hosting.IIS7WorkerRequest.GetServerVariableInternal(String name)
at System.Web.HttpRequest.AddServerVariableToCollection(String name)
at System.Web.HttpRequest.FillInServerVariablesCollection()
at System.Web.HttpServerVarsCollection.Populate()
at System.Web.HttpServerVarsCollection.Get(String name)
at Elmah.ErrorLog.InferApplicationName(HttpContext context)
at Elmah.ErrorLog.GetDefaultImpl(HttpContext context)
at Elmah.ServiceContainer.GetService(Type serviceType)
at Elmah.ServiceCenter.GetService(Object context, Type serviceType)
at Elmah.ErrorLog.GetDefault(HttpContext context)
at Bis.Utilities.Log.ElmahErrorLog.TryLogError(Exception exeption) in D:\Users\A500535\Documents\Projecten\Biobank\Bis\src\Utilities\Log\ElmahErrorLog.cs:line 13
Below is one ugly hack that might get the job done. Essentially, it creates an Error object on a bogus Exception (the prototype) so that the context can be captured while the request is still in flight. Later, when the task started as a result of the request fails, another Error object is created off the actual exception that occurred and then the interesting and contextual bits are selectively copied off the earlier prototype. Unfortunately, the prototype Error has to be created whether or not an exception will occur.
// Create an error that will capture the context
// and serve as a prototype in case a real exception
// needs logging
var prototype = new Error(new Exception(), context);
Task.Factory.StartNew(() =>
{
try
{
// Execute some code
}
catch (Exception ex)
{
// Generate some error for the user and log the error in ELMAH
try
{
// Create a new error without contextual information
// but then copy over the interesting bits from the
// prototype capture at time of request.
var error = new Error(ex)
{
HostName = prototype.HostName,
User = prototype.User,
};
error.ServerVariables.Add(prototype.ServerVariables);
error.QueryString.Add(prototype.QueryString);
error.Cookies.Add(prototype.Cookies);
error.Form.Add(prototype.Form);
ErrorLog.GetDefault(null).Log(error);
}
catch(Exception)
{
}
}
});
When you start a new thread it doesn't get the HttpContext structure. Since Elmah logging requires the HttpContext data, it will fail.
See the following QA:
Elmah Does not email in a fire and forget scenario
for me this worked in a async task called with Task.Run:
Elmah.ErrorLog.GetDefault(null).Log(new Elmah.Error(new NotSupportedException("elmah logging test")));

Getting an Unhandled Exception in VS2010 debugger even though the exception IS handled

I have an issue with VS2010 where the debugger stops with an Unhandled Exception. However, the exception is definitely handled. In fact, if I put code in the catch block, I'll hit it when I press F5. In Debug -> Exceptions, I definitely do not have the "Thrown" checkbox checked, so IMO there is absolutely no reason for the unhandled exception dialog to pop up...
I can't post the exact code, but will work on a sample soon. The basic idea behind the offending code section is that I have a thread that talks to hardware, and if I have an error talking to it, then I throw a HardwareException. The thread is launched with BeginInvoke, and the exception is caught in the callback handler when I call EndInvoke.
When the exception is thrown in the debugger, I get a messagebox that says 'HardwareException not handled by user code". But it is!!!
EDIT -- Well, this is driving me crazy. I've got sample code that is representative of the code I have in my application, and it looks like this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Remoting.Messaging;
using System.Threading;
namespace ConsoleApplication1
{
public class HardwareException : ApplicationException
{
public HardwareException( string message) : base(message) {}
}
class Program
{
delegate void HardwareTestDelegate();
static void Main(string[] args)
{
HardwareTestDelegate d = new HardwareTestDelegate( HardwareTestThread);
d.BeginInvoke( HardwareTestComplete, null);
while( true);
}
static void HardwareTestThread()
{
throw new HardwareException( "this is a test");
}
static void HardwareTestComplete( IAsyncResult iar)
{
try {
AsyncResult ar = (AsyncResult)iar;
HardwareTestDelegate caller = (HardwareTestDelegate)ar.AsyncDelegate;
caller.EndInvoke( iar);
} catch( Exception ex) {
Console.WriteLine( "Should see this line without getting an unhandled exception message in the IDE");
}
}
}
}
I throw my HardwareException from the thread, and then handle the exception when EndInvoke is called. I guess Murphy was right, because when I run this sample code, it does what I expect -- i.e. no unhandled exception error message pops up in the IDE!
Here is the response from Microsoft, case 111053102422121. Allen Weng writes the following:
Analysis:
For your information, CLR will re-throw the exception inside the callback when you call EndInvoke(). Below is a simplified version of EndInvoke():
public object EndInvoke(IAsyncResult asyncResult)
{
using (new MultithreadSafeCallScope())
{
ThreadMethodEntry entry = asyncResult as ThreadMethodEntry;
............
if (entry.exception != null)
{
throw entry.exception;
}
}
}
The exception will be handled in the call back function or in the asynchronous method if an exception handler is provided. This is how it works without a debugger attached.
When you run it in VS.NET, the debugger seems checking only the presence of the exception handler in the asynchronous method. If there is no such handler, the debugger would think the exception is not handled and pop up an error message notifying you of this.
Suggestion:
The application should work as expected when you run it stand alone. If the error message is annoying in debugging for you, you can disable it by unchecking “User unhandled” for “Common Language Runtime Exceptions”in the Exception dialog box (Debug|Exceptions or press CTRL+ATL+E). Or you can add try/catch in the asynchronous method. In the latter case, the exception is set to null and won’t be re-thrown in EndInvoke().
I'm having this same problem, so I'll post this possible workaround for posterity's sake:
In your code that throws an exception into the .NET code (HardwareTestThread() in the example above,) catch the exception that's being thrown and wrap it in some esoteric .NET exception type for which you can disable the "user-unhandled" option in the Debug>Exceptions dialog. For my case, I needed to allow an IOException to propagate through some .NET code back to my code, so I just caught the IOException and wrapped in an AppDomainUnloadedException before letting it propagate through the .NET code back to my catch block. I chose AppDomainUnloadedException because user-unhandled is unchecked for it by default and it's in the System.dll assembly, so it was already being imported in my project, though any exception should work, so long as you disable the "user-unhandled" option for it and you don't care that the debugger won't break on that type of exception in the future.
Here's my code that wraps the IOException I was needing to propagate:
public override int Read(byte[] buffer, int offset, int count)
{
try { return innerStream.Read(buffer, offset, count); }
catch (IOException ex) { throw new AppDomainUnloadedException("Exception from innerStream: " + ex.Message, ex); }
}
And here's my code where I'm catching it on the other side of the .NET code it needed to propagate through:
try { bytesRead = sslStream.Read(buffer, offset, count); }
catch (Exception ex) { /* ex handled here. */ }

Resources