Cannot catch custom exception thrown in MSScriptControl's Eval function - c#

This is a MVCE of my problem.
I have this method using MSScriptControl to dynamically evaluate some formula.
public void DoCalculate()
{
try
{
var evaluator = new Evaluator();
IScriptControl ctrl = new ScriptControl();
ctrl.Language = "JavaScript";
ctrl.AddObject("Evaluator", evaluator, false);
var calcFunction = "Number(Evaluator.Divide(4,0))";
double rs = ctrl.Eval(calcFunction);
}
catch (CustomException cex)
{
// Handle CustomException.
}
catch (Exception ex)
{
// Handle general Exception.
}
}
This is the Evaluator class.
public class Evaluator
{
public double Divide(int a, int b)
{
if (b == 0)
{
throw new CustomException("Cannot divide by zero");
}
else
{
return a / b;
}
}
public void TestThrow()
{
throw new CustomException("This is a test");
}
}
And this is the CustomException class:
using System;
namespace Library
{
public class CustomException : Exception
{
public CustomException()
: base()
{
}
public CustomException(string message)
: base(message)
{
}
}
}
I expected that in this case a CustomException will be throw, and the first catch clause will be entered. However, I got an general Exception (I verified the exception type using GetType().Name) with the message "Cannot divide by zero" instead.
I did get the following error in Evaluator class though:
An exception of type 'Library.CustomException' occurred in XXX.dll but was not handled in user code
If I modify my DoCalculate() like this then I can catch a CustomException just fine:
public void DoCalculate()
{
try
{
var evaluator = new Evaluator();
evaluator.TestThrow();
}
catch (CustomException cex)
{
// Handle CustomException.
}
catch (Exception ex)
{
// Handle general Exception.
}
}
Does that mean it is impossible to define and throw my own exception from inside Eval function?
I'm using .NET 4.6.2 and Interop.MSScriptControl 1.0.0.0

This is the summary of the answer given in this link
COM methods report errors by returning HRESULTs; .NET methods report them by throwing exceptions. The runtime handles the transition between the two. Each exception class in the .NET Framework maps to an HRESULT. So in order to throw proper exception, Let me suggest the following.
var evaluator = new Evaluator();
IScriptControl ctrl = new MSScriptControl.ScriptControl { Language = "VBScript" };
ctrl.AddObject("Evaluator", new Evaluator(), true);
const string calcFunction = "Evaluator.Divide(4,0)";
try {
double rs = ctrl.Eval(calcFunction);
}
catch (DivideByZeroException ex) {//Actual DivideByZeroException from .Net
//How can you divide by zero?!?!
}
catch (Exception ex) {
//STUFF
}
public class Evaluator {
public double Divide(int a, int b) {
if (b == 0) {
throw new MyDivideByZeroException();
}
return a / b;
}
}
public class MyDivideByZeroException : Exception {
public MyDivideByZeroException() {
HResult = -2147352558;
}
}

Related

How to enforce each Inside method must have throw

Enforce each Inside method must have throw or enforce not use try catch block.
Below example InsideMethod2() is not implemted throw in this case when it's is calling in Main() method, should give some warning or error message saying that you must throw or should not use try catch block.
Example :
public void Main()
{
try
{
InsideMethod1();
InsideMethod2();
}
catch (System.Exception)
{
throw;
}
}
public int InsideMethod1()
{
try
{
// implementation here
}
catch (System.Exception)
{
// log
throw;
}
}
public int InsideMethod2()
{
// enforce throw or enforce not use try catch block
int a = 1, b = 0, c = 0;
try
{
c = a / b;
}
catch (System.Exception)
{
// enforce to throw
// log
}
return c;
}
Is it possible to enforce inside methods..?

Catch derived class Exceptions in base class with different methods and arguments

