I am developing a MVC application.
I am trying to define my own exception classes. I am making this structure first time...
What else I have to add in my exception classes , like constructor or something , so it work well... ?
public ActionResult Edit(EmployeeVM employeeVM)
{
EmployeeService employeeService = new PartyService();
try
{
PartyService partyService = new PartyService();
partyService.Update(PartyVM);
}
catch (DuplicateEntityExcpetion e)
{
TempData["error"] = e + "Party you are trying to add is already exist.";
}
catch (InvalidDataException e)
{
TempData["error"] = e + "Data which you are trying to add is not valid.";
}
public class InvalidDataException : Exception
{
}
public class DuplicateEntityExcpetion : Exception
{
}
}
You must throw these exceptions from your service so that they get catched here.
throw new DuplicateEntityExcpetion("Your Query or Message");
throw new InvalidDataException ("Your Query or Message");
Also, it is a good practice to have a generic exception handled so that you have taken care of all exceptions.
catch (Exception e)
{
TempData["error"] = e + "Data which you are trying to add is not valid.";
}
Related
I have written a unit test class in C# for my MVC project.
The Test Method is following
[Test]
public void To_Add_DocumentStatusIsNull_ThrowsInvalidOperationException_ServiceTest()
{
try
{
_IDocumentStatusRepositoryMock = new Mock<IDocumentStatusRepository>();
_unitOfWorkMock = new Mock<IUnitOfWork>();
DocumentStatusService documentStatusService = new
DocumentStatusService(_unitOfWorkMock.Object,
_IDocumentStatusRepositoryMock.Object);
DocumentStatus documentStatus;
documentStatus = null;
_IDocumentStatusRepositoryMock.Setup(m => m.Add(documentStatus));
documentStatusService.Add(documentStatus);
Assert.Pass();
}
catch (Exception e)
{
throw new Exception(e.Message);
}
}
And the Service Method is following
public virtual void Add(TEntity entity)
{
try
{
if (entity == null)
{
throw new ArgumentNullException("entity");
}
_repository.Add(entity);
}
catch (Exception e)
{
throw new Exception(e.Message);
}
}
Now This test method only not passed due to the service class thrown ArgumentNullException.So how to handle the ArgumentNullException or How to make this test pass?
Please anybody help
If you are trying to check that the ArgumentNullException is working (which: it isn't currently). then it sounds like you want:
[Test, ExpectedException(typeof(ArgumentNullException), ExpectedMessage = #"Value cannot be null.
Parameter name: entity")]
public void To_Add_DocumentStatusIsNull_ThrowsInvalidOperationException_ServiceTest()
{
_IDocumentStatusRepositoryMock = new Mock<IDocumentStatusRepository>();
_unitOfWorkMock = new Mock<IUnitOfWork>();
DocumentStatusService documentStatusService = new
DocumentStatusService(_unitOfWorkMock.Object,
_IDocumentStatusRepositoryMock.Object);
DocumentStatus documentStatus;
documentStatus = null;
_IDocumentStatusRepositoryMock.Setup(m => m.Add(documentStatus));
documentStatusService.Add(documentStatus);
}
...
public virtual void Add(TEntity entity)
{
if (entity == null)
{
throw new ArgumentNullException("entity");
}
_repository.Add(entity);
}
Testing for the ArgumentNullException
If you remove the ill-advised
catch (Exception e)
{
throw new Exception(e.Message);
}
from your code to be tested (The current catch loses context of the error, and breaks the stack trace, see below), your test can be as simple as wrapping the invocation in an Assert.Throws<ArgumentNullException>():
[Test]
public void PassingANullEntityToAddMustThrowArgumentNullException()
{
var documentStatusService = new DocumentStatusService(...);
Assert.Throws<ArgumentNullException>(() => documentStatusService.Add(null));
}
Re: Your Exception Handler
In your service code, never catch an exception and rethrow it as you've done, as this will lose the stack trace (e.g. _repository.Add(entity); could throw as well.). You also aren't adding any value by throwing e.Message as this is already in the original exception (with additional info like stack trace and inner exception)
Bad:
catch (Exception e)
{
throw new Exception(e.Message);
}
Better: If you do catch and rethrow with some value, wrap the original as an inner exception:
catch (SqlException ex)
{
throw new Exception("Some value add here", ex);
}
or if you are just intercepting and allow to propagate:
catch (SqlException)
{
// Do some logging
throw;
}
Best to me would to let the exception propagate, unless you either adding value, or handling it.
I am assuming: Looking at the code this unit test should not pass. Adding a NULL to a list is in most cases not an intended behaviour.
I see 2 options:
A) You should add a try/catch to you Test metod.
try
{
_IDocumentStatusRepositoryMock.Setup(m => m.Add(documentStatus));
documentStatusService.Add(documentStatus);
}
catch (Exception )
{
Assert.Fail(); // or nothing is expected behaviour
}
B) Remove the try/catch block from the Test Method so you do not swallow the exception. (Every Test that does not fails or an Assert or thows an unhandeled exception automatically passes)
I have to make my own Exception Class for .NET project. Could somebody please help how can I use it in the code? I just to show to MessageBox to user that the images were not found. But I don't know where to do it. Hoping for a good answer.
class RijException : Exception
{
public RijException()
: base() { }
public RijException(string message)
: base(message) { }
public RijException(string format, params object[] args)
: base(string.Format(format, args)) { }
public RijException(string message, Exception innerException)
: base(message, innerException) { }
public RijException(string format, Exception innerException, params object[] args)
: base(string.Format(format, args), innerException) { }
}
Now I want to use it:
try
{
afbeeldingPictureBox.BackgroundImage =
Image.FromFile(#"..\..\Borden\Stilstaan en parkeren\Parkeren toegelaten.png");
}
catch (FileNotFoundException)
{
throw new RijException("Can't find the images");
}
Edit
try
{
try
{
afbeeldingPictureBox.BackgroundImage = Image.FromFile(#"..\..\Borden\Stilstaan en parkeren\Parkeren toegelaten.png");
}
catch (FileNotFoundException)
{
throw new RijException("ImageNotFound");
//MessageBox.Show("Afbeeldingen konden niet worden geladen");
}
}
catch (RijException)
{
MessageBox.Show("Not able to load the image...");
}
Your example could be improved, but before that let's take a more useful example.
Imagine that you have the following code:
class Program
{
static void Main(string[] args)
{
try
{
var processor = new FileProcessor();
processor.Run();
}
catch (RijException exception)
{
//what will I get here.
}
}
}
Which uses the following classes:
public class FileProcessor
{
private string _myFileName;
public void Run()
{
try
{
var fileLoader = new FileLoader();
Process(fileLoader.Load(_myFileName));
}
catch (FileNotFoundException)
{
throw new RijException("Can't find requested file");
}
}
private void Process(object file)
{
//some logic
}
}
public class FileLoader
{
public object Load(string myFileName)
{
//throws FileNotFoundException
}
}
So the call stack will be like this:
If we modify the code in the main method to print the stack trace, what do you think that we get?
try
{
var processor = new FileProcessor();
processor.Run();
}
catch (RijException exception)
{
Console.WriteLine(exception.StackTrace);
}
The correct answer is:
See? The stack trace shows that the error happened in FileProcessor while it really happened in FileLoader. The reason to that is this code:
catch (FileNotFoundException)
{
throw new RijException("Can't find requested file");
}
When you catch an exception and throw another one you must always include the original exception as the inner exception. Otherwise it will be hard to understand where the exception originally occurred.
catch (FileNotFoundException ex)
{
throw new RijException("Can't find requested file", ex); //includes inner
}
Another problem is the exception message: "Can't find requested file". Ask yourself. If you get that message in a log file, would you be able to figure out what went wrong? At least give some context information.
Finally you have another problem. Best practices for designing exceptions says that they should be able to get serialized. To do that you need to include the serialization constructor and mark the exception as serializable:
[Serializable]
public class RijException : Exception
{
public RijException(string message) : base(message)
{
}
public RijException(string message, Exception inner) : base(message, inner)
{
}
//serialization constructor
protected RijException(
SerializationInfo info,
StreamingContext context) : base(info, context)
{
}
Finally I would therefore write your exercise like this:
try
{
var filename = #"..\..\Borden\Stilstaan en parkeren\Parkeren toegelaten.png";
try
{
afbeeldingPictureBox.BackgroundImage = Image.FromFile(filename);
}
catch (FileNotFoundException exception)
{
throw new RijException("Failed to load " + filename, exception);
}
}
catch (RijException)
{
MessageBox.Show("Not able to load the image...");
//now you would have all information required
//to figure out where and why something went wrong.
}
Summary
Always include inner exceptions
Provide useful context information so that you can figure out what went wrong
Make sure that exceptions can be serialized.
It is generally not a great idea to catch an exception that you cannot do much about. Just catching the FileNotFoundException and then throwing a new RijException that essentially conveys the same information is not usually done.
I just to show to MessageBox to user that the images were not found. But I don't know where to do it.
The most direct way to restructure your code to show the message box is
catch (FileNotFoundException)
{
MessageBox.Show("Can't find the images.");
//Don't do this: throw new RijException("Can't find the images");
}
You really do not want your custom RijException to take on the responsibility of displaying the MessageBox.
When an exception is possible to be thrown in a finally block how to propagate both exceptions - from catch and from finally?
As a possible solution - using an AggregateException:
internal class MyClass
{
public void Do()
{
Exception exception = null;
try
{
//example of an error occured in main logic
throw new InvalidOperationException();
}
catch (Exception e)
{
exception = e;
throw;
}
finally
{
try
{
//example of an error occured in finally
throw new AccessViolationException();
}
catch (Exception e)
{
if (exception != null)
throw new AggregateException(exception, e);
throw;
}
}
}
}
These exceptions can be handled like in following snippet:
private static void Main(string[] args)
{
try
{
new MyClass().Do();
}
catch (AggregateException e)
{
foreach (var innerException in e.InnerExceptions)
Console.Out.WriteLine("---- Error: {0}", innerException);
}
catch (Exception e)
{
Console.Out.WriteLine("---- Error: {0}", e);
}
Console.ReadKey();
}
I regularly come into the same situation and have not found a better solution yet. But I think the solution suggested by the OP is eligible.
Here's a slight modification of the original example:
internal class MyClass
{
public void Do()
{
bool success = false;
Exception exception = null;
try
{
//calling a service that can throw an exception
service.Call();
success = true;
}
catch (Exception e)
{
exception = e;
throw;
}
finally
{
try
{
//reporting the result to another service that also can throw an exception
reportingService.Call(success);
}
catch (Exception e)
{
if (exception != null)
throw new AggregateException(exception, e);
throw;
}
}
}
}
IMHO it will be fatal to ignore one or the other exception here.
Another example: Imagin a test system that calibrates a device (DUT) and therefore has to control another device that sends signals to the DUT.
internal class MyClass
{
public void Do()
{
Exception exception = null;
try
{
//perform a measurement on the DUT
signalSource.SetOutput(on);
DUT.RunMeasurement();
}
catch (Exception e)
{
exception = e;
throw;
}
finally
{
try
{
//both devices have to be set to a valid state at end of the procedure, independent of if any exception occurred
signalSource.SetOutput(off);
DUT.Reset();
}
catch (Exception e)
{
if (exception != null)
throw new AggregateException(exception, e);
throw;
}
}
}
}
In this example, it is important that all devices are set to a valid state after the procedure. But both devices also can throw exceptions in the finally block that must not get lost or ignored.
Regarding the complexity in the caller, I do not see any problem there either. When using System.Threading.Tasks the WaitAll() method, for example, can also throw AgregateExceptions that have to be handled in the same way.
One more note regarding #damien's comment: The exception is only caught to wrap it into the AggregateException, in case that the finally block throws. Nothing else is done with the exception nor is it handled in any way.
For those who want to go this way you can use a little helper class I created recently:
public static class SafeExecute
{
public static void Invoke(Action tryBlock, Action finallyBlock, Action onSuccess = null, Action<Exception> onError = null)
{
Exception tryBlockException = null;
try
{
tryBlock?.Invoke();
}
catch (Exception ex)
{
tryBlockException = ex;
throw;
}
finally
{
try
{
finallyBlock?.Invoke();
onSuccess?.Invoke();
}
catch (Exception finallyBlockException)
{
onError?.Invoke(finallyBlockException);
// don't override the original exception! Thus throwing a new AggregateException containing both exceptions.
if (tryBlockException != null)
throw new AggregateException(tryBlockException, finallyBlockException);
// otherwise re-throw the exception from the finally block.
throw;
}
}
}
}
and use it like this:
public void ExecuteMeasurement(CancellationToken cancelToken)
{
SafeExecute.Invoke(
() => DUT.ExecuteMeasurement(cancelToken),
() =>
{
Logger.Write(TraceEventType.Verbose, "Save measurement results to database...");
_Db.SaveChanges();
},
() => TraceLog.Write(TraceEventType.Verbose, "Done"));
}
As the comments have suggested this may indicate "unfortunately" structured code. For example if you find yourself in this situation often it might indicate that you are trying to do too much within your method. You only want to throw and exception if there is nothing else you can do (your code is 'stuck' with a problem you can't program around. You only want to catch an exception if there is a reasonable expectation you can do something useful. There is an OutOfMemoryException in the framework but you will seldom see people trying to catch it, because for the most part it means you're boned :-)
If the exception in the finally block is a direct result of the exception in the try block, returning that exception just complicates or obscures the real problem, making it harder to resolve. In the rare case where there is a validate reason for returning such as exception then using the AggregateException would be the way to do it. But before taking that approach ask yourself if it's possible to separate the exceptions into separate methods where a single exception can be returned and handled (separately).
I am creating a utility class that will be used in my Facebook application for tasks that are commonly done, such as retrieving a Facebook Page ID from a URL. I am unsure if the below code is the correct way to throw and catch exceptions. Could someone please advise, thanks.
Utility Class:
public static class FacebookUtilities
{
public static string GetPageIDFromGraph(string pageUri, string accessToken)
{
try
{
FacebookClient client = new FacebookClient(accessToken);
dynamic result = client.Get(GetPageIDFromUri(pageUri), new { fields = "id" });
return result.ToString();
}
catch (FacebookOAuthException)
{
throw;
}
catch (FacebookApiException)
{
throw;
}
}
public static string GetPageIDFromUri(string pageUri)
{
if (pageUri.Contains('/'))
pageUri = pageUri.Substring(pageUri.LastIndexOf('/') + 1);
if (pageUri.Contains('?'))
return pageUri.Substring(0, pageUri.IndexOf('?'));
else
return pageUri;
}
}
Program class, just testing:
- Note "input" and "output" are just textboxes.
private void btnGetPageID_Click(object sender, EventArgs e)
{
try
{
output.Text = FacebookUtilities.GetPageIDFromGraph(input.Text, "Some Access Token Goes Here");
}
catch (FacebookOAuthException ex)
{
if (ex.ErrorCode == 803)
{
output.Text = "This page does not exist";
}
}
catch (FacebookApiException ex)
{
if (ex.ErrorCode == 100)
{
output.Text = "The request was not supported. The most likely cause for this is supplying an empty page ID.";
}
}
}
Is it correct to simply rethrow the exception from the utility class so that the calling class can catch it and do what needs to be done?
It seems that you do nothing with catched exceptions - so dont catch them. There are a lot of discussions about exception handling, but in general you should catch exceptions when you have something to do with them, or at least using finally to clean up resourses.
Since you aren't handling the exceptions in any way, your code can just be:
public static string GetPageIDFromGraph(string pageUri, string accessToken)
{
FacebookClient client = new FacebookClient(accessToken);
dynamic result = client.Get(GetPageIDFromUri(pageUri), new { fields = "id" });
return result.ToString();
}
You should only catch exceptions when you can meaningfully handle them, and it doesn't look like you can in your GetPageIDFromGraph method, so you should just propagate them.
Following the tutorial here
http://beyondrelational.com/modules/2/blogs/79/posts/11543/throwing-exceptions-from-wcf-service-faultexception.aspx
I ended up wit the following code:
Interface:
[ServiceContract]
public interface IAuthenticator
{
[OperationContract]
[FaultContract(typeof(AuthenticationException))]
Account authenticateApplication(string userName, string Password);
}
Exception:
[DataContract]
public class AuthenticationException
{
private string validationError;
[DataMember]
public string ValidationError
{
set { validationError = value; }
get { return validationError; }
}
public AuthenticationException(string valError)
{
validationError = valError;
}
}
And finally this is how I throw errors in my implementation of authenticateApplication:
catch (InvalidUsernameException)
{
throw new FaultException<AuthenticationException>(new AuthenticationException("The username you entered could not be found in our database."), new FaultReason("Error"));
}
The problem with this is that instead of sending the error back to the client, the app WCF app is crashing saying I didn't handle the exception.
If it matters, here is how I call from my client:
try
{
myAcc = httpProxy.authenticateApplication("some text", "some other text");
}
catch (FaultException<AuthenticationException> ex)
{
MessageBox.Show(ex.Detail.ValidationError);
return;
}
Edit: Here is my stack trace:
at AuthenticatorService.Authenticator.authenticateApplication(String userName, String Password) in E:\Miscellaneous\Applications\Web 2.0 Creator\AuthenticatorService\AuthenticatorService\AuthenticatorService\Authenticator.cs:line 109
at SyncInvokeauthenticateApplication(Object , Object[] , Object[] )
at System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(Object instance, Object[] inputs, Object[]& outputs)
Edit Edit:
Here is the full try catch block:
try
{
using (myConnection)
{
using (myCommand)
{
//Tell it to execute the stored procedure on the database
myCommand.CommandText = "findUsername";
myCommand.CommandType = CommandType.StoredProcedure;
myCommand.Parameters.Add("#userName", SqlDbType.NVarChar, 20);
myCommand.Parameters["#userName"].Value = userName;
//If the reader returns 0 rows, that means the username doesn't exist in the database, so step there and return an exception
using (myReader)
{
myReader = myCommand.ExecuteReader();
if (myReader.HasRows == false)
{
InvalidUsernameException iue = new InvalidUsernameException();
throw iue;
}
else //Else we store the fields
{
myAcc.Password = myReader[1].ToString();
isActive = Convert.ToBoolean(myReader[2]);
myAcc.Key = myReader[3].ToString();
myAcc.ExpiryDate = myReader[4].ToString();
}
}
}
}
}
catch (SqlException)
{
throw new FaultException<AuthenticationException>(new AuthenticationException("There was an error while connecting the database, please contact support."), new FaultReason("Error"));
}
catch (InvalidOperationException)
{
throw new FaultException<AuthenticationException>(new AuthenticationException("An error in the program while connecting to the database."), new FaultReason("Error"));
}
catch (InvalidUsernameException)
{
throw new FaultException<AuthenticationException>(new AuthenticationException("The username you entered could not be found in our database."), new FaultReason("Error"));
}
catch (Exception)
{
throw new FaultException<AuthenticationException>(new AuthenticationException("There was a general error during the process."), new FaultReason("Error"));
}
Try adding a parameterless constructor to the AuthenticationException class. Or:
[DataContract]
public class AuthenticationException
{
[DataMember]
public string ValidationError { get; set; }
}
and in your service:
throw new FaultException<AuthenticationException>(
new AuthenticationException
{
ValidationError = "The username you entered could not be found in our database."
},
new FaultReason("Error")
);
Also bare in mind that this works only for exceptions that are occuring inside the try/catch block. If there's some other exception occurring in some other part of the service that is not translated to a FaultContract you won't catch it as FaultException<T> on the client.
Also it is recommended to centralize the exception handling of your WCF service at a single location by using a custom IErrorHandler that will propagate the faults instead of putting try/catch blocks all around your code.
Looks like you need to call myReader.Read before accessing its fields.
I found the answer to my problem at this page:
http://sergecalderara.wordpress.com/2008/11/25/systemservicemodelfaultexception1-was-unhandled-by-user-code/
You need to disable these visual studio options: