I have an MVC controller that uses a payment service class. Where should I do the exception handling? What is best practice?
Do I use try/catch blocks in both my controller and service class?
Is the exception just thrown again in the service class so it can be handled in the controller? Or should all the exception handling be done in the controller?
I can catch Stripe specific exceptions, should that be done in the service class or controller? Confused...
public async Task<IActionResult> DoSomething(MyViewModel model)
{
try
{
await _paymentService.UpdateSomethingAsync(id, token);
}
catch (Exception ex)
{
//handle
}
enter code here
}
public class PaymentService : IPaymentService
{
public async Task UpdateSomethingAsync(string id, string token)
{
try
{
//update using Stripe...
}
catch (Exception ex)
{
//TODO: Implement error handling
throw;
}
}
}
I guess exception handling must be at service level as it should be self capable of catching and handling all the exceptions(also, to log it at service level for later analysis) occurred at service level and throwing it in its original form (or as per the need it can be customized at service level) to the receiver.
Receiver (controller in this case) should have it's own error handling mechanism as it is a different layer of application and may require some manipulation over exceptions or it's logging at UI level. Here, note that if there is no manipulation or logging of exception or error is required you can directly show service level exception and remove catch from controller.
Hope it make sense.
just write the same code in catch which is in try{ } because catch never pass back or return the value .
try
{
cust_id = txtID.Text;
submit changes();
lblmessage.Text = "Data Save";
}
catch (Exception ex)
{
lblmessage.Text = "Saving error";
cust_id = txtID.Text;
submit changes();
}
Related
Some background before I get into my question. I am currently working on a project that is migrating from an IBM DB2 to a SQL Server. Not to get into too much detail, but this DB2 linked server sometimes disconnects with the SQL server, which is normal for linked servers. I have this working in code and have a process setup for this to take care of it.
Anyway, I am trying to write a Test Method that throws a DbException (which is the exception that is thrown when the linked server is not connected) to test the process which I wrote when the linked server is disconnected. Is there a way to force throw a certain type of exception so I can test my code?
The try catch block looks something like this:
try
{
//Regular Processing and attempt to update to DB2
}
catch (DbException ex)
{
//Other processing to catch a linked server issue
}
catch (Exception ex)
{
//Even more processing for other exceptions
}
It's the same method as most unit testing, Inject your dependency via an interface, put your real db logic in one class based on that interface, and your
test stuff in another based on that interface.
interface IDBProcessor
{
void Process()
}
class ThrowyClass : IDBProcessor
{
public Exception ThrowThis {get; set;}
public void Process()
{
throw ThrowThis;
}
}
void MyMethod(IDBProcessor processor)
{
try
{
processor.Process()
}
catch (DbException ex)
{
//Other processing to catch a linked server issue
}
catch (Exception ex)
{
//Even more processing for other exceptions
}
}
Then in your unit test, Make a ThrowyClass with the exception you want and pass it in. ( There are mocking frameworks that will save you from making a Test class if you like).
[Test]
void MyThrowTest()
{
var throwy = new ThrowyClass() { ThrowThis = new SomeSpecificException() };
var myClass = new MyClass()
myClass.MyMethod(throwy);
// Assert what you expect
}
You will have to customize things to your specific application. You may wish to inject the IProcessor in the constructor of "MyClass"
You can simply throw it like this way :
throw new DbException();
You should take a look at IDbConnection and try the Moq framework
your code should like the following
var dbConnectionMock = new Mock<IDbConnection>();
dbConnectionMock.Setup(x => x.Open())
.Callback(() => {
throw new SqlException();
}).Verifiable();
https://github.com/Moq/moq4/wiki/Quickstart
I am currently implementing log4net for catching my exceptions for web api controller.
I wanted to know how could i potentially catch all errors in any action within the controller?
I did not want to go through each action ideally and add try catch if it can be helped?
You need to register an IExceptionLogger
e.x.: GlobalConfiguration.Configuration.Services.Add(typeof(IExceptionLogger), new YourWebApiExceptionLogger());
You can implement a System.Web.Http.Filters.ActionFilterAttribute. In the OnActionExecuted you can handle your logging:
public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
{
if (actionExecutedContext.Response != null)
{
//ok
}
else
{
_logger.ErrorFormat("actionExecutedContext.Response == null will result in 500, unhandled exception"); //Add extra information here
}
}
Then you can add this ActionFilter as attribute to the methods you want to log.
Does the class Exception have an unique Id or any other unique modifier (GUID,... )?
I'm logging the generated exceptions inside a backend-service. But my goal is to only log each exception once.
Perhaps an example might of some use here:
The Service has 3 layers:
DAL (SQL-Interaction)
=> Exception A occurs here and is being logged into the database
BL (BusinessLayer)
=> Exception A is passed to here but isn't being logged
=> Exception B is thrown here and is being logged into the table
Services (Service Interface)
=> Exception A is passed to here but isn't being logged
=> Exception B is passed to here but isn't being logged
...
Client-solutions
My current solution (which i personnally really don't like):
I've written a own exception (inherits from the base class exception). when any exception is thrown for the first time then its being logged. Then its being cast to my own exception and rethrown. Exceptions of type of my own exceptions are nog logged in the database
example (This is pseudo code)
DAL - Layer
try{}
catch (Exception e)
{
// log in database
// log in logfile
// Cast to OwnException
// rethrown as OwnException
}
BL - Layer
try{}
catch (OwnException e)
{
// log in logfile
// rethrow e
}
catch (Exception e)
{
// log in database
// log in logfile
// Cast to OwnException
// rethrow as OwnException
}
Update: What i'm actually looking for is an Id/unique modifier. I would scan the database for the presence of this id. And if this id isn't present then i would write a record. If its present then it would just be rethrown.
You can create your Exception and create a new propertie boolean as "Logged" , when you log the exception you set true to "Logged" and in your anothers layers before log you need to verify if is not logged.
public class YourException : ApplicationException
{
public YourException () { }
public YourException (string message) : base(message) { }
public YourException (string message, Exception innerException) : base(message, innerException) { }
public bool LoggedInLogFile { get; set; }
public bool LoggedInDataBase { get; set; }
}
In your DAL:
try{}
catch (Exception e)
{
// log in database
// log in logfile
var ex = new YourException (e.Message);
ex.LoggedInLogFile = true;
ex.LoggedInDataBase = true;
throw ex;
}
In your Service Layer:
try{}
catch (YourException e)
{
if(!e.LoggedInLogFile)
//Log in file
if(!e.LoggedInDataBase)
//Log in Database
}
I wouldnt create my own custom exception. What I would do is explicitly catch the exceptions I know can occur in the DAL, For example an SQLException. In the BL catch specific exceptions that can occur there, and let the rest propogate upwards.
It is unlikely that your BL and DAL would need to log the same exceptions, seperate them so each of them catches the set they are responsible for, and then rethrow them so the client UI can catch them.
Edit
Forgot to mention, make sure when you rethrow to use:
throw,
And not:
throw ex;
So you wont lose your stacktrace
In one of my classes I have a call to a repository which has some error handling on it. I would like to refactor the error handling code because it is quite repetitive and the only thing that really changes is the message.
My code currently looks something like this:
public IList<User> GetUser()
{
try
{
return _repository.GetUsers();
}
catch (WebException ex)
{
ErrorMessages.Add("...");
_logger.ErrorException("...", ex);
}
catch (SoapException ex)
{
ErrorMessages.Add("...");
_logger.ErrorException("...", ex);
}
... etc
}
I could replace those lines in my catch block with a call to another method which takes an error message value and a logger message value. However I suppose I could also do this using an Action<> parameter but I am very inexperienced at using Func<> and Action<> and don't really see what benefit I would have using one of those over a method.
My question is really what is the best way to refactor this code and why does one way benefit over the other (as per my example above).
Thanks for any help.
You can use lambdas to help with this.
If you define your general-purpose error handler to accept a parameter of type Action then you can call that action in the error handler.
You don't need to worry about return values because the lambda you write at the point of call can take care of that.
For example, your general handler could look like this:
public void AttemptAction(Action action)
{
try
{
action();
}
catch (WebException ex)
{
ErrorMessages.Add("...");
_logger.ErrorException("...", ex);
// Rethrow?
}
catch (SoapException ex)
{
ErrorMessages.Add("...");
_logger.ErrorException("...", ex);
// Rethrow?
}
}
And then you could use it like this:
public IList<User> GetUser()
{
IList<User> result = null;
AttemptAction(() => result = _repository.GetUsers());
return result;
}
Assuming the exception types are always the same but the messages are different, you can do this:
static public T Try<T>(string webMessage, string soapMessage, Func<T> func)
{
try
{
return func();
}
catch (WebException ex)
{
ErrorMessages.Add(webMessage);
_logger.ErrorException(webMessage, ex);
}
catch (SoapException ex)
{
ErrorMessages.Add(soapMessage);
_logger.ErrorException(soapMessage, ex);
}
}
This Try-method will use a delegate of type Func<T> to call a function and return its value. The function will be inside the same try-catch block. The messages are provides via parameters. Now, somewhere else in your code, you could call this like:
var users = Try("My web message.", "My soap message.", () => _repository.GetUsers());
Or, in your case even shorter (when not using parameters):
var users = Try("My web message.", "My soap message.", _repository.GetUsers);
Of course you can modify and arrange the parameters of Try to your own liking.
In case you are mixing method with and without return types, it is better not to use the Func but the Action. This will be able to comply to all situations:
static public void Try(string webMessage, string soapMessage, Action action)
{
try
{
action();
}
catch (WebException ex)
{
ErrorMessages.Add(webMessage);
_logger.ErrorException(webMessage, ex);
}
catch (SoapException ex)
{
ErrorMessages.Add(soapMessage);
_logger.ErrorException(soapMessage, ex);
}
}
But this solution makes the code a tiny bit more difficult to read / maintain:
IList<User> users;
Try("My web message.", "My soap message.", () => users = _repository.GetUsers());
You can use Aspect-Oriented Programming http://en.wikipedia.org/wiki/Aspect-oriented_programming.
The idea to place all repetitive code to special classes that are called aspect.
Your code will look like in PostSharp
[ExceptionLogger]
public IList<User> GetUser()
{
return _repository.GetUsers();
}
public class ExceptionLogger: OnMethodBoundaryAspect
{
//getting _logger and ErrorMessages
public override void OnException(MethodExecutionArgs args)
{
ErrorMessages.Add("...");
_logger.ErrorException("...", ex);
}
}
For c#, you ccan use PostSharp, Castle.Windsor or Unity frameworks.
I am developing a distributed application. In it, there are roles and sets of permissions that I must validate.
Is a good pratice to throw an exception, in per example, unauthorized access?
Or should I send some message back to the client?
On your service operation, you can specify a FaultContract that will serve both purposes like so:
[OperationContract]
[FaultContract(typeof(MyServiceFault))]
void MyServiceOperation();
Note that MyServiceFault must be marked with DataContract and DataMember attributes, in the same way you would a complex type:
[DataContract]
public class MyServiceFault
{
private string _message;
public MyServiceFault(string message)
{
_message = message;
}
[DataMember]
public string Message { get { return _message; } set { _message = value; } }
}
On the service-side, you are then able to:
throw new FaultException<MyServiceFault>(new MyServiceFault("Unauthorized Access"));
And on the client-side:
try
{
...
}
catch (FaultException<MyServiceFault> fault)
{
// fault.Detail.Message contains "Unauthorized Access"
}
Well, you can catch all exceptions in the WCF service implementations methods and rethrow them as FaultExceptions. By doing it this way, the exception will be rethrown on the client with a message of your choosing:
[OperationContract]
public List<Customer> GetAllCustomers()
{
try
{
... code to retrieve customers from datastore
}
catch (Exception ex)
{
// Log the exception including stacktrace
_log.Error(ex.ToString());
// No stacktrace to client, just message...
throw new FaultException(ex.Message);
}
}
To avoid having unexpected errors relayed back to the client, it's also a good practice to never throw Exception instances in code on the server-side. Instead create one or more of your own exception types and throw them. By doing so, you can distinguish between unexpected server processing errors and errors that are thrown due to invalid requests etc:
public List<Customer> GetAllCustomers()
{
try
{
... code to retrieve customers from datastore
}
catch (MyBaseException ex)
{
// This is an error thrown in code, don't bother logging it but relay
// the message to the client.
throw new FaultException(ex.Message);
}
catch (Exception ex)
{
// This is an unexpected error, we need log details for debugging
_log.Error(ex.ToString());
// and we don't want to reveal any details to the client
throw new FaultException("Server processing error!");
}
}
Throwing general Dot Net Exceptions would make the service client proxies and the server channel to go in faulted state if you are not using basicHTTPBinding ...To avoid that you should always throw FaultException from the service...
from you catch block just use:
throw new FaultException("Your message to the clients");