Class Level Error Handler For DAO - c#

I am using Entity Framework. Below is an example of a list method for an Actors context in my ActorsDao class. If you imagine my application is like imdb, there will be CRUD methods for various other contexts such as Movies, Directors, Genres, Reviews, Studios etc.
Regardless of the method or context, I handle errors in the same way. Due to my many methods across many contexts, my catch section is always exactly the same.
Obviously, I could create an error handling class, put the code in there, and just call a method in that class from the catch block.
However, I'm wondering if there a way to omit the TRY...CATCH from each method and set up a global error handler for the methods in my entity framework layer?
I would only want this global error handler to handle these errors and not errors from the rest of the application.
I seem to remember in Java Spring, you could annotate a class or method with the name of a method, and all errors would be passed to that without the need of a TRY...CATCH. I'm wondering if there is something similar for .NET (or a third party library with such functionality)?
public List<Actor> ListActors()
{
List<Actor> actorList = new List<Actor>();
using (var context = new ActorContext())
{
try
{
actorList = context.Actors.ToList<Actor>();
}
catch (Exception e)
{
//Handle error code
}
}
return actorList;
}
EDIT
I did some more research and found this code from here https://stackoverflow.com/a/4851985/1753877
private void GlobalTryCatch(Action action)
{
try
{
action.Invoke();
}
catch (ExpectedException1 e)
{
throw MyCustomException("Something bad happened", e);
}
catch (ExpectedException2 e)
{
throw MyCustomException("Something really bad happened", e);
}
}
public void DoSomething()
{
GlobalTryCatch(() =>
{
// Method code goes here
});
}
Would using a delegate like this be OK? It certainly meets my requirements.

You can create a class like this and extend the controller from this class.
Error Handler class looks like this :
package com.wes.essex.rest;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Set;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import com.wes.essex.bean.ErrorResponse;
public class SkyNewsController {
private static final Logger LOGGER = LoggerFactory.getLogger(SkyNewsController.class);
#ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> handleError(Exception ex) {
LOGGER.info("start");
LOGGER.error(ex.getMessage(), ex);
ErrorResponse error = new ErrorResponse();
error.setTimestamp(ZonedDateTime.now().format(DateTimeFormatter.ISO_INSTANT));
LOGGER.debug("error : {} ", error);
ResponseEntity<ErrorResponse> response = null;
if (ex instanceof ConstraintViolationException) {
error.setReasonCode(HttpStatus.BAD_REQUEST.value());
ConstraintViolationException constraintException = (ConstraintViolationException) ex;
Set<ConstraintViolation<?>> set = constraintException.getConstraintViolations();
String errorMessage = "Input Validation Failed:";
for (ConstraintViolation<?> constraintViolation : set) {
errorMessage += constraintViolation.getMessageTemplate() + ",";
}
errorMessage = errorMessage.substring(0, errorMessage.length() - 1);
error.setErrorMessage(errorMessage);
response = new ResponseEntity<ErrorResponse>(error, HttpStatus.BAD_REQUEST);
} else {
error.setReasonCode(HttpStatus.INTERNAL_SERVER_ERROR.value());
error.setErrorMessage(ex.getMessage());
response = new ResponseEntity<ErrorResponse>(error, HttpStatus.INTERNAL_SERVER_ERROR);
}
return response;
}
}
This would be the baean class for error response :
package com.wes.essex.bean;
public class ErrorResponse {
private static final long serialVersionUID = 5776681206288518465L;
private String timestamp;
private String errorMessage;
private int reasonCode;
public String getErrorMessage() {
return errorMessage;
}
public void setErrorMessage(String errorMessage) {
this.errorMessage = errorMessage;
}
public int getReasonCode() {
return reasonCode;
}
public void setReasonCode(int reasonCode) {
this.reasonCode = reasonCode;
}
public String getTimestamp() {
return timestamp;
}
public void setTimestamp(String timestamp) {
this.timestamp = timestamp;
}
public static long getSerialversionuid() {
return serialVersionUID;
}
}

Related

How to create a exception handling and logging class in C#

I am working on a small project, I am trying to create a layer that will handle exception and logging.
This layer will sit in between User interface and DAL, mostly like BAL which will have some generic method that will then initiate further call to Data access layer.
Some thing like this
Public Class ExceptionHandler
{
//which should take a method name,parameters and return a object.
Public T InitiateDatabaseCall(//method name as input,parameters)
{
try
{
//then make the call to the method using the input parameter and pass the parameters
}
catch(Exception e)
{
// do logging
}
}
This layer will act as center repository to handle and log exception. I am not able to create the method that i described can experts provide some snippet that will show case this scenario.
Edited: With code added
static void Main(string[] args)
{
BAL b = new BAL();
var ll = b.GetFieldList("xxxxyyyy");
}
public class BAL
{
public List<Fields> GetFieldList(string screen)
{
if(!string.IsNullOrEmpty(screen))
{
ExceptionHandler.InitiateCall(() =>GetList(screen) ));
}
}
}
public static class ExceptionHandler
{
public T InitiateCall<T>(Func<T>method,object[] parms) where T : object
{
try
{
return method.Invoke();
}
catch(Exception ex)
{
return default(T);
}
}
}
public class DAL
{
public List<Fields> GetList(string name)
{
VipreDBDevEntities context = new VipreDBDevEntities();
return context.Database.SqlQuery<Fields>("SCREEN_FIELDS_SELECT #SCREEN_NAME", name).ToList();
}
}
It gives error GetList() does not exist in current context.
For these kind of things AOP (Aspect Oriented Programming, see https://en.wikipedia.org/wiki/Aspect-oriented_programming) is a really good fit.
These are cross-cutting concerns that are cluttering code if not done properly.
See for an example AOP framework PostSharp. Even with the free version that is simple to code. There are also (might be paid) build-in aspects for that, like http://doc.postsharp.net/exception-tracing.
A simple alternative is using a Func or Action (try it out in a Console App):
static void Main(string[] args)
{
ExceptionHandler.InitiateDatabaseCall(() => CallDb("Dummy"));
ExceptionHandler.InitiateDatabaseCall<int>(() => { throw new InvalidOperationException(); });
}
int CallDb(string justToShowExampleWithParameters)
{
return 5;
}
public static class ExceptionHandler
{
public static T InitiateDatabaseCall<T>(Func<T> method)
{
try
{
return method.Invoke();
}
catch (Exception e)
{
// do logging
Console.WriteLine(e.Message);
return default(T); // or `throw` to pass the exception to the caller
}
}
}
Edit:
based on your added code in the question you can solve the error about GetList() by some minor modifications:
static void Main(string[] args) {
BAL b = new BAL();
var ll = b.GetFieldList("xxxxyyyy");
}
public class BAL
{
public List<Fields> GetFieldList(string screen)
{
if (!string.IsNullOrEmpty(screen))
{
return ExceptionHandler.InitiateCall(() => new DAL().GetList(screen)); // Slight modification of your code here
}
else
{
return null; // or whatever fits your needs
}
}
}
public class ExceptionHandler
{
public static T InitiateCall<T>(Func<T> method)
{
try
{
return method.Invoke();
}
catch (Exception ex)
{
//log
return default(T);
}
}
}
public class DAL
{
public List<Fields> GetList(string name)
{
VipreDBDevEntities context = new VipreDBDevEntities();
return context.Database.SqlQuery<Fields>("SCREEN_FIELDS_SELECT #SCREEN_NAME", name).ToList();
}
}
You don't need the object[] parms parameter in InitiateCall given the provided code. Any paramaters you need for the method call are given in the Func<T>
Personally, I think loging should be done in two ways:
Step logging (when you log some step in your code)
Scope logging (when you log begin/end of some code or it's time)
So, I always choose to create ILogger class with these two ways:
public sealed class Logger : ILogger
{
private readonly Serilog.ILogger _seriLogger;
public Logger(Serilog.ILogger seriLogger)
{
_seriLogger = seriLogger;
}
public void Debug(string format, params object[] args)
{
_seriLogger.Debug(format, args);
}
public void Info(string format, params object[] args)
{
_seriLogger.Information(format, args);
}
public void Warn(string format, params object[] args)
{
_seriLogger.Warning(format, args);
}
public void Error(Exception e, string format, params object[] args)
{
_seriLogger.Error(e, format, args);
}
public void Fatal(Exception e, string format, params object[] args)
{
_seriLogger.Fatal(e, format, args);
}
public IDisposable GetScope(string name, long timeout = 0)
{
return new LoggerScope(this, name, timeout);
}
}
internal class LoggerScope : IDisposable
{
private readonly ILogger _logger;
private readonly string _name;
private readonly long _timeout;
private readonly Stopwatch _sw;
private bool ExceedScope
{
get { return _timeout > 0; }
}
public LoggerScope(ILogger logger, string name, long timeout)
{
_logger = logger;
_name = name;
_timeout = timeout;
if (!ExceedScope)
{
_logger.Debug("Start execution of {0}.", name);
}
_sw = Stopwatch.StartNew();
}
public void Dispose()
{
_sw.Stop();
if (ExceedScope)
{
if (_sw.ElapsedMilliseconds >= (long)_timeout)
{
_logger.Debug("Exceeded execution of {0}. Expected: {1}ms; Actual: {2}ms.", _name, _timeout.ToString("N"), _sw.Elapsed.TotalMilliseconds.ToString("N"));
}
}
else
{
_logger.Debug("Finish execution of {0}. Elapsed: {1}ms", _name, _sw.Elapsed.TotalMilliseconds.ToString("N"));
}
}
}
Then, If I want to log something, I use it like this, without AOP:
using(_log.GetScope("Some describable name"))
{
//Some code here
}

Catch derived class Exceptions in base class with different methods and arguments

I'm trying to make something like base "exception handler" thing. So this base class will try-catch exceptions when any method (with any number of parameters) in derived class gets invoked. I'm not good in describing this with words, so here is the scenario:
public abstract BaseClass
{
Exception _ex;
public Exception LastKnownException
{
get
{
return this._ex;
}
}
//...
//what do I do here to assign the value of above property when some random exception occur in derived class?
//...
//The closest I can get...
public void RunMethod(Action method)
{
try
{
method.Invoke();
}
catch (Exception ex)
{
this._ex = ex;
}
}
}
public class DerivedClass : BaseClass
{
public void DoRandomMethod(int couldBeOfAnyTypeHere, bool andIndefiniteNumberOfThese)
{
bool result = false;
var someObject = new OtherClass(couldBeOfAnyTypeHere, out andIndefiniteNumberOfThese);
someObject.DoInternalWork(result); // <-- here is where I need the base class to take care if any exception should occur
}
public int AnotherMethod(int? id)
{
if (!id.HasValue)
id = Convert.ToInt32(Session["client_id"]);
var someOtherObject = new OtherClassB(id.Value);
return someOtherObject.CheckSomething(); // <-- and catch possible exceptions for this one too
}
//The closest I can get... (see base class implementation)
public List<RandomClass> GetSomeListBy(int id)
{
RunMethod(() =>
string[] whateverArgs = new[] { "is", "this", "even", "possible?" };
YetAnotherStaticClass.GetInstance().ExecuteErrorProneMethod(whateverArgs); // <-- Then when something breaks here, the LastKnownException will have something
);
}
}
public class TransactionController : Controller
{
public ActionResult ShowSomething()
{
var dc = new DerivedClass();
dc.DoRandomMethod(30, true);
if (dc.LastKnownException != null)
{
//optionally do something here
return RedirectToAction("BadRequest", "Error", new { ex = dc.LastKnownException });
}
else
{
return View();
}
}
}
EDIT: My simple approach will work, only, I don't want to have to wrap all methods with this lambda-driven RunMethod() method all the time -- I need the base class to somehow intercept any incoming exception and return the Exception object to the derived class without throwing the error.
Any ideas would be greatly appreciated. And thanks in advance!
I think you should consider using the event System.AppDomain.UnhandledException
This event will be raised whenever an exception occurs that is not handled.
As you don't clutter your code with the possibilities of exception, your code will be much better readable. Besides it would give derived classes the opportunity to catch exceptions if they expect ones, without interfering with your automatic exception catcher.
Your design is such, that if someone calls several functions of your derived class and then checks if there are any exceptions the caller wouldn't know which function caused the exception. I assume that your caller is not really interested in which function causes the exception. This is usually the case if you only want to log exception until someone investigates them.
If that is the case consider doing something like the following:
static void Main(string[] args)
{
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
}
static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
var ex = e.ExceptionObject as Exception;
if (ex != null)
logger.LogException(ex);
// TODO: decide whether to continue or exit.
}
If you really want to do this only for your abstract base class
public abstract BaseClass
{
private List<Exception> unhandledExceptions = new List<Exception>();
protected BaseClass()
{
AppDomain.CurrentDomain.UnhandledException += UnhandledException;
}
private void UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
var ex = e.ExceptionObject as Exception;
if (ex != null)
this.UnhandledExceptions.Add(ex);
}
public List<Exception> LastKnownExceptions
{
get { return this.unhandledExceptions; }
}
I had a similar requirement for catching exceptions, but used a specific implementation (i.e. not an abstract class) to encapsulate the handling of errors.
Please note this takes in an argument for any expected exceptions (params Type[] catchableExceptionTypes), but of course you can modify to suit your own requirements.
public class ExceptionHandler
{
// exposes the last caught exception
public Exception CaughtException { get; private set; }
// allows a quick check to see if an exception was caught
// e.g. if (ExceptionHandler.HasCaughtException) {... do something...}
public bool HasCaughtException { get; private set; }
// perform an action and catch any expected exceptions
public void TryAction(Action action, params Type[] catchableExceptionTypes)
{
Reset();
try
{
action();
}
catch (Exception exception)
{
if (ExceptionIsCatchable(exception, catchableExceptionTypes))
{
return;
}
throw;
}
}
// perform a function and catch any expected exceptions
// if an exception is caught, this returns null
public T TryFunction<T>(Func<T> function, params Type[] catchableExceptionTypes) where T : class
{
Reset();
try
{
return function();
}
catch (Exception exception)
{
if (ExceptionIsCatchable(exception, catchableExceptionTypes))
{
return null;
}
throw;
}
}
bool ExceptionIsCatchable(Exception caughtException, params Type[] catchableExceptionTypes)
{
for (var i = 0; i < catchableExceptionTypes.Length; i++)
{
var catchableExceptionType = catchableExceptionTypes[i];
if (!IsAssignableFrom(caughtException, catchableExceptionType)) continue;
CaughtException = caughtException;
HasCaughtException = true;
return true;
}
return false;
}
static bool IsAssignableFrom(Exception exception, Type type)
{
if (exception.GetType() == type) return true;
var baseType = exception.GetType().BaseType;
while (baseType != null)
{
if (baseType == type) return true;
baseType = baseType.BaseType;
}
return false;
}
void Reset()
{
CaughtException = null;
HasCaughtException = false;
}
}

Avoid Try Catch Stements with custom ErrorHandler class - C#

I have a class which exposes some functionality,
and I want to ensure exceptions will be handled by a custom ErrorHandler class.
Currently I can achieve this by a try / catch statement per each method, and process the exception by the error handler there.
My question is if there is a better way / design pattern to do it.
Code:
public class BasicErrorHandler
{
public void ProcessException(Exception ex)
{
//Does error handling stuff
}
}
public class Manager
{
BasicErrorHandler _errorHandler;
public Manager()
{
_errorHandler = new BasicErrorHandler();
}
public void MethodA()
{
try
{
//Does Something
}
catch(Exception ex)
{
_errorHandler.ProcessException(ex);
}
}
public void MethodB()
{
try
{
//Does Something Else
}
catch(Exception ex)
{
_errorHandler.ProcessException(ex);
}
}
}
In keeping with DRY principles, you could just wrap your try...catch logic into into own method which takes a predicate of the actual work to do:
public class Manager
{
BasicErrorHandler _errorHandler;
public Manager()
{
_errorHandler = new BasicErrorHandler();
}
public void MethodA()
{
DoWork( () => {
// do something interesting here
});
}
public void MethodB()
{
DoWork( () => {
// do something else interesting here
});
}
private void DoWork(Action action)
{
try
{
action();
}
catch(Exception ex)
{
_errorHandler.ProcessException(ex);
}
}
}
I've crafted this quickly and without thinking too much in the implications, but if you want to avoid all the try/catch blocks, you could do something like:
public class BasicErrorHandler
{
public void ProcessException(Exception ex)
{
//Does error handling stuff
}
public void Do(Action act)
{
try
{
act();
}
catch(Exception ex)
{
ProcessException(ex);
}
}
}
And then use it like:
public class Manager
{
BasicErrorHandler _errorHandler;
public Manager()
{
_errorHandler = new BasicErrorHandler();
}
public void MethodA()
{
_errorHandler.Do(() => {
//Does Something
});
}
public void MethodB()
{
_errorHandler.Do(() => {
//Does Something Else
});
}
}
Design patterns are there to solve a problem. Which problem are you trying to solve? What is wrong with the Try Catch blocks?
Only thing I can imagine is you want to have more clean code. Some answers suggest a helper method with an action. Given the helper methods that encapsulate a delegate: Do consider the impact on your stack trace and debugging sessions using these delegates. It might make logging etc more hard to understand.
If your intend is to do separation of concern, I would say If you can't handle it, just don't catch the exception. Let the class invoking the method handle it. If you insist to have a handler in your class, I would suggest Inversion of Control. That way, your class is not in control of determining which class should handle its exceptions.
Rx .net is for You. Advanced error handling gives You the ability to highly customize Your error handling. Check out the pages about that.
For example:
var source = new Subject<int>();
var result = source.Catch<int, TimeoutException>(tx=>Observable.Return(-1));
result.Dump("Catch");
source.OnNext(1);
source.OnNext(2);
source.OnError(new ArgumentException("Fail!"));
You'll get the following output:
Catch-->1
Catch-->2
Catch failed-->Fail!
The number of retries, the handling of how much time a method can take, everything can be configured.
The following is an Aspect oriented method of soling the problem, this makes use of PostSharp to do the weaving.
[Serializable]
public class HandleExceptionsAttribute : OnExceptionAspect {
/// <summary>
/// Initializes a new instance of the <see cref="HandleExceptionsAttribute"/> class.
/// </summary>
public HandleExceptionsAttribute() {
AspectPriority = 1;
}
public override void OnException(MethodExecutionArgs args) {
//Suppress the current transaction to ensure exception is not rolled back
using (var s = new TransactionScope(TransactionScopeOption.Suppress)) {
//Log exception
using (var exceptionLogContext = new ExceptionLogContext()) {
exceptionLogContext.Set<ExceptionLogEntry>().Add(new ExceptionLogEntry(args.Exception));
exceptionLogContext.SaveChanges();
}
}
}
}
[HandleExceptions]
public class YourClass {
}

Run C# code in Transaction

I called three methods on button click in asp.net
The First Method is to save a text file on the application
The Second Method is to create and save PdF file.
The Third Method is to send email in asp.net
I want that , If any of the above method has any error occured, then all the methods that are prevsouly called should be rollbacked.
How this is possible.??
In such simpler procedure, you do not need transaction as simple Try/Catch/Finally should do the job.
FileInfo localFile;
FileInfo pdfFile;
try{
SaveTextFile(localFile);
SavePDFFile(pdfFile);
SendEmail();
}catch{
// something went wrong...
// you can remove extra try catch
// but you might get security related
// exceptions
try{
if(localFile.Exists) localFile.Delete();
if(pdfFile.Exists) pdfFile.Delete();
}catch{}
}
Here is detailed Transaction Implementation.
This is little long process, but here is a simple implementation (single threaded approach with no locking etc). Remember this is simplest form of transaction with no double locking, no multi version concurrency.
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))
{
FileInfo localFile = new FileInfo("localFile.txt");
FileInfo pdfFile = new FileInfo("localFile.pdf");
SimpleTransaction.EnlistTransaction(
// prepare
() =>
{
CreateTextFile(localFile);
CreatePDFFile(pdfFile);
// prepare mail should throw an error
// if something is missing as sending email
// is network operation, it cannot be rolled back
// so email should be sent in commit
PrepareMail();
},
// commit
() =>
{
SendEmail();
},
// rollback
() =>
{
try
{
if (localFile.Exists)
localFile.Delete();
if (pdfFile.Exists)
pdfFile.Delete();
}
catch { }
},
// in doubt...
() => { }
);
}
public class SimpleTransaction : IEnlistmentNotification
{
public static void EnlistTransaction(Action prepare, Action commit, Action rollback, Action inDoubt)
{
var st = new SimpleTransaction(prepare, commit, rollback, inDoubt);
Transaction.Current.EnlistVolatile(st, EnlistmentOptions.None);
}
Action CommitAction;
Action PrepareAction;
Action RollbackAction;
Action InDoubtAction;
private SimpleTransaction(Action prepare, Action commit, Action rollback, Action inDoubt)
{
this.CommitAction = commit;
this.PrepareAction = prepare;
this.RollbackAction = rollback;
this.InDoubtAction = inDoubt ?? (Action)(() => {});
}
public void Prepare(PreparingEnlistment preparingEnlistment)
{
try
{
PrepareAction();
preparingEnlistment.Prepared();
}
catch
{
preparingEnlistment.ForceRollback();
}
}
public void Commit(Enlistment enlistment)
{
CommitAction();
enlistment.Done();
}
public void Rollback(Enlistment enlistment)
{
RollbackAction();
enlistment.Done();
}
public void InDoubt(Enlistment enlistment)
{
InDoubtAction();
enlistment.Done();
}
}
The reason this is different from Try Catch is that some other code can rollback transaction instead of raising exception.
Whether or not the operation succeeds, you should always be cleaning up files you create. If you can bypass the file system, and use a MemoryStream to store the data and include it in the email, that would of course both solve your problem and be alot faster.
As mentioned by others, there is no magic method to automatically rollback whatever you created since you clicked that button - you'll have to think of a solution yourself.
Most likely not the best solution, but a simple one, is to create a List<string> containing the files you have successfully written, and in the catch you simply delete all files from that list.
There are tons of other solutions, like a TemporaryFile class that deletes files in its Dispose() method. Give it a go and ask again when you run into issues with your attempt.
Here's another take for achieving what the OP wanted using IEnlistmentNotification.
But instead of writing all the operation (save text, save pdf, and send email) in one implementation class, this one use separate IEnlistmentNotification implementation and support for rollback in case of email sending operation failed.
var textPath = "somefile.txt";
var pdfPath = "somefile.pdf";
try {
using (var scope = new TransactionScope()) {
var textFileSave = new TextFileSave(textPath);
var pdfFileSave = new PDFFileSave(pdfPath);
Transaction.Current.TransactionCompleted += (sender, eventArgs) => {
try {
var sendEmail = new SendEmail();
sendEmail.Send();
}
catch (Exception ex) {
// Console.WriteLine(ex);
textFileSave.CleanUp();
pdfFileSave.CleanUp();
}
};
Transaction.Current.EnlistVolatile(textFileSave, EnlistmentOptions.None);
Transaction.Current.EnlistVolatile(pdfFileSave, EnlistmentOptions.None);
scope.Complete();
}
}
catch (Exception ex) {
// Console.WriteLine(ex);
}
catch {
// Console.WriteLine("Cannot complete transaction");
}
Here's the implementation details:
SendEmail
public class SendEmail {
public void Send() {
// uncomment to simulate error in sending email
// throw new Exception();
// write email sending operation here
// Console.WriteLine("Email Sent");
}
}
TextFileSave
public class TextFileSave : AbstractFileSave {
public TextFileSave(string filePath) : base(filePath) { }
protected override bool OnSaveFile(string filePath) {
// write save text file operation here
File.WriteAllText(filePath, "Some TXT contents");
return File.Exists(filePath);
}
}
PDFFileSave
public class PDFFileSave : AbstractFileSave {
public PDFFileSave(string filePath) : base(filePath) {}
protected override bool OnSaveFile(string filePath) {
// for simulating a long running process
// Thread.Sleep(5000);
// write save pdf file operation here
File.WriteAllText(filePath, "Some PDF contents");
// try returning false instead to simulate an error in saving file
// return false;
return File.Exists(filePath);
}
}
AbstractFileSave
public abstract class AbstractFileSave : IEnlistmentNotification {
protected AbstractFileSave(string filePath) {
FilePath = filePath;
}
public string FilePath { get; private set; }
public void Prepare(PreparingEnlistment preparingEnlistment) {
try {
var success = OnSaveFile(FilePath);
if (success) {
// Console.WriteLine("[Prepared] {0}", FilePath);
preparingEnlistment.Prepared();
}
else {
throw new Exception("Error saving file");
}
}
catch (Exception ex) {
// we vote to rollback, so clean-up must be done manually here
OnDeleteFile(FilePath);
preparingEnlistment.ForceRollback(ex);
}
}
public void Commit(Enlistment enlistment) {
// Console.WriteLine("[Commit] {0}", FilePath);
enlistment.Done();
}
public void Rollback(Enlistment enlistment) {
// Console.WriteLine("[Rollback] {0}", FilePath);
OnDeleteFile(FilePath);
enlistment.Done();
}
public void InDoubt(Enlistment enlistment) {
// in doubt operation here
enlistment.Done();
}
// for manual clean up
public void CleanUp() {
// Console.WriteLine("[Manual CleanUp] {0}", FilePath);
OnDeleteFile(FilePath);
}
protected abstract bool OnSaveFile(string filePath);
protected virtual void OnDeleteFile(string filePath) {
if (File.Exists(FilePath)) {
File.Delete(FilePath);
}
}
}
One thing worth mentioning about IEnlistmentNotification implementation is: if a resource called/ voted a ForceRollback() within the Prepare() method, the Rollback() method for that resource will not be triggered. So any cleanup that should have happen in Rollback() may need to be manually called in Prepare().

