Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I throw an exception and add in my own message containing a key and a value?

Tags:

c#

exception

I have methods that look like this:

public IDictionary<string, string> Delete(Account account)
{
    try { _accountRepository.Delete(account); }
    catch { _errors.Add("", "Error when deleting account"); }
    return _errors;
}

public IDictionary<string, string> ValidateNoDuplicate(Account ac)
{
    var accounts = GetAccounts(ac.PartitionKey);
    if (accounts.Any(b => b.Title.Equals(ac.Title) &&
                            !b.RowKey.Equals(ac.RowKey)))
        _errors.Add("Account.Title", "Duplicate");
    return _errors;
}

I would like to change this method so that it returns a bool and so it throws an exception if there is an error instead of:

_errors.Add("", "Error when deleting account");

Can someone explain to me how I can throw an exception and pass a message containing a key and a value. In this case the key would be "" and the value would be "Error when deleting account".

Also in the method that calls this. How would I catch the exception?

Would it be necessary for me to make my own class and somehow throw an exception based on this class?

like image 621
Samantha J T Star Avatar asked Dec 17 '11 07:12

Samantha J T Star


2 Answers

Create your own exception class, that can hold the data that you need:

public class AccountException : ApplicationException {

  public Dictionary<string, string> Errors { get; set; };

  public AccountException(Exception ex) : base(ex) {
    Errors = new Dictionary<string, string>();
  }

  public AccountException() : this(null) {}

}

In your methods you can throw the exception. Don't return an error status also, that is handled by the exception.

Don't throw away the exception that you get in the method, include that as InnerException, so that it can be used for debugging.

public void Delete(Account account) {
  try {
    _accountRepository.Delete(account);
  } catch(Exception ex) {
    AccountException a = new AccountException(ex);
    a.Errors.Add("", "Error when deleting account");
    throw a;
  }
}

public void ValidateNoDuplicate(Account ac) {
  var accounts = GetAccounts(ac.PartitionKey);
  if (accounts.Any(b => b.Title.Equals(ac.Title) &&
                            !b.RowKey.Equals(ac.RowKey))) {
    AccountException a = new AccountException();
    a.Errors.Add("Account.Title", "Duplicate");
    throw a;
  }
}

When calling the methods, you catch your exception type:

try {
  Delete(account);
} catch(AccountException ex) {
  // Handle the exception here.
  // The ex.Errors property contains the string pairs.
  // The ex.InnerException contains the actual exception
}
like image 152
Guffa Avatar answered Sep 19 '22 23:09

Guffa


The Exception class has a Data property that is a dictionary of key/value pairs.

IDictionary<string, string> errors;
...

if (errors.Count > 0)
{
    Exception ex = ... construct exception of the appropriate type
    foreach(string key in _errors.Keys)
    {
        ex.Data.Add(key, _errors[key]);
    }
    throw ex;
}

Note that it's generally considered to be good practice to use Exceptions that are Serializable, so that the objects you put into the Data dictionary should also be serializable. In your example, you're just putting in strings, so you'll be fine.

Would it be necessary for me to make my own class and somehow throw an exception based on this class?

It's certainly not necessary to create your own custom Exception class, and may not be desirable. The MSDN design guidelines for Exceptions gives guidelines on choosing which Exception type to throw.

In general, you should prefer to use one of the existing Exception types unless you have an error condition that can be programatically handled in a different way from existing Exception types.

like image 43
Joe Avatar answered Sep 18 '22 23:09

Joe