I'm trying to make something like base "exception handler" thing. So this base class will try-catch exceptions when any method (with any number of parameters) in derived class gets invoked. I'm not good in describing this with words, so here is the scenario:
public abstract BaseClass
{
Exception _ex;
public Exception LastKnownException
{
get
{
return this._ex;
}
}
//...
//what do I do here to assign the value of above property when some random exception occur in derived class?
//...
//The closest I can get...
public void RunMethod(Action method)
{
try
{
method.Invoke();
}
catch (Exception ex)
{
this._ex = ex;
}
}
}
public class DerivedClass : BaseClass
{
public void DoRandomMethod(int couldBeOfAnyTypeHere, bool andIndefiniteNumberOfThese)
{
bool result = false;
var someObject = new OtherClass(couldBeOfAnyTypeHere, out andIndefiniteNumberOfThese);
someObject.DoInternalWork(result); // <-- here is where I need the base class to take care if any exception should occur
}
public int AnotherMethod(int? id)
{
if (!id.HasValue)
id = Convert.ToInt32(Session["client_id"]);
var someOtherObject = new OtherClassB(id.Value);
return someOtherObject.CheckSomething(); // <-- and catch possible exceptions for this one too
}
//The closest I can get... (see base class implementation)
public List<RandomClass> GetSomeListBy(int id)
{
RunMethod(() =>
string[] whateverArgs = new[] { "is", "this", "even", "possible?" };
YetAnotherStaticClass.GetInstance().ExecuteErrorProneMethod(whateverArgs); // <-- Then when something breaks here, the LastKnownException will have something
);
}
}
public class TransactionController : Controller
{
public ActionResult ShowSomething()
{
var dc = new DerivedClass();
dc.DoRandomMethod(30, true);
if (dc.LastKnownException != null)
{
//optionally do something here
return RedirectToAction("BadRequest", "Error", new { ex = dc.LastKnownException });
}
else
{
return View();
}
}
}
EDIT: My simple approach will work, only, I don't want to have to wrap all methods with this lambda-driven RunMethod() method all the time -- I need the base class to somehow intercept any incoming exception and return the Exception object to the derived class without throwing the error.
Any ideas would be greatly appreciated. And thanks in advance!
I think you should consider using the event System.AppDomain.UnhandledException
This event will be raised whenever an exception occurs that is not handled.
As you don't clutter your code with the possibilities of exception, your code will be much better readable. Besides it would give derived classes the opportunity to catch exceptions if they expect ones, without interfering with your automatic exception catcher.
Your design is such, that if someone calls several functions of your derived class and then checks if there are any exceptions the caller wouldn't know which function caused the exception. I assume that your caller is not really interested in which function causes the exception. This is usually the case if you only want to log exception until someone investigates them.
If that is the case consider doing something like the following:
static void Main(string[] args)
{
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
}
static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
var ex = e.ExceptionObject as Exception;
if (ex != null)
logger.LogException(ex);
// TODO: decide whether to continue or exit.
}
If you really want to do this only for your abstract base class
public abstract BaseClass
{
private List<Exception> unhandledExceptions = new List<Exception>();
protected BaseClass()
{
AppDomain.CurrentDomain.UnhandledException += UnhandledException;
}
private void UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
var ex = e.ExceptionObject as Exception;
if (ex != null)
this.UnhandledExceptions.Add(ex);
}
public List<Exception> LastKnownExceptions
{
get { return this.unhandledExceptions; }
}
I had a similar requirement for catching exceptions, but used a specific implementation (i.e. not an abstract class) to encapsulate the handling of errors.
Please note this takes in an argument for any expected exceptions (params Type[] catchableExceptionTypes), but of course you can modify to suit your own requirements.
public class ExceptionHandler
{
// exposes the last caught exception
public Exception CaughtException { get; private set; }
// allows a quick check to see if an exception was caught
// e.g. if (ExceptionHandler.HasCaughtException) {... do something...}
public bool HasCaughtException { get; private set; }
// perform an action and catch any expected exceptions
public void TryAction(Action action, params Type[] catchableExceptionTypes)
{
Reset();
try
{
action();
}
catch (Exception exception)
{
if (ExceptionIsCatchable(exception, catchableExceptionTypes))
{
return;
}
throw;
}
}
// perform a function and catch any expected exceptions
// if an exception is caught, this returns null
public T TryFunction<T>(Func<T> function, params Type[] catchableExceptionTypes) where T : class
{
Reset();
try
{
return function();
}
catch (Exception exception)
{
if (ExceptionIsCatchable(exception, catchableExceptionTypes))
{
return null;
}
throw;
}
}
bool ExceptionIsCatchable(Exception caughtException, params Type[] catchableExceptionTypes)
{
for (var i = 0; i < catchableExceptionTypes.Length; i++)
{
var catchableExceptionType = catchableExceptionTypes[i];
if (!IsAssignableFrom(caughtException, catchableExceptionType)) continue;
CaughtException = caughtException;
HasCaughtException = true;
return true;
}
return false;
}
static bool IsAssignableFrom(Exception exception, Type type)
{
if (exception.GetType() == type) return true;
var baseType = exception.GetType().BaseType;
while (baseType != null)
{
if (baseType == type) return true;
baseType = baseType.BaseType;
}
return false;
}
void Reset()
{
CaughtException = null;
HasCaughtException = false;
}
}