how can i set return so it accepts class1 or class2?

how can i, in my function start to fill the parameters for the class it is supposed to return, but if an exception occurs i'll return my error class instead?
public **** function()
{
try
{
Articles articles = new Articles();
articles.articleid = 234;
articles.articlename = "Milk";
articles.deleted = 0;
//continue fill Articles
//and an exception occurs
return articles;
}
catch (Exception e)
{
Errors Error = new Errors();
Error.exceptionmessage = e.Message;
Error.exceptionname = e.ToString();
Error.httpcode = 500;
return Error;
}
}
is this possible and a good thing to do? or should i just extend all return classes with my error class, even though i will return much info with allot of null values.
i would like to send as little data as possible and if my function fails i'll just send back the error.
UPDATE
sorry for not giving enough inforamtion about my situation this is a function that i want to use in a webservice
[OperationContract]
[WebGet(
ResponseFormat = WebMessageFormat.Json,
RequestFormat = WebMessageFormat.Json)]
**** Function();
so i dont think i can just throw an exception. i would like to return a class of articles if all is well so i dont have to convert my data to JSON but if something goes wrong i would like to send http code 500 Internal Server Error to the client.
i have not yet read all answers but i think i'll have to include my error class in all my other return classes so the client can now when something went wrong?
UPDATE:
That gives more insight on what you want to do. Since you can't throw exceptions, you should have a base result class. I usually do this for WCF methods I call through javascript, since it can't handle the exceptions nicely.
So you'll want a base class like:
[DataContract]
public class AjaxResult
{
public static AjaxResult GetSuccessResult()
{
return new AjaxResult();
}
[DataMember]
public int Status { get; set; }
[DataMember]
public string Error { get; set; }
}
Then you can inherit this, adding any data you would want to return. This example returns a single product object and a list of validation errors.
[DataContract]
public class SingleProductResult : AjaxResult
{
[DataMember]
public Product Data { get; set; }
[DataMember]
public IList<int> ValidationErrors { get; set; }
}
You can also opt to create a generic wrapper so you don't have to write to much code in your methods. I usually put this in a base class and let all WCF services inherit from that class.
protected T PerformAjaxOperation<T>(Func<T> action) where T : AjaxResult, new()
{
try
{
return action();
}
catch (AccessDeniedException ade)
{
// -- user tried to perform an invalid action
return new T()
{
Status = AjaxErrorCodes.AccessDenied,
Error = ade.ToString()
};
}
catch (Exception ex)
{
return new T()
{
Error = ex.ToString(),
Status = 1
};
}
}
Then just use it like so:
public SingleProductResult GetProduct(int productId)
{
return PerformAjaxOperation(() =>
{
return retval = new SingleProductResult()
{
Data = ProductServiceInstance.GetProduct(productId)
};
});
}
public AjaxResult DeleteProduct(int productId)
{
return PerformAjaxOperation(() => {
ProductServiceInstance.DeleteProduct(productId);
return AjaxResult.GetSuccessResult();
});
}
So, if everything proceeds smoothly, error will be 0 and message will be null. If an exception is thrown, then it will be caught by the PerformAjaxOperation() function and stuffed inside the AjaxResult object (or a derivative of it) and return to the client.
Previous answer:
I don't think this is a good idea. What you can do is create a custom exception by creating a class that inherits from Exception and add properties there that you want to save. Then when an exception occurs, you just catch it and stuff it inside this new exception along with other details. Then throw this exception instead. You can then catch this exception in the higher levels and display the proper message.
an example:
public IList<Articles> GetArticles()
{
try
{
return GetSomeArticlesFromDatabase();
}
catch (Exception innerException)
{
throw new MyCustomException("some data", 500, innerException);
}
}
public class MyCustomException : Exception
{
public int HttpCode { get; set; }
public MyCustomException(string errorMessage, int httpCode, Exception innerException)
: base(errorMessage, innerException) {
HttpCode = httpCode;
}
}
public void EntryPoint()
{
try
{
DoSomething();
var result = GetArticles();
DoSomething();
DisplayResult(result);
}
catch (MyCustomException ex)
{
ReturnHttpError(ex.Message, ex.HttpCode);
}
}
I would honestly advise against doing what you suggest. Instead, either use an existing Exception type or create a new subclass of Exception and throw it. You can even retain the causing exception information in the new exception's InnerException if so desired.
If the situation does not warrant an exception, however (you have not given enough details about what you are doing), you can create a Result class that contains error/warning information. This kind of thing would be better suited for warnings, though. That is, it is not an error condition that prevents things from continuing (exception), but instead a message that the calling code could choose to ignore without drastic side-effects.
For example:
class Result<T>
{
public Result(T Value, Errors Errors = null)
{
this.Value = Value;
this.Errors = Errors;
}
public T Value {get; private set;}
public Errors Errors {get; private set;}
}
Usage (as per your example code):
public Result<Articles> function()
{
try
{
Articles articles = new Articles();
articles.articleid = 234;
articles.articlename = "Milk";
articles.deleted = 0;
//continue fill Articles
//and an exception occurs
return new Result(articles);
}
catch (Exception e)
{
Errors Error = new Errors();
Error.exceptionmessage = e.Message;
Error.exceptionname = e.ToString();
Error.httpcode = 500;
return new Result<Articles>(null, Error);
}
}
If class1 and class2 have a common base type or common interface, use that. But in this case, you could create a wrapper class to encapsulate both result types, like this:
class MethodResult<T>
{
public T Result { get; private set; }
public Errors Errors { get; private set; }
public MethodResult(T result) { this.Result = result; }
public MethodResult(Errors errors) { this.Errors = errors; }
}
public MethodResult<Articles> MyMethod()
{
try
{
...
return new MethodResult<Articles>(articles);
}
catch(Exception e)
{
...
return new MethodResult<Articles>(errors);
}
}
In light of additional information in the question, since this is a WCF service, you could throw a WebFaultException:
public Articles function()
{
try
{
Articles articles = new Articles();
articles.articleid = 234;
articles.articlename = "Milk";
articles.deleted = 0;
//continue fill Articles
//and an exception occurs
return articles;
}
catch (Exception e)
{
throw new WebFaultException(System.Net.HttpStatusCode.InternalServerError)
{
Message = e.Message
};
}
}
The ways that other answers have handled this involve technical methods of how to define the two classes, using interfaces and subclassing.
However, fundamentally you're actually solving the wrong problem. You will still need to write code in the caller that distinguishes between the two types of object, as well as documenting the way in which your function works.
Personally, I would create a new Exception class for the type of error you may be handling, and throw that instead, for example:
public class InvalidArticleException: Exception {
public string ExceptionMessage { get; set; }
public string ExceptionName { get; set; }
public int HttpCode { get; set; }
}
public **** function()
{
try
{
// DO STUFF
return articles;
}
catch (InvalidArgumentException e)
{
throw new InvalidArticleException() {
ExceptionMessage = e.Message,
ExceptionName = e.ToString(),
HttpCode = 500
}
}
catch (Exception ex) { // Not actually required; left in for future debugging
throw ex;
}
}
Callers would then be able to catch the exception and examine it for the error details, with code that is kept separated from that which processes the returned articles.
You can try out keyword,
public Articles function(out Error err)
{
Articles articles = null;
err = null;
try
{
articles = new Articles();
articles.articleid = 234;
articles.articlename = "Milk";
articles.deleted = 0;
// Set your article values
}
catch (Exception e)
{
Errors ex = new Errors();
ex.exceptionmessage = e.Message;
ex.exceptionname = e.ToString();
ex.httpcode = 500;
err = ex;
}
return articles;
}
I'm not sure why would you want swallowing the exeptions, but if you do whatn this behgaviour make a return type common for both type. The both classes inherit from object so you can change the method signature to public object function()

Categories

Resources