I am using StackExchange.Precompilation to perform some C# syntax transformations on build. I would like to be able to throw exceptions from my ICompileModule during the build and have those output to Visual Studio's output window.
I have created a custom exception type PrecompilationException to represent errors that occur during these syntax transformations. Here is my exception class:
[Serializable]
public class PrecompilationException : Exception {
public PrecompilationException() : base() { }
public PrecompilationException(string message) : base(message) { }
public PrecompilationException(string message, Exception innerException) : base(message, innerException) { }
protected PrecompilationException(SerializationInfo info, StreamingContext context) : base(info, context) { }
}
When one of these exceptions is thrown, the output window shows a SerializationException whose message is "Type is not resolved for member 'PrecompilationException...", but there are no details of that PrecompilationException like its message or stack trace.
Did I leave out something important for proper serialization in my exception class? Is there a better way to get StackExchange.Precompilation to log errors?
Update
If I change the exception type being throw to something standard like Exception or NotSupportedException the output window will show the exception details. However, I would still like to be able to use custom exception types in this way.
Update2
The answer to this question sheds some light on why my custom exception type was not working. Basically, the ASP.NET compiler has trouble serializing types that aren't in the GAC.
Type resolution error during ASP.NET precompilation
Just add a Diagnostic to the Diagnostics collections in Before/AfterCompileContext.
The other alternative is to Console.WriteLine in the MsBuild VS-Aware error message format
Related
So in a few days I have a test coming up where I have to program a project in 2 days, afterwards my assessors will get the chance to ask me questions about what I made. One of the things I need to include in my program is Exceptions, I created a custom exception and let the constructors be automatically generated (see below) but I only use the second one. Now I could just delete the bottom two but I think it'll be more handy to try to understand what they are actually used for.
public class CantConnectToDatabaseException : Exception
{
public CantConnectToDatabaseException()
{
}
public CantConnectToDatabaseException(string message) : base(message)
{
}
public CantConnectToDatabaseException(string message, Exception innerException) : base(message, innerException)
{
}
protected CantConnectToDatabaseException(SerializationInfo info, StreamingContext context) : base(info, context)
{
}
}
If someone could explain this to me in a way I can remember and explain it back to someone I would greatly appreciate that, I tried reading up on it through MSDN but I couldn't follow it.
InnerException is used when you catch an exception and rethrow it.
For a somewhat contrived example, say you have a bunch of data access methods. All kinds of things can go wrong in them, so you wrap them like so:
try
{
// stuff
}
catch (Exception ex)
{
throw new MyDataAccessException("Error accessing data", ex);
}
Now your code can catch MyDataAccessException to get any exception caused by data access problems, but the handler can look at the InnerException property of the MyDataAccessException object to find out exactly what went wrong, and where.
protected CantConnectToDatabaseException(SerializationInfo info, StreamingContext context) : base(info, context)
This constructor is called during deserialization to reconstitute the exception object transmitted over a stream. For more information, see XML and SOAP Serialization.
Serialization is when you take an object in memory and convert it into some kind of text or binary representation that can be transmitted over a network or stored on a disk. SOAP, "Simple Object Access Protocol", is a protocol you use to talk to web services.
So that constructor would be used when a webservice throws an exception and the system has to get the exception over the network to the client.
Just check the documentation on MSDN for the constructors you're calling with base(), such as Exception Constructor (String):
Initializes a new instance of the Exception class with a specified error message.
Or Exception Constructor (String, Exception):
Initializes a new instance of the Exception class with a specified error message and a reference to the inner exception that is the cause of this exception.
They're used to populate the exception-to-be-thrown with relevant information about the exception and its surroundings.
If you hate your fellow programmers, you only use the parameterless one.
I'm working on selenium with C# and using NUnit3.0 test framework and I need to implement a global exception handler in my test project, how to do it? any help appreciated.
You can create you own Custom exceptions like this:
public class CustomSeleniumException: Exception
{
public CustomSeleniumException()
{
}
public CustomSeleniumException(string message)
: base(message)
{
}
public CustomSeleniumException(string message, Exception inner)
: base(message, inner)
{
}
}
I'm not sure what you mean by
global exception handler
but MSDN gives basic guide here. IMHO having central place to manage thrown exceptions could be a bad idea. Exceptions are thrown in a certain scope and you need to catch those according to your flow. Sometimes you need to let Exceptions propagate higher up the call chain, rather than handling them right away. You could look at those Exception patterns before making the final decision. But if you still need such, try this Global Exception Handler.
I have a static class that retrieves values from app.config in its constructor. These could potentially be null, and I would like to throw an exception if this is the case.
I would like to throw the error in the static methods that use these values, but ArgumentNullException doesn't seem right as they are not arguments passed to the method.
Is there an alternative, or is this not a good approach?
It does not matter what you throw. It is not an exception that should ever be caught, catching it does not fix the .config file. Using a custom exception type only encourages a bad practice.
So don't, just throw Exception. Be sure to tell the reader what is wrong with the .config file, that's the only thing he needs to know. And that he can read it, write an event handler for AppDomain.CurrentDomain.UnhandledException
You can create your own custom exception (MSDN).
Basically:
public class ConfigurationValueMissingException : Exception
{
public ConfigurationValueMissingException()
{
}
public ConfigurationValueMissingException(string message)
: base(message)
{
}
public ConfigurationValueMissingException(string message, Exception inner)
: base(message, inner)
{
}
}
Why? If you follow Microsoft Code Analysis rules, you can't simply throw new Exception(); as that would be a violation of CA2201: Do not raise reserved exception types:
Do Not Throw General Exceptions
If you throw a general exception type, such as Exception or
SystemException in a library or framework, it forces consumers to
catch all exceptions, including unknown exceptions that they do not
know how to handle.
Instead, either throw a more derived type that already exists in the
framework, or create your own type that derives from Exception.
How to Fix Violations
To fix a violation of this rule, change the type of the thrown exception to a specific type that is not one of the reserved types.
When to Suppress Warnings
Do not suppress a warning from this rule.
This would be a custom exception that fully passes Code Analysis rules:
using System;
using System.Runtime.Serialization;
[Serializable]
public class ConfigurationValueMissingException : Exception
{
public ConfigurationValueMissingException()
{
}
public ConfigurationValueMissingException(string message)
: base(message)
{
}
public ConfigurationValueMissingException(string message, Exception inner)
: base(message, inner)
{
}
protected ConfigurationValueMissingException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
}
}
You can use any of the System.Configuration namespace exceptions. Or create your own ConfigurationParameterNullException
Create a class that inherits from Exception:
https://msdn.microsoft.com/en-us/library/87cdya3t(v=vs.110).aspx
public class NullConfigEntryException: Exception
And then throw a NullConfigEntryException when you find an empty one
A custom exception is the most informative, and you have control over what information it includes. A more generic approach is to use ApplicationException (the most generic being Exception). If you take the generic approach, be sure to add details in Message, Data, etc.
I am handling errors using IErrorHandler in WCF REST. I need to log class name, method name, line number, error code etc. and i find out the soultions to all this.
But I am thinking any possibility or options to get 1ErrorLevel1 like windows event viewer. Eg: Warning, Information, Error.
Actually if I do like this my applciation exceptions can be put as Information. This can be work simple create an custom Exception class.
But my question is for other exceptions (other than my application exceptions) any option to get this level based on the error. I don't need to set this level for other types of erros.
Actually i am logging the exception in HandleError event. Now i am just throw my exceptions as applicationexception.
Just see my Service method code below:
if(!long.TryParse("534543534", out value))
{
throw new ApplicationException("Input is Not Valid!!!");
}
So in my error handling i got this as application exception. Here i dont knwo this is because of FormatException, Overflow Exception, ArgumentNullException. How i handle this. I can add the original exception as innerexception but need to wrap try..catch in each service method to get the exception. Is this good practice when i have the IErrorHandler methods. Please suggest good approach for this
In .NET, an exception is a severe error that interrupts the process of your application. The framework does (for the most part) not provide an error level as all exceptions are basically errors. If an exception is thrown, this always means that there is an error that the application cannot continue with.
If you want to discern between the exception types and write some as informational messages or warnings to your log, you'd have to inspect the exceptions in your error handler, e.g. by code similar to this:
public class MyErrorHandler : IErrorHandler
{
// ...
private static readonly Dictionary<Type, TraceLevel> _exceptionTraceLevelMappings;
static MyErrorHandler()
{
_exceptionTraceLevelMappings = new Dictionary<Type, TraceLevel>();
_exceptionTraceLevelMappings.Add(typeof(ApplicationException), TraceLevel.Information);
_exceptionTraceLevelMappings.Add(typeof(ArgumentException), TraceLevel.Warning);
}
private static TraceLevel GetLevelByExceptionType(Type exType)
{
// You might want to add a more sophisticated approach here (e.g. for base classes)
if (_exceptionTraceLevelMappings.ContainsKey(exType))
return _exceptionTraceLevelMappings[exType];
return TraceLevel.Error;
}
// ...
}
Based upon the comments, you want to discern between errors that are raised to coding mistakes and input data validation errors. In this case, you'd need to implement a CustomException type and use TryParse to validate input data:
public class MyValidationException : Exception
{
public MyValidationException(string message)
: base(message)
{
}
// A custom exceptions needs several constructors, so add them also
}
In your service code, you'd use TryParse as in your sample:
if(!long.TryParse("534543534", out value))
{
throw new MyValidationException("Input is Not Valid!!!");
}
In the mapping dictionary, you can register your exception type and assign TraceLevel.Information:
// ...
_exceptionTraceLevelMappings.Add(typeof(MyValidationException), TraceLevel.Information);
// ...
I've got some UI code that looks like this:
try
{
SomeClass classInstance = new SomeClass(someId);
}
catch (Exception exception)
{
// Content wasn't created, show a message, stop processing
return;
}
It seems the try catch was added because the constructor for SomeClass would bomb out if the someId it receives isn't valid, and data couldn't be found in a DB.
Running this code through FXCop recently, it warns against using the general Exception, but all SomeClass does is throw a new Exception with a message to say it failed to initialize.
I guess the problem is that the class constructor should have it's own custom exception, which I could then handle in my UI, but I wonder what else I could do to the code above to handle the exception, that meets FXCop requirements?
FxCop's rule exists because the catch (Exception) block above catches all possible exceptions, including low-level exceptions like StackOverflowException that you probably can't catch in a useful way.
The right approach is definitely to throw a more specific type: either one you've invented, or an existing .NET framework exception type that closely matches your situation. (When in doubt, I normally go for InvalidOperationException.)
Alternatively, you could check the exact exception type when catching it. This won't prevent the FxCop warning, but it should address the underlying problem:
catch (Exception exception)
{
if (exception.GetType() == typeof(Exception))
{
// Content wasn't created, show a message, stop processing
return;
}
else
{
// Some other exception type that wasn't thrown from our code -
// delegate to a higher-level exception handler
throw;
}
}
You don't need a custom exception; just use one of the dozens that already exist in the framework for given circumstances. If someId is bad, throw an ArgumentException -- that's what it's made for. If something's null that shouldn't be, a NullReferenceException will occur; just let it be thrown. Etc. Throwing a plain Exception is a bit like saying "something went wrong -- read the message for details" rather than "this went wrong".
FxCop is complaining about catch (Exception) because it's too commonly abused to swallow up all exceptions rather than letting them propagate and be handled by code that knows how to do so. You should be able to say what types of exceptions are being thrown and catch those, while letting those you don't recognize make their way up the call stack.
You should fix the class constructor. Throwing Exception is never a good idea.
However, to work around the issue you have temporarily (as this is a horrible, unreliable hack), you could check the message of the exception against the one you're expecting:
catch (Exception exception)
{
if (exception.Message == "whatever your class sets the message to")
// Content wasn't created, show a message, stop processing
return;
else
// Any other exception should bubble
throw;
}
Using InvalidOperationException in place of throwing Exception sounds like it might be sensible.
If FXCop doesn't like handling the general Exception (and I tend to agree) then maybe you have access to SomeClass's source code. Modify the constructor to throw an exception that is more specific, e.g. ArgumentOutOfRangeException or some custom exception.
In that case your code would then look as follows:
try
{
SomeClass classInstance = new SomeClass(someId);
}
catch(ArgumentOutOfRangeException exception)
{
// Content wasn't created, show a message, stop processing
return;
}
As many others have said, the constructor should not be throwing a naked Exception. Seeing that the constructor retrieves data from DB and throws based on the result, the best solution is to create your own exception class.
Creating exceptions is super-easy in Visual studio. Just type in Exception and press TAB. It will then create the exception class with required constructors(all four of them). Do not be afraid to create classes that don't do very much, that's what they are designed for.
This is how I would write this class:
public class SomeClass {
public SomeClass(int someId) {
if (someId < 0) //validation on the ID, can it be negative?
throw new ArgumentException("someId", "ID cannot be negative");
//Perform DB operation
if (/*DB error - not found*/)
throw new DataNotFoundException("Cannot find record with ID " + someId);
}
}
[Serializable]
public class DataNotFoundException : Exception {
public DataNotFoundException() { }
public DataNotFoundException(string message) : base(message) { }
public DataNotFoundException(string message, Exception inner) : base(message, inner) { }
protected DataNotFoundException(
System.Runtime.Serialization.SerializationInfo info,
System.Runtime.Serialization.StreamingContext context)
: base(info, context) { }
}