how to differentiate among different exceptions of same class?

how to check whether its is login info exception or a connection lost exception if the the exceptions are form the same class?
private bool checkFileExists(string absoluteRemoteLocation)
{
try
{
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(absoluteRemoteLocation);
request.Method = WebRequestMethods.Ftp.UploadFile;
request.Timeout = timeOut;
request.Credentials = new NetworkCredential(this.username, this.password);
request.GetResponse();
return true;
}
catch(Exception e) //i want to check here
{
var g = e.ToString();
return false;
}
}
Use different catch block like this:
catch (System.TimeoutException e)
{
var g = e.ToString();
return false;
}
catch (System.Net.WebException e)
{
var g = e.ToString();
return false;
}
Use is keyword of C#.
<!-- language: C# -->
catch (Exception e) {
if (e is LoginInfoException) // do something
else if (e is ConnectionLostException) // do something else
}
For reference, check this link.
Isn't this what you want?
public class Program
{
public static void Main(string[] args)
{
try
{
throw new ConnectionLostException();
}
catch (Exception ex)
{
if (ex is LoginInfoException)
{
Console.WriteLine ("LoginInfoException");
}
else if (ex is ConnectionLostException)
{
Console.WriteLine ("ConnectionLostException");
}
}
}
}
public class LoginInfoException : WebException
{
public String Message { get; set; }
}
public class ConnectionLostException : WebException
{
public String Message { get; set; }
}
This is a simple example of a filter that will catch different exceptions. I don't know much about the hierarchy of exceptions you're dealing with, but this will allow you to filter what exceptions get caught where.
public class CatchExceptions
{
public void SomeMethod ()
{
try
{
//some stuff that throws exceptions
}
catch (WebException e) if (e is LoginInfoException)
{}
catch (WebException e) if (e is ConnectionLostException)
{}
}
}
Obviously you'll have to figure out what you can use to filter the exceptions like so; it appears that the two examples I used above are not concrete types. You may need to do some restructuring to figure out how to differentiate between the two.

Unit testing exception property

