This issue is technology agnostic, but I am working with C# and ASP.NET and will use this for the pseudo code. Which is the better approach, and why?
Encapsulate logging, transaction and exception handling:
protected void Page_Load(object sender, EventArgs e) {
SomeBusinessClass.SomeBusinessMethod();
}
public class SomeBusinessClass {
public void SomeBusinessMethod() {
using (TransactionScope ts = new TransactionScope()) {
doStuff();
ts.Complete();
}
catch (Exception ex) {
LogError("An error occured while saving the order", ex);
}
}
}
}
Delegate logging, transaction and exception handling to the caller:
protected void Page_Load(object sender, EventArgs e) {
using (TransactionScope ts = new TransactionScope()) {
try {
SomeBusinessClass.SomeBusinessMethod();
ts.Complete();
}
catch (Exception ex) {
LogError("An error occured while saving the order", ex);
}
}
}
public class SomeBusinessClass {
public void SomeBusinessMethod() {
doStuff();
}
}
I am concerned that by introducing dependencies on logging, transactions, etc in my business logic code, I make it less generic. On the other hand, the UI code looks so much cleaner. I can't make the call. Let me know what other factors I should consider.
Transactions: a central concern of your business layer, so it should absolutely handle this (though you might centralize transaction handling via a unit of work implementation).
Update: I don't agree with this part any more. Often, the controller, presenter, or or another top-level caller is the best place to handle transactions (a la the the onion architecture) - in many cases, that's where the logical unit of work is defined.
Exception Handling: use as needed in every layer - but only use it in the business layer when you can actually do something about it (not just log it). Use a global handler in the UI layer if your infrastructure supports one.
Logging: use trace or informational logging in whatever layers need it, only log exceptions in the top layer.
Use Inversion of Control:
protected void Page_Load(object sender, EventArgs e) {
new SomeBusinessClass(_logger, _dbcontext, _exceptionhandler).SomeBusinessMethod();
}
A better one would be
protected void Page_Load(object sender, EventArgs e) {
_mybusinessclass.SomeBusinessMethod();
}
where _mybusiness class is passed to your page via IoC container, along with populated _logger, _dbcontext, and _exceptionhandler. If you need to create _exceptionhandler manually, for example "new RedirectExceptionHandler(this)", then
protected void Page_Load(object sender, EventArgs e) {
_mybusinessclass.SomeBusinessMethod(new RedirectExceptionHandler(this));
}
Now it really boils down to your specific design decisions. Don't know how to do IoC in ASP.NET, though, since I use MVC.
Another option is to use Aspect Oriented Programming to catch exceptions and do logging. Yet another option (available in www.sharparchitecture.net) is to handle transactions declaratively using [Transaction] attributes on method.
Anything that makes the UI thinner will make your life easier.
Related
When certain exceptions are thrown in controllers, I want to catch those exceptions and do some extra logic.
I was able to achieve this with a custom IExceptionFilter that is added to the global filters list.
However, I preffer to handle these exception within a custom Owin middleware.
My middleware looks like this:
try
{
await Next.Invoke(context);
}
catch (AdalSilentTokenAcquisitionException e)
{
//custom logic
}
This piece of code does not work, it looks like the exception is already catched and handled in MVC.
Is there a way to skip the exception processing from MVC and let the middleware catch the exception?
Update: I've found a cleaner approach, see my updated code below.
With this approach, you don't need a custom Exception Filter and best of all, you don't need the HttpContext ambient service locator pattern in your Owin middleware.
I have a working approach in MVC, however, somehow it doesn't feel very comfortable, so I would appreciate other people's opinion.
First of all, make sure there are no exception handlers added in the GlobalFilters of MVC.
Add this method to the global asax:
protected void Application_Error(object sender, EventArgs e)
{
var lastException = Server.GetLastError();
if (lastException != null)
{
HttpContext.Current.GetOwinContext().Set("lastException", lastException);
}
}
The middleware that rethrows the exception
public class RethrowExceptionsMiddleware : OwinMiddleware
{
public RethrowExceptionsMiddleware(OwinMiddleware next) : base(next)
{
}
public override async Task Invoke(IOwinContext context)
{
await Next.Invoke(context);
var exception = context.Get<Exception>("lastException");
if (exception != null)
{
var info = ExceptionDispatchInfo.Capture(exception);
info.Throw();
}
}
}
There's no perfect way to do this (that I know of), but you can replace the default IExceptionHandler with one that just passes the error through to the rest of the stack.
I did some extensive digging about this, and there really doesn't seem to be a better way for now.
My DAL doesn't handle exceptions and it will be propagated up to the calling method in the presenter classes where the exception will be handled.
I'm using a single handler called ExecutAction(Action action) so I'm catching exceptions in one place rather than repeating in every method.
At the moment, I'm not logging errors. Just alert the user for an action and try to keep the system alive if possible.
When showing messages to users, Presenters will use a static class called MessagingService. (ShowErrorMessage()). So that I can customize all massage boxes in one place.
private void Search()
{
ExecutAction(() =>
{
var info = _DataService.GetByACNo(_model.AccountNumber);
if (info != null)
{
_Model = info ;
this.SetViewPropertiesFromModel(_Model, _View);
}
else
{
MessageBox.Show ("Bank account not found");
}
});
}
private void ExecutAction(Action action)
{
try
{
action();
}
catch (NullReferenceException e) { MessagingService.ShowErrorMessage(e.Message); }
catch (System.Data.SqlTypes.SqlTypeException e) { MessagingService.ShowErrorMessage(e.Message); }
catch (System.Data.SqlClient.SqlException e) { MessagingService.ShowErrorMessage(e.Message); }
}
}
Should I include general exception handler to this, to be able to handle any unforeseen exceptions?
Also could you show me a better way to handle showing messages than using a static?
Does use of lambda statements in every method call (ExecutAction(() =>) degrade code readability?
When showing user messages how to show a custom message like "Check the server connection" etc. first and then if the user wants more information (like StackTrace / technical details) he /she could press a button like More Info which is in the MessageBox dialog?
I agree with jeffrey about trying to incorporate IoC for your message service. You could define an abstract base presenter class that has a dependency on an interface for your message service. The base class would be responsible for handling the delegate execution + exception logging.
public interface IMessageService
{
void ShowErrorMessage(Exception e);
}
public abstract class PresenterBase
{
private readonly IMessageService _messageService;
public PresenterBase(IMessageService messageService)
{
this._messageService = messageService;
}
protected void ExecuteAction(Action action)
{
try
{
action();
}
catch (Exception e) { this._messageService.ShowErrorMessage(e); }
}
}
public class SearchPresenter: PresenterBase
{
public SearchPresenter(IMessageService messageService)
: base(messageService)
{
}
public void Search()
{
this.ExecuteAction(() =>
{
//perform search action
});
}
}
Regarding your question about catching all exeptions. Unless you are doing something special for specific types of exceptions, I would suggest just handling all the same. The example I provided passes the exception to the message service so that the formatting specifics can be handled by your message service.
If you have not yet incorporated any sort of IoC container, you can always start by using the interface injection and then passing the instance explicitly from the child class constructor.
public class SearchPresenter: PresenterBase
{
public SearchPresenter()
: base(new SomeMessageService())
{
}
...
}
This is at least removes the static dependency and is not too dificult to swap out later if you ever introduce an IoC container.
I think your approach is good enough for your work. Wrapping logics by ExecuteAction is an acceptable way to me. As another option, I might use AOP for centralized exception handling in practice.
Also, I might use a MessagingService resolved from dependency injection container rather than a static one.
Regarding how to display the error, that's totally depend on your business purpose. For example, you could simply log the error and tell the user "something's wrong", or show them the complete stacktrace including the environment information so they could simply copy & paste in the email.
I don't think I am even asking this right but here it goes.
I have a .NET CF app that displays a datagrid of info. This app is connected by TCP Sockets to a Central Server that will periodically broadcast out data.
How do I get my datagrid on my ShellForm to update. Feels wrong to have a reference to my ShellForm in my DAL where the Socket stuff is happening.
Would I use a Delegate or Async Callback? Just looking for a little guidance. Thanks!
The DAL can just publish an Event, and then the GUI can subscribe to it.
The reference (and dependency) will be from the GUI to the DAL.
Watch your thread-safety as well.
I'd suggest that your UI shouldn't know anything about your DAL at all. What I'd do for this would be to create an intermediate "presenter" class that watches the DAL and then can notify the UI, either via an event, callback or whatever.
I would most likely create a presenter class that implements INotifyPropertyChanged, which would allow you to directly watch the event or to data bind to the property that you're using to fill your grid. The presenter would also handle marshaling to the UI context, so neither the UI or the DAL would have to worry about it.
Some sort-of pseudo code might look like this. Bear in mind I have all sorts of infrastructure bits in my code, so this is not likely to just compile, but it should give you a flavor of how I'd attack the problem.
class PointPresenter : INotifyPropertyChanged
{
private IDataService DAL { get; set; }
protected Control EventInvoker { get; private set; }
public PointPresenter()
{
// get your DAL reference however you'd like
DAL = RootWorkItem.Services.Get<IDataService>();
EventInvoker = new Control();
// this is required to force the EE to actually create the
// control's Window handle
var h = EventInvoker.Handle;
}
protected void RaisePropertyChanged(string propertyName)
{
try
{
if (m_disposed) return;
EventInvoker.BeginInvokeIfRequired(t =>
{
try
{
PropertyChanged.Fire(this, propertyName);
}
catch (Exception e)
{
Debug.WriteLine(e);
}
});
}
catch (ObjectDisposedException)
{
// if the Form to which we're sending a message is disposed,
// this gets thrown but can safely be ignored
}
catch (Exception ex)
{
// TODO: log this
}
}
public int MyDataValue
{
get { return DAL.Data; }
set
{
if (value == MyDataValue) return;
DAL.Data = value;
RaisePropertyChanged("MyDataValue");
}
}
}
Is there a better way to catch exceptions? I seem to be duplicating a lot of code. Basically in every controller I have a catch statement which does this:
try
{
Do something that might throw exceptions.
}
catch (exception ex)
{
Open database connection
Save exception details.
If connection cannot be made to the database save exception in a text file.
}
I have 4 controllers and around 5-6 actions methods in each controller which is a lot of code duplication. How can I trim down on the amount of line in the try catch statement above?
You could make use of Extension methods here.
Create an extension method in a new class.
public static class ExtensionMethods
{
public static void Log(this Exception obj)
{
// log your Exception here.
}
}
And use it like:
try
{
}
catch (Exception obj)
{
obj.Log();
}
You don't need to put try/catch blocks on every method. That's tedious and painful! Instead you can use the Application_Error event of Global.asax for logging the exceptions. The code below is the sample implementation which can be used to catch exceptions that occur in your web application.
protected void Application_Error(object sender, EventArgs e)
{
var error = Server.GetLastError();
if (!string.IsNullOrWhiteSpace(error.Message))
{
//do whatever you want if exception occurs
Context.ClearError();
}
}
I would like also to stress that "Handled exception" especially trying to put try/catch blocks on most methods is one of the "Top 3 silent performance killers for IIS / ASP.NET apps" as explained in this blog http://mvolo.com/fix-the-3-high-cpu-performance-problems-for-iis-aspnet-apps/
What you are trying to do is called a cross-cutting concern. You are trying to log any error that happens anywhere in your code.
In ASP.NET MVC cross-cutting concerns can be achieved by using Filters. Filters are attributes that can be applied globally, to a controller or to a method. They run before an action method executes or after it.
You have several types of filters:
Authorization filters, they run to check if the user is allowed to access a resource.
Action filters, these run before and after an action method executes.
Result filters, these can be used to change the result of an action method (for example, add some extra HTMl to the output)
Exception filters run whenever an exception is thrown.
In your case, you are looking for exception filters. Those filters only run when an exception happens in in an action method. You could apply the filter globally so it will automatically run for all exceptions in any controller. You can also use it specifically on certain controllers or methods.
Here in the MSDN documentation you can find how to implement your own filters.
Personally, since I greatly dislike try/catch blocks, I use a static Try class that contains methods that wrap actions in reusable try/catch blocks. Ex:
public static class Try {
bool TryAction(Action pAction) {
try {
pAction();
return true;
} catch (Exception exception) {
PostException(exception);
return false;
}
}
bool TryQuietly(Action pAction) {
try {
pAction();
return true;
} catch (Exception exception) {
PostExceptionQuietly(exception);
return false;
}
}
bool TrySilently(Action pAction) {
try {
pAction();
return true;
} catch { return false; }
}
// etc... (lots of possibilities depending on your needs)
}
I have used a special class in my applications that is called ExceptionHandler, in the class that is static I have some methods to handle application's exceptions. It gives me an opportunity to centralize exception handling.
public static class ExceptionHandler
{
public static void Handle(Exception ex, bool rethrow = false) {...}
....
}
In the method you can log the exception, rethrow it, replace it with another kind of exception, etc.
I use it in a try/catch like this
try
{
//Do something that might throw exceptions.
}
catch (exception ex)
{
ExceptionHandler.Handle(ex);
}
As Wouter de Kort has rightly stated in his answer, it is cross-cutting concern, so I've put the class in my Application Layer and have used it as a Service. If you defined the class as an interface you would be able to have different implementations of it in different scenarios.
Also you can use Singleton pattern:
sealed class Logger
{
public static readonly Logger Instance = new Logger();
some overloaded methods to log difference type of objects like exceptions
public void Log(Exception ex) {}
...
}
And
Try
{
}
Catch(Exception ex)
{
Logger.Instance.Log(ex);
}
Edit
Some peoples don't like Singleton for reasonable grounds.instead of singleton we can use some DI:
class Controller
{
private ILogger logger;
public Controller(ILogger logger)
{
this.logger = logger;
}
}
And use some DI library that will inject one instance of ILogger into your controllers.
I like the answers suggesting general solutions, however I would like to point out another one which works for MVC.
If you have a common controller base (wich you should anyways, it's a Best Practice IMO). You can simply override the OnException method:
public class MyControllerBase : Controller
{
protected override void OnException(ExceptionContext filterContext)
{
DoSomeSmartStuffWithException(filterContext.Exception);
base.OnException(filterContext);
}
}
Then simply inherit your normal controllers from your common base instead of Controller
public class MyNormalController : MyControllerBase
{
...
If you like this you can check out the Controller class for other handy virtual methods, it has many.
In ASP .NET MVC you can implement your own HandleErrorAttribute to catch all the exceptions that occur in all controllers:
public class CustomHandleErrorAttribute : HandleErrorAttribute
{
public override void OnException(ExceptionContext filterContext)
{
var ex = filterContext.Exception;
// Open database connection
// Save exception details.
// If connection cannot be made to the database save exception in a text file.
}
}
Then register this filter:
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new CustomHandleErrorAttribute());
}
}
And of-course call the register method on application start-up:
public class MvcApplication : HttpApplication
{
protected override void OnApplicationStarted()
{
// ...
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
// ...
}
}
Wouter de Kort has already explained the concept behind this in his answer.
Can anyone advise of a good pattern for using a WCF Service from an ASP.net Page? It seems that if the lifetime of the Client(:ServiceModel.ClientBase) is not properly controlled that we get PipeException thrown. It currently exists as a field of the Page class, but is being reinstantiated upon each page request without being cleaned up (the .Close method).
I suspect this question could be rephrased "Managing limited resources in an ASP.net page", and is probably more related to the lifecycle of an ASP.net page. I'm new to ASP.net, so my understanding of this is a little thin.
TIA.
EDIT: Some code (there's not much to it!)
public partial class Default : Page
{
//The WCF client... obviously, instantiating it here is bad,
//but where to instantiate, and where to close?
private readonly SearchClient client = new SearchClient();
protected void Page_Load(object sender, EventArgs e)
{
2nd Edit: Would the following be better?
public partial class Default : Page
{
private SearchClient client;
protected void Page_Unload(object sender, EventArgs e)
{
try
{
client.Close();
}
catch
{
//gobbled
}
}
protected void Page_Load(object sender, EventArgs e)
{
client= new SearchClient();
//.....
I agree with Michael, abstract it out into another layer if possible.
However, if you are going to call it from your aspx page, I would just create a separate method to call it, return its results and cleanup. Keeps the code clean by having it all in one place. Just remember to dispose in your finally block, and that the wcf proxy will have to be cast to IDisposable in order to dispose.
for instance:
void Page_Load(object sender, EventArgs e)
{
if(!IsPostBack)
{
RemoteCall();
}
}
void RemoteCall()
{
var client = new SearchClient();
try
{
var results = client.Search(params);
clients.Close();
}
catch(CommunicationException cex)
{
//handle
}
catch(Exception ex)
{
//handle
}
finally
{
((IDisposable)client).Dispose();
}
}
In general, you shouldn't call external services directly from your presentation tier. It creates two problems: first, performance (pooling, scaling, etc), and second, it creates a security risk if you need to authenticate (authentication code in your DMZ is bad.
Even if you don't have an application tier, you should consider refactoring your service call to a private service in your presentation tier. This will allow you to decouple the service's lifecycle from the page's lifecycle (which is problematic as you have stated).