I have a project that makes extensive use of the GetGlobalResourceObject which is a member of the System.Web.UI class. It works fine providing english or french labels to the bilingual C#/ASP.NET application.
But....if the reference in the resource file is missing or malformed the application crashes
There are hundreds of calls like this
GetGlobalResourceObject("XXX.WebResource", "Remove")
Is there any way to encapsulate the GetGlobalResourceObject with an exception handler so that it returns null and logs it if there's a problem without adding a try/catch to each call?
I am new to C# so I don't know if I can override the GetGlobalResourceObject with my own class and then do a search and replace. Surely there is a better way.
Kevinsky
You can write your own version of GetGlobalResourceObject to embed the exception handling and logging in that:
public static Object MyGetGlobalResourceObject (string classKey,
string resourceKey)
{
try
{
return GetGlobalResourceObject (classKey, resourceKey);
}
catch (MissingManifestResourceException ex)
{
// log error
return null;
}
}
This code is provided as an starting point
You could even write it as an extension method on HttpContext.
You will have to do a global search and replace to call this rather than the base method, which isn't the most elegant solution, but it will work.
Related
What is the correct way to determine exactly what caused an exception, to correct it?
Consider the code below. I attempt to parse a string of XML, but occasionally, the incoming XML will not be top-level, meaning it needs to be surrounded by a root element.
Which this happens, the parser throws an XmlException, but it could throw that for a lot of reasons. I want to catch this one specific reason.
I do this, which I concede is probably not great:
var doc = new XmlDocument();
try
{
doc.LoadXml(xml);
}
catch(XmlException e)
{
if(e.Message.Contains("multiple root elements"))
{
doc.LoadXml($"<root>{xml}</root>");
}
else
{
throw e;
}
}
This feels like a hack. What is the correct way to do this?
There is a new feature of C# that allows you to filter exceptions in the catch clause with when keyword:
try
{
}
catch (XmlException ex) when ( ex.Message.Contains(...) )
{
//handle
}
You can use multiple fields to recognize the exception type, like the InnerException, StackTrace, and Data. As #David Hruška suggests, the HResult property is also a good place to check to recognize the type of the exception
The Message is not the best property to use for the check, as it is usually localized for the built-in types and as a result might look different with other culture setting.
you can try to make a switch for XmlException.HResult as described here:
https://msdn.microsoft.com/en-us/library/system.xml.xmlexception(v=vs.110).aspx
The only thing I am not sure, if it points the the specific exception type (like XmlException) or specific exception "message".
If this does not help, I think you have no other option than checking for message.
EDIT: Also, as was pointed above, you should throw; instead of throw e; as the second clears the StackTrace. ReSharper also warns about this one.
There are multiple ways to achieve what you're trying to do.
Different test frameworks bring their own tools to help with this too.
For example, if you're using MSVS Test Framework, the simplest option is to only check for the exception type. In this case you just mark the test method with "ExceptedExceptionAttribute" and specify the expected exception type to be thrown from the method, as follows:
[TestMethod]
[ExpectedException(typeof(ArgumentException))]
public void Action_ThrowsException()
{
// test logic here
}
There is another constructor available, which allows to specify the exact exception message as the second parameter, which is rarely used. You can find the documentation for ExpectedExceptionAttribute in MSDN.
Another option, where you have more control, would be what was already suggested in the other answers, which can be encapsulated in a helper method as follow:
private static T Throws<T>(Action action) where T : Exception
{
try
{
action();
Assert.Fail();
}
catch (T ex)
{
// This exception was expected.
return ex;
}
}
Using this helper method, you now can have your test method as follows:
[TestMethod]
public void Action_ThrowsException()
{
// test logic here
ArgumentException aex = Throws<ArgumentException>(()=>{
// Test logic here
});
Assert.AreEqual("Expected error message", aex.Message);
}
As you can see, this option provides you with higher flexibility as you can now validate other aspects of the exception explicitly.
FYI: The second solution is given as part of the xUnit framework.
OK, so I have the C# DLL method:
public void DeletePublisher(string strName)
{
try
{
if (_PublisherData.PublisherDictionary.ContainsKey(strName))
_PublisherData.PublisherDictionary.Remove(strName);
}
catch (Exception ex)
{
SimpleLog.Log(ex);
}
}
It works fine. If there is a exception it is detected and added to the log.
At the moment, the above is called via MFC in my C++ project using a wrapper:
bool CMSATools::DeletePublisher(CString strPublisher)
{
bool bDeleted = false;
if (m_pInterface != nullptr)
{
CComBSTR bstrPublisher = strPublisher.AllocSysString();
throw_if_fail(m_pInterface->DeletePublisher(bstrPublisher));
bDeleted = true;
}
return bDeleted;
}
They both work fine. The issue is that fact that the CPP method currently has no knowledge of the C# method having failed. Now, in this particular instance I know I could change the signature of the DLL method to return false for a exception failure occurring and examine that return value in the CPP file.
But, in other instances I am already using the return value and thus, it would seem for consistency to me, that I pass in a bool bExceptionRaised parameter instead to my methods in the DLL.
That way, I can test that value when the method seemed to complete and if it is false act accordingly.
At the moment my application doesn't realise that an exception occurred and that is confusion.
Can I assume that either of these methodologies are the simplest approach to what I am trying to detect?
Update
Based on the answer provided I have tried to follow this tutorial and I am getting confused. I have tried to follow it and I can't create a CLR DLL and build it that is a bridge to my C# DLL file.
Whilst I appreciate the answer I feel like it is breaking up everything I have worked on since the C# DLL already handles and logs it's exceptions. Whilst I would like to learn how to build this bridge for the future, I still think perhaps at the point in time just changing my signatures is sufficient. Either way, my attempt a basic build of a bridge is failing.
Use a C++/CLI wrapper for the access of the managed component.
With C++/CLI you can directly use the C# component can catch the managed exception and you can throw a native exception or even return true or false... whatever you want.
void DoManagedStuff(SOMEDATA somedata)
{
try
{
auto sm = ConvertToSomeDataToManaged(somedata);
CallManagedCode(sm);
}
catch (Exception^ e)
{
throw CMyNativeException();
}
}
Let's say that I have a class in my dll file:
public ClassInDllFile()
{
String str = "";
try
{
str = someClassMethod();
}
catch (Exception e) // or more precised exception type
{
// some code
}
}
I don't want to put exception message in MessageBox from Dll level (it requires additional references), but I would to pass it to some (on example) WinForm application.
You can just catch the exception in the WinForms class.
This means you should not catch the exception here, but in the WinForms class itself, where you can show a dialog.
You could use something like (I changed a bit of code from your example to improve naming):
public ClassInDllFile()
{
# Other functions
///
/// Might throw a ... exception
///
public Run()
{
String str = someClassMethod(); # Might cause an exception
# More code
}
And in your WinForms class:
var instance = ClassInDllFile()
try
{
instance.Run()
}
catch (Exception e) // or more precised exception type
{
// Error handling code
}
# More code
Also it is a good idea to document the ClassInDllFile.Run function which type of exceptions it might generate to inform calling functions to act upon it.
There are several ways in which you could handle this.
One simple way is to just throw the exception, and handle it in the outer / calling class.
Another is to gather info from the exception in your catch clause (like ExceptionMessage, StackTrace, and perhaps InternalException), and store these in properties that the the calling class can check. You might then also include a boolean property like Suceeded, which you set to false if an exception occurs. Then the calling class can check that property after making the call, and retrieve more details about the exception if it needs them.
You can manipulate this however you want. Experiment until you find a solution that fits your needs.
I have a problem running a Gurobi Optimization Model using a C#/.NET library through IronPython.
I have a method to access variables though their name (ie GRBModel.GetVarByName), something like
public GRBVar variable(i,t)
{
try
{
GRBModel M = getModel();
string varname = varname(i,t);
GRBVar var = M.GetVarByName(varname);
return var;
}
catch (GRBException ex)
{
System.Console.WriteLine(ex.ToString());
throw new GRBException(ex.ToString());
}
}
The problem is that on my IronPython script, when I try to access a non existing variable, nothing happens... the message doesnt appear on the console. What I'm doing wrong???
I think you're missing a return statement somewhere; if you catch the exception, the method does not return. (Doesn't the C# compiler error in that case?)
If this method is just for IronPython, you could just let the exception pass through to IronPython and deal with it there.
According to this page in the Gurobi .NET Reference Manual, GRBException inherits from the .NET Exception class. To obtain the error message from an Exception based class you should use the Message property rather than the ToString() method, which by default normally displays only the class name for reference classes.
In other words, change the catch clause to:
catch (GRBException ex)
{
System.Console.WriteLine(ex.Message);
}
Alternatively, you could output the ErrorCode property which is specific to the GRBException class.
In my services all exposed methods have:
try
{
// the method core is written here
}
catch(Exception ex)
{
Log.Append(ex);
}
It's boring and ugly to repeat it over and over again. Is there any way to avoid that? Is there a better way to keep the service working even if exceptions occur and keep sending the exception details to the Log class?
Try AOP. This is the most widely-used selling point of AOP.
Also, see this discussion here on SO.
You could set up a generic error handling method for all uncaught exceptions like so:
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(UnhandledException);
Depending on what went wrong, you may not be able to recover from the error... but this should hopefully give you some idea of what what went wrong. If it gets to the point where your application code hasn't handled the exception gracefully, this method could attempt to reinitialize the service to a known working state.
I came up with a semi-solution right now. I can refactor the code:
public TResult ExecuteAndLogOnError(Func<TResult> func)
{
try
{
return func();
}
catch(Exception ex)
{
// logging ...
}
}
And then you can call it on each method:
return ExecuteAndLogOnError(() =>
{
// method core goes here..
});
Which is 4 lines shorter than the original scenario.
In such cases I always use centralized error handlers.
In WCF it is very easy. Some more details:
http://www.haveyougotwoods.com/archive/2009/06/24/creating-a-global-error-handler-in-wcf.aspx
Basically, you just implement the IServiceBehavior interface and then provide your own error handler. That is the best way to do this because you don't have to write any code that handles fatal exceptions (I mean exceptions that you can only log and you don't know what to do about them) in your methods.
If all your doing is logging then just log the error at a later stage... No need to log the error early. If you do more than log the error, well then you're gonna need the try..catch anyway. And if you swallow exceptions (IE. just log them and then go on as if nothings happened) then maybe you're doing it wrong...
I once used something like the Template Function Pattern to resolve a problem like this. I had a base class that did something like:
public void Execute()
{
try
{
ExecuteImplementation();
}
catch (Exception ex)
{
// Log ex
}
}
public abstract void ExecuteImplementation();
There was one derived class per web service operation. The derived classes each implemented ExecuteImplementation.
The web service operations did:
[WebMethod]
public Result WebOperation(Request request)
{
WebOperationClass instance = new WebOperationClass(request);
instance.Execute();
return instance.Result;
}
Exception filters would be good for this. Alas, .NET supports them through MSIL, C++/CLI, VB.NET, but not C#.
If all you're doing in your catch is logging the exception, you could maybe just use a custom error page and let ELMAH log all your uncaught exceptions.
A previous poster brought up AOP (Aspecte-Oriented Programming).
I use PostSharp for basic logging traces/exceptions.
It's quite easy to use and setup.
Check out this link and watch the tutorial.
http://www.sharpcrafters.com/postsharp
--crap it is no longer open source ... anyways you can grab Postsharp1.5 and mess around with it to see if it is something you are interested in it.
I am also in no way affiliated with PostSharp. I'm just a user.