I have exception
class SyntaxError : Exception {
public SyntaxError(int l) {
line = l;
}
public int line;
}
I'm using unit tests to test class Parser which on specific input should throw exception above. I'm using code like this:
[TestMethod]
[ExpectedException(typeof(Parser.SyntaxError))]
public void eolSyntaxError()
{
parser.reader = new StringReader("; alfa\n; beta\n\n\n\na");
parser.eol();
}
Is there any smart simple way to check if SyntaxError.line == 1?
Best I come up with is:
[TestMethod]
public void eolSyntaxError()
{
try {
parser.reader = new StringReader("; alfa\n; beta\n\n\n\na");
parser.eol();
Assert.Fail();
} catch (SyntaxError e) {
Assert.AreEqual(1, e.line);
}
}
I don't like it very much, is there better way?
Consider using FluentAssertions. Your test will then look like this:
[TestMethod]
public void eolSyntaxError()
{
parser.reader = new StringReader("; alfa\n; beta\n\n\n\na");
Action parseEol = () => parser.eol();
parseEol
.ShouldThrow<SyntaxError>()
.And.line.Should().Be(1);
}
Otherwise, your approach is pretty much as good as it gets.
You could write a method similar to the one in NUnit
public T Throws<T>(Action code) where T : Exception
{
Exception coughtException = null;
try
{
code();
}
catch (Exception ex)
{
coughtException = ex;
}
Assert.IsNotNull(coughtException, "Test code didn't throw exception");
Assert.AreEqual(coughtException.GetType(), typeof(T), "Test code didn't throw same type exception");
return (T)coughtException;
}
And then you can use it in your test method
Parser.SyntaxError exception = Throws<Parser.SyntaxError>(() => parser.eol());
Assert.AreEqual(1, exception.line);
As per my comment, if the line at which you encounter the syntax error is relevant, then include it in your custom exception class, like so.
public class SyntaxError : Exception
{
public SyntaxError(int atLine)
{
AtLine = atLine;
}
public int AtLine { get; private set; }
}
Then it's easy to test.
EDIT - After having read the question (!) here's a simple additional Assert method which will tidy up your exception assertions.
public static class xAssert
{
public static TException Throws<TException>(Action a) where TException : Exception
{
try
{
a();
}
catch (Exception ex)
{
var throws = ex as TException;
if (throws != null)
return throws;
}
Assert.Fail();
return default(TException);
}
}
Usage as follows...
public class Subject
{
public void ThrowMyException(int someState)
{
throw new MyException(someState);
}
public void ThrowSomeOtherException()
{
throw new InvalidOperationException();
}
}
public class MyException : Exception
{
public int SomeState { get; private set; }
public MyException(int someState)
{
SomeState = someState;
}
}
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
var subject = new Subject();
var exceptionThrown = xAssert.Throws<MyException>(() => { subject.ThrowMyException(123); });
Assert.AreEqual(123, exceptionThrown.SomeState);
}
}
I am not aware of an out of the box solution for this, but I have seen the concept of expectations which work like this:
[TestMethod]
public void EolSyntaxError()
{
Expectations.Expect<(SyntaxError>(
() =>
{
parser.reader = new StringReader("; alfa\n; beta\n\n\n\na");
parser.eol();
},
e =>
{
Assert.AreEqual(1, e.line);
});
}
Expectations needs to be implemented. I reckon there will be libraries out there which already do this. Anyhow, the Expect method in Expectations could look like this:
public static void Expect<TExpectedException>(
System.Action action,
System.Action<TExpectedException> assertion) where TExpectedException : Exception
{
if (action == null) { throw new ArgumentNullException("action"); }
try
{
action.Invoke();
Assert.Fail(string.Format("{0} expected to be thrown", typeof(TExpectedException).Name));
}
catch (TExpectedException e)
{
assertion.Invoke(e);
}
}

Is it possible to catch an exception you can't handle (in C#)?

I have a generic class that catches exceptions of T:
public abstract class ErrorHandlingOperationInterceptor<T> : OperationInterceptor where T : ApiException
{
private readonly Func<OperationResult> _resultFactory;
protected ErrorHandlingOperationInterceptor(Func<OperationResult> resultFactory)
{
_resultFactory = resultFactory;
}
public override Func<IEnumerable<OutputMember>> RewriteOperation(Func<IEnumerable<OutputMember>> operationBuilder)
{
return () =>
{
try
{
return operationBuilder();
}
catch (T ex)
{
var operationResult = _resultFactory();
operationResult.ResponseResource = new ApiErrorResource { Exception = ex };
return operationResult.AsOutput();
}
};
}
}
With subclasses for specific exceptions e.g.
public class BadRequestOperationInterceptor : ErrorHandlingOperationInterceptor<BadRequestException>
{
public BadRequestOperationInterceptor() : base(() => new OperationResult.BadRequest()) { }
}
This all seems to work perfectly. But, somehow, in the logs (once, not every time) is an InvalidCastException:
System.InvalidCastException: Unable to cast object of type 'ErrorHandling.Exceptions.ApiException' to type 'ErrorHandling.Exceptions.UnexpectedInternalServerErrorException'.
at OperationModel.Interceptors.ErrorHandlingOperationInterceptor`1.c__DisplayClass2.b__1() in c:\BuildAgent\work\da77ba20595a9d4\src\OperationModel\Interceptors\ErrorHandlingOperationInterceptor.cs:line 28
Line 28 is the catch.
What am I missing? Have I done something really dumb?
As smithy said, your T is of type ApiErrorResource. You are, some where in your code, attempting to create your ErrorHandlingOperationInterceptor with an Exception that is NOT derived from ApiErrorResource.
try
{
// throw Exception of some sort
}
catch (BadRequestException ex)
{
BadRequestOperationInterceptor broi = new BadRequestOperationInterceptor ();
}
catch (Exception ex)
{
// this is NOT right
BadRequestOperationInterceptor broi = new BadRequestOperationInterceptor ();
}

Categories

Resources