I have a WebAPI which is having the following piece of code in which there is Null reference exception in the code written in try block which is getting logged using my logger.
But in the TargetSite of the Exception getting logged, I am receiving Void MoveNext() instead of the method name in which this code is written.
What could be the reason for the same??
public async Task<ResponseStatus> ProcessRCSCNotification(IList<RecurringSubscriptionModelV2> recurringSubscriptionList, string appCD)
{
foreach (var model in modelList)
{
// Some code
try
{
// Exception occurs here
}
catch (Exception ex)
{
// Logger is logging exception here
}
}
return null;
}
You have an async method with several awaits. The compiler transform this whole method into a state machine and your method ends up actually only calling this state machine.
This state machine class has the mentioned MoveNext() method that now contains all the work you actually wanted to do.
To analyze your NullReferenceException you should rather check the StackTrace property of the exception than the TargetSite.
The method is an async/await method.
This kind of method is rewritten to a state machine with a MoveNext method. That's why your stack trace will identify this method as the one throwing that exception.
.NET Core 2.0 or 2.1 have either built-in or an extra nuget package that will fix stack traces like this to mention the actual method instead of the generated one.
You can read more about this here: Age of Ascent: Stacktrace improvements in .NET Core 2.1.
It might not fixup the TargetSite however, and I don't think it will handle .NET Framework.
Related
I am working on a small wpf application and one of the users is getting the following exception:
System.MethodAccessException:
Attempt by method "xxx.HttpConfirmation.Invoke()" to access method "System.Threading.Tasks.Task.get_CompletedTask()" failed.
at xxx.HttpConfirmation.Invoke()
at xxx.RequestPipeline.<ProcessQueuedRequests>d__11.MoveNext()
According to MSDN documentation, such exception is thrown in the following situations:
A private, protected, or internal method that would not be accessible from normal compiled code is accessed from partially trusted code by using reflection.
A security-critical method is accessed from transparent code.
The access level of a method in a class library has changed, and one or more assemblies that reference the library have not been recompiled.
Task.get_CompletedTask() is public since its introduction and I am also not using reflection to access the property.
I also don't think that there is a problem with code security/transparency since only one user is having this issue.
The exception is thrown at the Task.CompletedTask line:
public class HttpConfirmation
{
public static Task Invoke()
{
using (var client = new WebClient())
{
try
{
// Send the request and don't wait for the response.
client.UploadStringTaskAsync("http://sampleUrl.com", string.Empty);
}
catch
{
// ignore
}
}
return Task.CompletedTask;
}
}
Any ideas on what may cause the exception?
The problem was that the customer had .NET 4.5.2 installed and the program targeted .NET 4.6.
Though I still have no clue as to why exactly System.MethodAccessException was thrown as none of the 3 documented situations for throwing this exception did happen.
I'm writing a wrapper around a fairly large unmanaged API. Almost every imported method returns a common error code when it fails. For now, I'm doing this:
ErrorCode result = Api.Method();
if (result != ErrorCode.SUCCESS) {
throw Helper.ErrorToException(result);
}
This works fine. The problem is, I have so many unmanaged method calls that this gets extremely frustrating and repetitive. So, I tried switching to this:
public static void ApiCall(Func<ErrorCode> apiMethod) {
ErrorCode result = apiMethod();
if (result != ErrorCode.SUCCESS) {
throw Helper.ErrorToException(result);
}
}
Which allows me to cut down all of those calls to one line:
Helper.ApiCall(() => Api.Method());
There are two immediate problems with this, however. First, if my unmanaged method makes use of out parameters, I have to initialize the local variables first because the method call is actually in a delegate. I would like to be able to simply declare a out destination without initializing it.
Second, if an exception is thrown, I really have no idea where it came from. The debugger jumps into the ApiCall method and the stack trace only shows the method that contains the call to ApiCall rather than the delegate itself. Since I could have many API calls in a single method, this makes debugging difficult.
I then thought about using PostSharp to wrap all of the unmanaged calls with the error code check, but I'm not sure how that would be done with extern methods. If it ends up simply creating a wrapper method for each of them, then I would have the same exception problem as with the ApiCall method, right? Plus, how would the debugger know how to show me the site of the thrown exception in my code if it only exists in the compiled assembly?
Next, I tried implementing a custom marshaler that would intercept the return value of the API calls and check the error code there. Unfortunately, you can't apply a custom marshaler to return values. But I think that would have been a really clean solution it if had worked.
[return:
MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(ApiMethod))]
public static extern ErrorCode Method();
Now I'm completely out of ideas. What are some other ways that I could handle this?
Follow ErrorHandler class from the Visual Studio 2010 SDK. It existed in earlier versions, but the new one has CallWithCOMConvention(Action), which may prove valuable depending on how your API interacts with other managed code.
Of the available methods, I recommend implementing the following:
Succeeded(int)
(Failed() is just !Succeeded(), so you can skip it)
ThrowOnFailure(int)
(Throws a proper exception for your return code)
CallWith_MyErrorCode_Convention(Action) and CallWith_MyErrorCode_Convention(Func<int>)
(like CallWithCOMConvention, but for your error codes)
IsCriticalException(Exception)
(used by CallWith_MyErrorCode_Convention)
What happens if you don't check ErrorCode.SUCCESS? Will your code quickly fail and throw an exception? Can you tell which unmanaged API failed if your managed code throws? If so, consider not checking for errors and just letting the runtime throw when your unmanaged API fails.
If this is not the case, I suggest biting the bullet and following your first idea. I know you called it "frustrating and repetitive", but after coming from a project with a "clever" macro solution to a similar problem, checking return values in method calls and wrapping exceptions is the doorway to insanity: exception messages and stack traces become misleading, you can't trace the code, performance suffers, your code become optimized for errors and goes off the rails upon success.
If a particular return value is an error, thow a unique exception then. If it might not be an error, let it go and throw if becomes an error. You said you wanted to reduce the check to one line?
if (Api.Method() != ErrorCode.SUCCESS) throw new MyWrapperException("Api.Method broke because ...");
Your proposal also throws the same exception if any method returns the same "common error code". This is another debugging nightmare; for APIs which return the same error codes from multiple calls, do this:
switch (int returnValue = Api.Method1())
{
case ErrorCode.SUCCESS: break;
case ErrorCode.TIMEOUT: throw new MyWrapperException("Api.Method1 timed out in situation 1.");
case ErrorCode.MOONPHASE: throw new MyWrapperException("Api.Method1 broke because of the moon's phase.");
default: throw new MyWrapperException(string.Format("Api.Method1 returned {0}.", returnValue));
}
switch (int returnValue = Api.Method2())
{
case ErrorCode.SUCCESS: break;
case ErrorCode.TIMEOUT: throw new MyWrapperException("Api.Method2 timed out in situation 2, which is different from situation 1.");
case ErrorCode.MONDAY: throw new MyWrapperException("Api.Method2 broke because of Mondays.");
default: throw new MyWrapperException(string.Format("Api.Method2 returned {0}.", returnValue));
}
Verbose? Yup. Frustrating? No, what's frustrating is trying to debug an app that throws the same exception from every line whatever the error.
I think, the easy way is to add aditional layer.
class Api
{
....
private static ErrorCode Method();//changing Method to private
public static void NewMethod()//NewMetod is void, because error is converted to exceptions
{
ErrorCode result = Method();
if (result != ErrorCode.SUCCESS) {
throw Helper.ErrorToException(result);
}
}
....
}
Create a private property to hold the ErrorCode value, and throw the exception from the setter.
class Api
{
private static ErrorCode _result;
private static ErrorCode Result
{
get { return _result; }
set
{
_result = value;
if (_result != ErrorCode.SUCCESS)
{
throw Helper.ErrorToException(_result);
}
}
}
public static void NewMethod()
{
Result = Api.Method();
Result = Api.Method2();
}
}
Write a T4 template to do the generation for you.
Your existing code is actually really, really close. If you use an expression tree to hold the lambda, instead of a Func delegate, then your Helper.ApiCall can pull out the identity of the function that was called and add that to the exception it throws. For more information on expression trees and some very good examples, Google Marc Gravell.
I'm working with threads on a compact framework project and have code that looks something like below. When I try to step into StartThreads(), a NotSupportedException is thrown. This seems a bit wierd, why is the exception thrown on the line calling StartThreads() and not inside, and what is it that's not supported on CF? I think its ThreadStart.BeginInvoke but that's not where the exception is actually being thrown.
void SomeMethod()
{
this.StartThreads(); // <- NotSupportedException is thrown here, I can't step into this method with the debugger
}
void StartThreads()
{
ThreadStart threadStart = BeginDoStuff;
threadStart.BeginInvoke(EndDoStuff, null);
}
The BeginInvoke mechanism is not supported in CF, along with the ThreadPool.
The reason you don't see the Exception where you expect is due to the way this is implemented. I am not totally sure about the details but BeginInvoke is not a normal method (of the Delegate class) but something that is injected at runtime (just guessing that last part).
The error occurs when the JIT compiler gets to work on the StartThreads method.
delegate.BeginInvoke is not supported on the CF.
However the ThreadPool is supported. You can use the thread pool to achieve essentially the same behavior.
void SomeMethod()
{
this.StartThreads();
}
void StartThreads()
{
System.Threading.ThreadPool.QueueUserWorkItem(DoStuff);
}
if you want it to call a callback when finished I suggest you read up on the Asynchronous Programming Model
In the most recent version (4.1, released October 2008) of The Microsoft Enterprise Library's Exception Handling Application Block, there are two HandleException() method signatures, and I am a bit lost on the intent for these, especially since neither the documentation, intellisense, nor the QuickStart apps intimate any meaningful difference.
Here are the two signatures:
bool HandleException(Exception exceptionToHandle, string policyName);
bool HandleException(Exception exceptionToHandle, string policyName, out Exception exceptionToThrow);
All of the examples I have found use the first, as in this example straight out of the XML documentation comments on the actual method:
try
{
Foo();
}
catch (Exception e)
{
if (ExceptionPolicy.HandleException(e, name)) throw;
}
And here, from the same source (the XML doc comments for the method), is an example of using the second:
try
{
Foo();
}
catch (Exception e)
{
Exception exceptionToThrow;
if (ExceptionPolicy.HandleException(e, name, out exceptionToThrow))
{
if(exceptionToThrow == null)
throw;
else
throw exceptionToThrow;
}
}
So, my question is, what does using the second one give you that the first does not? This should probably be obvious to me, but my head is a mess today and I don't really want to keep banging my head against the proverbial wall any longer. :)
No speculations, please; I hope to hear from someone that actually knows what they are talking about from experience using this.
If you use a replace handler in the enterprise library config, your replacement exception is returned by means of the second signature .. , out Exception exceptionToThrow).
The main difference between the two method overloads is that
bool HandleException(Exception exceptionToHandle, string policyName);
will throw an exception if the PostHandlingAction is set to ThrowNewException.
Whereas the second method overload:
bool HandleException(Exception exceptionToHandle, string policyName, out Exception exceptionToThrow);
does not throw an exception in that case but instead returns the exception to be rethrown as an out parameter.
Actually, both calls invoke the same core code but the second method overload catches the thrown Exception and returns it to the caller.
So the second overload gives you a bit more control since you could perform some additional logic before throwing. It also standardizes the API in the sense that if you use the second HandleException method with the out parameter Enterprise Library will never intentionally handle your exception and throw it for you. i.e. The first method sometimes throws and sometimes relies on you to rethrow (in the case of NotifyRethrow) but the second method always returns and lets the caller throw/rethrow.
I believe you are not allowed to throw your original exceptions across WCF service boundaries, this is a security feature (really to make sure that sensitive error information is not propagated through the service chain). Therefore a new execption can be created and passed in via the second parameter out Exception exceptionToThrow) and given a specific exception message and type by means of your configuration (enterprise library replace exception). One example of which is:
try
{
throw new InvalidCastException();
}
catch (InvalidCastException ex)
{
Exception ex1;
bool rethrow = ExceptionPolicy.HandleException(ex, "ReplacePolicy1", out ex1);
if (rethrow)
{
throw new FaultException<ApplicationException>((ApplicationException)ex1, ex1.Message);
}
}
Throwing a FaultException (with a Fault contract set up on the WCF operation) prevents the WCF Service from reporting a faulted state error message in your calling application / Service.
Without the second signature i would struggle with error simplification / propagation across WCF service boundries.
Thanks,
Paul.
(mod to code 8/7/09 - correction comment from John, thanks)
In an application I work on, any business logic error causes an exception to be thrown, and the calling code handles the exception. This pattern is used throughout the application and works well.
I have a situation where I will be attempting to execute a number of business tasks from inside the business layer. The requirement for this is that a failure of one task should not cause the process to terminate. Other tasks should still be able to execute. In other words, this is not an atomic operation. The problem I have is that at the end of the operation, I wish to notify the calling code that an exception or exceptions did occur by throwing an exception. Consider the following psuedo-code snippet:
function DoTasks(MyTask[] taskList)
{
foreach(MyTask task in taskList)
{
try
{
DoTask(task);
}
catch(Exception ex)
{
log.add(ex);
}
}
//I want to throw something here if any exception occurred
}
What do I throw? I have encountered this pattern before in my career. In the past I have kept a list of all exceptions, then thrown an exception that contains all the caught exceptions. This doesn't seem like the most elegant approach. Its important to preserve as many details as possible from each exception to present to the calling code.
Thoughts?
Edit: The solution must be written in .Net 3.5. I cannot use any beta libraries, or the AggregateException in .Net 4.0 as mentioned by Bradley Grainger (below) would be a nice solution for collection exceptions to throw.
The Task Parallel Library extensions for .NET (which will become part of .NET 4.0) follow the pattern suggested in other answers: collecting all exceptions that have been thrown into an AggregateException class.
By always throwing the same type (whether there is one exception from the child work, or many), the calling code that handles the exception is easier to write.
In the .NET 4.0 CTP, AggregateException has a public constructor (that takes IEnumerable<Exception>); it may be a good choice for your application.
If you're targeting .NET 3.5, consider cloning the parts of the System.Threading.AggregateException class that you need in your own code, e.g., some of the constructors and the InnerExceptions property. (You can place your clone in the System.Threading namespace inside your assembly, which could cause confusion if you exposed it publicly, but will make upgrading to 4.0 easier later on.) When .NET 4.0 is released, you should be able to “upgrade” to the Framework type by deleting the source file containing your clone from your project, changing the project to target the new framework version, and rebuilding. Of course, if you do this, you need to carefully track changes to this class as Microsoft releases new CTPs, so that your code doesn't become incompatible. (For example, this seems like a useful general-purpose class, and they could move it from System.Threading to System.) In the worst case, you can just rename the type and move it back into your own namespace (this is very easy with most refactoring tools).
Two ways of the top of my head would be either make a custom exception and add the exceptions to this class and throw that the end :
public class TaskExceptionList : Exception
{
public List<Exception> TaskExceptions { get; set; }
public TaskExceptionList()
{
TaskExceptions = new List<Exception>();
}
}
public void DoTasks(MyTask[] taskList)
{
TaskExceptionList log = new TaskExceptionList();
foreach (MyTask task in taskList)
{
try
{
DoTask(task);
}
catch (Exception ex)
{
log.TaskExceptions.Add(ex);
}
}
if (log.TaskExceptions.Count > 0)
{
throw log;
}
}
or return true or false if the tasks failed and have a 'out List' variable.
public bool TryDoTasks(MyTask[] taskList, out List<Exception> exceptions)
{
exceptions = new List<Exception>();
foreach (MyTask task in taskList)
{
try
{
DoTask(task);
}
catch (Exception ex)
{
exceptions.Add(ex);
}
}
if (exceptions.Count > 0)
{
return false;
}
else
{
exceptions = null;
return true;
}
}
You could create a custom Exception that itself has a collection of Exceptions. Then, in your Catch block, just add it to that collection. At the end of your process, check if the Exception count is > 0, then throw your custom Exception.
You might want to use a BackgroundWorker to do this for you. It automatically captures and presents any exceptions when completed, which you could then throw or log or do whatever with. Also, you get the benefit of multithreading.
The BackgroundWorker is a nice wrapper around delegate's asynchronous programming model.
No super-elegant solution here but a few ideas:
Pass an error-handler function as argument to DoTasks so the user can decide whether to continue
Use tracing to log errors as they occur
Concatenate the messages from the other exceptions in the exception bundle's message