Very similar to this question: Handling Exceptions in Biztalk which don't get caught by Scope shape, but yet a totally different error.
I was creating a tutorial on how to catch errors in BizTalk, and low and behold, it didn't catch my error at all. I had just shown how to use promoted fields, so I dropped a file that didn't have the element that was promoted. If I put a divided by zero ( x = x / x where x =0) in the top of "Do XPaths" expression then it catches fine.
So I know the reason for the error, and how to fix it. But I'm asking why the scope/catch didn't catch it.
Error:
Shape name: Do XPaths ShapeId: 3c3c7019-6322-4fe8-85eb-3292601c6039
Exception thrown from: segment 2, progress 2
Inner exception: There is no value associated with the property 'SchemaLesson.Airline' in the
message.
Exception type: MissingPropertyException
Source: Microsoft.XLANGs.BizTalk.Engine
Orch "Transaction Type" is "Long Running" and so is my Scope. I also tried both with "Transaction Type" set to "None", and same result.
That is because you are catching a System.SystemException rather than a System.Exception. XLang exceptions are not a member of System.SystemException but are of System.Exception. System.Exception will catch a lot more.
See also System.Exception vs System.SystemException
Related
This is what I get when I use Exception.Message :
System.Web.Services.Protocols.SoapException: The server can not process the request. ---> System.NullReferenceException: Object reference not set to an instance of an object in . in WebService.ProcessRequestArc... --- End of inner exception stack trace ---
Is it possible to configure a web application so that exceptions only send the part in bold in my example?
Or do you know of any way to extract only that part?
The Message property of an exception does not follow any pattern. In particular, the Message property will be different depending on the current culture settings (language).
But even if you are only concerned about a single language, you should never depend on anything in the Message property. It simply contains whatever the developer who threw the exception thinks you might want to see.
In particular, it does not contain anything that you should display to your users!
I didn't quite understand your problem at first. To avoid seeing the Stack Trace, you simply had have display Server.GetLastError().Message. On further examination I see that your problem is that exceptions are getting wrapped into a HttpException, and the Message from HttpException concatenates the method info with the original exception message.
Solution
In web.config you need to add a custom error section.
<customErrors defaultRedirect="Error.aspx"
mode="On" redirectMode="ResponseRewrite">
In Error.aspx you can do the following to check if it's an HttpException, and if so get the inner exception's message.
var ex = Server.GetLastError();
string message;
if (ex != null)
{
message = ((ex is HttpException || ex is SoapException) && ex.InnerException != null)
? ex.InnerException.Message : ex.Message;
}
else
{
message = "An error has occurred.";
}
Response.Write(message);
On your page you just want to show Server.GetLastError().Message.
Here is the before and after for a divide by zero error:
Before: Default.aspx(4): error CS0020: Division by constant zero
After: Attempted to divide by zero.
For SoapException to actually have the InnerException property not be null, then you need to throw a SoapException with the actual exception inside.
Here are some links from MSDN regarding the customErrors section and error handling:
customErrors Element
Complete Example for Error Handlers
I am getting the following error in Biztalk...
The value assigned to property 'https://blah.Schemas.PropertySchema:sequenceNumber' is not valid: '15'.
Error:
Uncaught exception (see the 'inner exception' below) has suspended an instance of service 'blah.Orchestrations.CommitDispatcher(3d0134b5-83b1-1fb7-c6b0-5d6fa4614373)'.
The service instance will remain suspended until administratively resumed or terminated.
If resumed the instance will continue from its last persisted state and may re-throw the same unexpected exception.
InstanceId: 4da93c1f-7303-4052-adf4-976afcdda1cf
Shape name: SetSequence
ShapeId: 3909c37f-092e-419d-864d-4a0cb5a7c03e
Exception thrown from: segment 1, progress 134
Inner exception: The value assigned to property 'https://blah.Schemas.PropertySchema:sequenceNumber' is not valid: '15'.
Exception type: InvalidPropertyValueException
Source: Microsoft.XLANGs.BizTalk.Engine
Target Site: Microsoft.BizTalk.Agent.Interop.IBTMessage PrepareMessage(Microsoft.XLANGs.BaseTypes.XLANGMessage, System.Collections.IList, System.Collections.IList)
This is the schema which I'm using to set the above long value...
<ns0:SetSequenceNumber xmlns:ns0="http://tempuri.org/">
<ns0:transactionId>transactionId_0</ns0:transactionId>
<ns0:sequenceNumber>10/<ns0:sequenceNumber>
</ns0:SetSequenceNumber>
The datatype of sequenceNumber is xs:long.
Could someone please help me understand what is going wrong.
I think this an outright bug in Biztalk (I've had this BizTalk 2009 as well)
Yossi Dahan talks about this here
The workaround I've used is just to change the type on the correlation to xs:string.
This is still a problem in BTS2016 :-(
I used nonNegativeInteger, that also works. Seams like nonNegativeInteger works with int64 variables in orchestrations.
I have a global error trap in the Application_Error method of Global.asax that writes any unhandled exception to a log file.
Is there anyway of reporting the variable names and their values as part of the exception report?
Unless you do something really tricky with Aspect-Oriented Programming, you pretty much need to make sure that you manually introduce any relevant information into the stack trace when exceptions are thrown. For example:
public void DoSomething(int number, string name)
{
try
{
...
}
catch (Exception e)
{
throw new Exception("Error occurred while doing something: " +
new {number, name}, e);
}
}
This way, the number and name will be included in the stack trace when this exception trickles up to the top level.
Edit
After reading David Stratton's answer, I felt the need to expand on this a little. I get the sense that even some very experienced C# programmers haven't learned some of the tricks that I've learned.
First of all, I wanted to point out that the exception-handling system in .NET was designed with the idea of an InnerException specifically for this purpose (providing additional information at various points of the stack trace), and it is not at all hacky to do. However, you should definitely provide the exception as the innerException constructor parameter, rather than appending e.ToString() to the new exception's message.
Secondly, based on various comments and answers I've read on StackOverflow, as well as my own experience, it's best to:
Avoid catching an exception if there's nothing specific you plan to do with it.
When you catch an exception, rethrow it unless you know why the exception was thrown and you're in a scope where you know how to gracefully retreat from what you were trying to do. Simply pretending nothing went wrong is asking for more trouble down the road.
When re-throwing exceptions, either just throw; to preserve the original exception's stack trace, or include the original exception as a new exception's InnerException.
Consistently log exceptions that don't get re-thrown. This will generally only happen at the UI level, so you can tell the user something unexpected happened rather than allowing the program to crash.
Finally, I wanted to mention that the anonymous type declaration syntax is ideal for this kind of thing because it is very concise and it will automatically produce a string that uses the given variable names and values. For example, new {number, name}.ToString() might produce "{ number = 1, name = Test }".
We do this in some cases, but in a roundabout way. We use a try/catch at the granular level and if we want to pass the exception up to the global error handler, we build the error message. For example:
int someCounterValue = 0;
string someStringValue = "Some string we want to track to send to the global error handler."
private void SomeFunction()
{
try
{
someStringValue = "in the try block";
someCounterValue = 1.5 // should thrown an exception
}
catch(Exception ex)
{
throw new Exception("Error in SomeFunction. someStringValue = " + someStringValue + "; someCounterValue = " + someCounterValue.ToString() + "\r\nException details: " + ex.ToString());
}
}
It's a lot of work so we really don't do this very often. Usually our error handling is better handled at the local level but in those very rate cases where you want to pass it off to the global error handler, this is about the only way we've found, since the variables would be out of scope otherwise, and therefore, inaccessible.
An easier/less hack-like option would be to set up a static class in your web app called ErrorLogger or something similar, and just handle the exceptions better locally and pass them up to the global handler ONLY when you can't do it locally.
In my opinion (and in the way we do it here by policy) a global error handler should be used to catch exceptions that you forgot to handler better at a more granular level. It should NOT just be an easy way to be lazy about proper exception handling.
Also it feels like a hack to me, so if anyone has a better option I'd like to know it, too.
When I get an Object Ref error, it can sometimes be a real pain to find out which variable is causing the error (when you can't debug). Is there a way for this error to throw the classname that isn't assigned?
So: I want the name of the type of the variable that was unexpectedly null.
Thanks in advance.
I dont think you can get the class name, the closes I get is to get the class and method name, then the stack trace:
try
{
}
catch ( Exception ex )
{
xxx.API.ErrorHandler.Handler.HandleError( ex, System.Reflection.MethodBase.GetCurrentMethod().Name, System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName );
}
Well, its only the information in the stack trace which would be the first step in finding out where the error has originated. Also you should make sure you check the complete stack trace (all inner exceptions too). This would give you the method name with complete namespace. So that should be fairly good step to see where the error is, unless the standard coding is really bad.
Could anyone tell me why a problem in the noun model would not be caught by this try catch?
I have tried this on two different controller methods now, and both times, even if the linq2sql doesn't allow the data to be saved, the code never jumps into the catch block.
I've watched the noun object in the middle of the trace, and the isvalid property is false, but the modelstate isvalid is true. Either way, the code never jumps into the catch block.
I'm pulling my hair out about this. I feel like it will be something really silly.
The code all works similar to nerd dinner.
NounRepository nounRepository = new NounRepository();
Noun noun = new Noun();
try
{
UpdateModel(noun);
nounRepository.Add(noun);
nounRepository.save();
}
catch (Exception ex)
{
ModelState.AddRuleViolations(noun.GetRuleViolations());
return View(noun);
}
return View(noun);
Update
I have just added this code, and now the rules are coming back to the front end fine, so it just seems that the try catch isn't catching!
UpdateModel(noun);
if (!noun.IsValid)
{
var errors = noun.GetRuleViolations();
ModelState.AddRuleViolations(noun.GetRuleViolations());
return View(noun);
}
nounRepository.Add(noun);
nounRepository.save();
I'd rather not have to add code in this manner though, as it seems like an unnecessary duplication.
You faced logical change in mvc - validation here do not throw exceptions. Indeed, you need to check it using if statement.
I doubt that exception is happening - you need to catch linq2sql exception anyway, code is correct. Also there is high a chance that inside 'save' or 'add' you have another catch - this is quite common mistake
Programming Rule #1: catch ain't broken (AKA: SELECT ain't broken).
If you're really in doubt, open up the Debug menu, choose "Exceptions", then tick the box for "Common Language Runtime Exceptions" under "Thrown." This will cause the debugger to break on all first-chance exceptions. If the debugger doesn't break during your update, then the exception is never getting thrown in the first place.
Don't forget to untick when you're done, as the behaviour gets pretty annoying under normal usage.
P.S. Never catch System.Exception. Catch the specific type(s) of exception(s) that you know might actually be thrown.
Are you doing something in another thread? That is often a cause exceptions not being caught.