Strategy to handle token expiration event across all view models - c#

The application architecture is: MVVM[Views -> ViewModels] -> Repositories -> API.
The API layer can throw a TokenExpiredException exception, which we ultimately want to handle at the UI layer (by showing a message box and redirecting to login).
Today, our VMs interact with the repositories like so:
SomeCommand {
await _repo.DoSomethingAsync();
}
My question is on finding a good pattern to handle this exception from the API layer. I can think of 3 approaches:
1) Wrap every repository call in a BaseViewModel method that takes care of catching and handling this view model-agnostic exception.
SomeCommand {
await base.RepoRequest(() => _repo.DoSomethingAsync());
}
where BaseViewModel would have:
RepoRequest(action) {
try { action() }
catch (TokenExpiredException) {
// show message box
// redirect
}
any other exception, such as a validation error, would be handled in the VM. The problem I see here is that it's too easy to forget to use this pattern. I might call the repository directly somewhere and miss handling the exception.
2) Every VM catches this exception
SomeCommand {
try { await _repo.DoSomethingAsync(); }
catch (InvalidUsernameException) { ... }
catch (TokenExpiredException) {
// show message box
// redirect
}
Not really different from 1), same issues and requires more code duplication.
3) Using an event aggregator to publish a message from the API layer to the BaseViewModel.
ApiRequest {
var response = await _httpClient.ExecuteAsync<..>(...);
if (response.ErrorId == "InvalidUsername")
throw new InvalidUsernameException();
else if (response.ErrorId == "TokenExpired")
EventAggregator.Publish(new TokenExpiredException());
}
and BaseViewModel
onMessage(TokenExpiredException e) {
// show message box
// redirect
}
This has the advantage of leaving all VMs (but the base) free of wiring up.
Disadvantage is that I'm hesitant to use an event aggregator 1) at all 2) at the API layer.
We are using mvvm-light and this would mean referencing those libraries in our deeper layers just for the Messenger (its event aggregator).
Does anyone have a suggestion as to how to cleanly implement this functionality?

I had to figure out the same problem, but I was using WCF with the castle wcf facility, this helped me, because the facility already had point of extension for intercepting the calls. So I just created my custom AbstractWcfPolicy and intercepted all the exception that I want to manage.
With the same idea you can think about using a proxy class, based on castle dynamic proxy, in that way your call will remain await _repo.DoSomethingAsync(); but under the wood your ExceptionInterceptor will intercept all the exception and do whatever you want:
[Serializable]
public class Interceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
Console.WriteLine("Before target call");
try
{
invocation.Proceed();
}
catch(Exception)
{
Console.WriteLine("Target threw an exception!");
throw;
}
finally
{
Console.WriteLine("After target call");
}
}
}
Then you can throw back some of the exceptions you might want to throw anyway, for some of the exception or all, you could also implement a publish-subscribe (a global message broker, the messenger in MVVM Light) mechanism where you push the exception, and then in any point of your application you can subscribe to those errors and do something (log, show the error to the user in an unobtrusive way, etc...).

Related

surrounding a function with actions

I am developing an Asp.net MVC application, and I have created an error handling system that forces me to create the following code per function in my BLL.
try
{
...
_unitOfWork.Save(nameof(Function));
}
catch
{
if (rollbackTo != null)
{
_unitOfWork.RollbackToSave(rollbackTo);
}
else
{
_unitOfWork.Rollback();
}
throw;
}
this basically allows me to manage my transactions per request, and manage the transaction's error handling without my Controllers knowing about the actual way that this is being done - it only allows it to decide whether or not the transaction will continue (rollbackTo parameter)
What I am wondering is, is there a way for me not to have to write this piece of code over and over? I thought about just throwing an exception, and then handle it in my pipeline - but since I need to return a valueable response to the user, and not just a 500 code - this isn't really an option. I thought about maybe creating a base class that calls and abstract method - and implementing it per function - but that won't work either, since the parameters can change. Any Ideas?
Yes, this is fairly standard.
For example, in the base class
public void DoSomethingAndRollbackThenThrow(Action<IUnitOfWork> action)
{
try
{
...
action(_unitOfWork);
}
catch
{
if (rollbackTo != null)
{
_unitOfWork.RollbackToSave(rollbackTo);
}
else
{
_unitOfWork.Rollback();
}
throw;
}
}
And then you can call it from derived class like so
public void DoSomethingSpecific()
{
base.DoSomethingAndRollbackThenThrow(unitOfWork => {
_unitOfWork.Save(nameof(Function));
});
}
You can use an AOP(Aspect Oriented Programming) framework.
You can "weave" some functionalities to your methods with just implementing for one time and adding some attributes.
More about AOP:
https://en.wikipedia.org/wiki/Aspect-oriented_programming
An easy-to-use open source AOP Framework:
https://github.com/AntyaDev/KingAOP
There are also a bunch of alternatives (both commercial and open source). Google may give you good results about alternatives.

Servicestack - Write all exceptions to custom logger

I am trying to find how to catch all exceptions (raised on the server, not the client) from my ServiceStack services in order to write them to my custom logger (which writes it to the eventlog). Now I am confused what implementation to use. I find postings implementing a custom ServiceRunner which looks rather complicated.
I found in the documentation you can use something like:
public override void Configure(Funq.Container container)
{
this.ServiceExceptionHandler = (req, ex) => { WRITE EXCEPTION TO MY OWN LOGGER };
}
Now I am stuck because this method is not available (there is a collection named ServiceExceptionHandlers, note the 's' at the end).
You need to use the .Add method on the ServiceExceptionHandler because you can setup more than one handler, i.e. if you have multiple loggers. See here for more information.
You need two methods to catch all exceptions. One to catch the exceptions in your service, and one to catch the others. The code below shows how to handle both cases.
public override void Configure(Container container)
{
//Handle Exceptions occurring in Services:
this.ServiceExceptionHandler.Add((httpReq, request, exception) => {
// Log your exceptions here
...
// Call the default exception handler or prepare your own custom response
return DtoUtils.CreateErrorResponse(request, exception);
});
// Handle Unhandled Exceptions occurring outside of Services
// E.g. in Request binding or filters:
this.ExceptionHandler = (req, res, operationName, ex) => {
res.Write("Error: {0}: {1}".Fmt(ex.GetType().Name, ex.Message));
res.EndServiceStackRequest(skipHeaders: true);
};
}
Note:
The reason that ServiceStack is expecting a collection of handlers, and your example code didn't show this, is because that documentation is for v3 (BSD open source version of ServiceStack), the corresponding documentation is here, but you are running ServiceStack v4 (Commercial) where improvements have been made to allow multiple actions to be taken.
Hope this helps.

Throw or not throw the exception from the methods consumed by the ASP.NET Web API layer

Assume that I am building an ASP.NET Web API application and it has the following structure:
As you can see from the diagram, the ASP.NET Web API core will talk to domain service layer (e.g. MembershipService class which has methods such as GetUsers, CreateUser, etc.) and my service classes will talk to one or multiple repositories to handle the operations.
It's very obvious that a service operation (such as MembershipService.CreateUser method) would fail for several reasons (unmet conditions, an exception thrown by the repository, etc.) and this is the place where I have the doubts.
Do you think that service classes should handle exceptions and return some sort of result object such as the below one:
public class OperationResult {
public OperationResult(bool isSuccess) : this(isSuccess) {
IsSuccess = isSuccess;
}
public OperationResult(bool isSuccess, Exception exception) : this(isSuccess) {
Exception = exception;
}
public bool IsSuccess { get; private set; }
public Exception IsSuccess { get; private set; }
}
public class OperationResult<TEntity> : OperationResult {
public OperationResult(bool isSuccess)
: base(isSuccess) { }
public OperationResult(bool isSuccess, Exception exception)
: base(isSuccess, exception) { }
public TEntity Entity { get; set; }
}
Or do you think that the service methods shouldn't abstract the exception like that and should throw the exception directly or indirectly (creating a new meaningful exception type specific to operation and put the thrown exception as its inner exception)?
When you are in-process, use exceptions.
I don't see ANY point in avoiding exceptions. Exceptions are there for good reasons, mainly to be used!
Just try to look at the big picture: you are trying to change Exception mechanism with the old fashion way of error checking. This way you'll lose all the merits of Exceptions (like separation of the error-handling and regular code, CallStack, ...) and gain nothing in return.
What I usually do in this situation is to catch the exception in service layer and rewrap it into a custom exception (with the reference to the original exception in the InnerException field).
Taking a page from Microsoft's book, the implementation of the Membership API throws exceptions rather than handling them and returning a result object, so I would consider this a best practice as long as you don't control both the client and the API.
In the case where you do control both the client and the API, it is my personal preference to return a result object or an error message. The reason for this is that I want to log capture detailed information about the source of actual exceptions, but I don't want an exception for everything that could go wrong, such as the password being incorrect.
In this case, a simple error message to the user will be more than sufficient. From real-world experience, recording exceptions to the event log or log file every time a validation error occurs is a major burden on operations personnel that are trying to determine whether or not there is an actual fault occurring or whether it is just a user's typo.

How to refactor logging in C#?

In my services all exposed methods have:
try
{
// the method core is written here
}
catch(Exception ex)
{
Log.Append(ex);
}
It's boring and ugly to repeat it over and over again. Is there any way to avoid that? Is there a better way to keep the service working even if exceptions occur and keep sending the exception details to the Log class?
Try AOP. This is the most widely-used selling point of AOP.
Also, see this discussion here on SO.
You could set up a generic error handling method for all uncaught exceptions like so:
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(UnhandledException);
Depending on what went wrong, you may not be able to recover from the error... but this should hopefully give you some idea of what what went wrong. If it gets to the point where your application code hasn't handled the exception gracefully, this method could attempt to reinitialize the service to a known working state.
I came up with a semi-solution right now. I can refactor the code:
public TResult ExecuteAndLogOnError(Func<TResult> func)
{
try
{
return func();
}
catch(Exception ex)
{
// logging ...
}
}
And then you can call it on each method:
return ExecuteAndLogOnError(() =>
{
// method core goes here..
});
Which is 4 lines shorter than the original scenario.
In such cases I always use centralized error handlers.
In WCF it is very easy. Some more details:
http://www.haveyougotwoods.com/archive/2009/06/24/creating-a-global-error-handler-in-wcf.aspx
Basically, you just implement the IServiceBehavior interface and then provide your own error handler. That is the best way to do this because you don't have to write any code that handles fatal exceptions (I mean exceptions that you can only log and you don't know what to do about them) in your methods.
If all your doing is logging then just log the error at a later stage... No need to log the error early. If you do more than log the error, well then you're gonna need the try..catch anyway. And if you swallow exceptions (IE. just log them and then go on as if nothings happened) then maybe you're doing it wrong...
I once used something like the Template Function Pattern to resolve a problem like this. I had a base class that did something like:
public void Execute()
{
try
{
ExecuteImplementation();
}
catch (Exception ex)
{
// Log ex
}
}
public abstract void ExecuteImplementation();
There was one derived class per web service operation. The derived classes each implemented ExecuteImplementation.
The web service operations did:
[WebMethod]
public Result WebOperation(Request request)
{
WebOperationClass instance = new WebOperationClass(request);
instance.Execute();
return instance.Result;
}
Exception filters would be good for this. Alas, .NET supports them through MSIL, C++/CLI, VB.NET, but not C#.
If all you're doing in your catch is logging the exception, you could maybe just use a custom error page and let ELMAH log all your uncaught exceptions.
A previous poster brought up AOP (Aspecte-Oriented Programming).
I use PostSharp for basic logging traces/exceptions.
It's quite easy to use and setup.
Check out this link and watch the tutorial.
http://www.sharpcrafters.com/postsharp
--crap it is no longer open source ... anyways you can grab Postsharp1.5 and mess around with it to see if it is something you are interested in it.
I am also in no way affiliated with PostSharp. I'm just a user.

How Do You Communicate Service Layer Messages/Errors to Higher Layers Using MVP?

I'm currently writing an ASP.Net app from the UI down. I'm implementing an MVP architecture because I'm sick of Winforms and wanted something that had a better separation of concerns.
So with MVP, the Presenter handles events raised by the View. Here's some code that I have in place to deal with the creation of users:
public class CreateMemberPresenter
{
private ICreateMemberView view;
private IMemberTasks tasks;
public CreateMemberPresenter(ICreateMemberView view)
: this(view, new StubMemberTasks())
{
}
public CreateMemberPresenter(ICreateMemberView view, IMemberTasks tasks)
{
this.view = view;
this.tasks = tasks;
HookupEventHandlersTo(view);
}
private void HookupEventHandlersTo(ICreateMemberView view)
{
view.CreateMember += delegate { CreateMember(); };
}
private void CreateMember()
{
if (!view.IsValid)
return;
try
{
int newUserId;
tasks.CreateMember(view.NewMember, out newUserId);
view.NewUserCode = newUserId;
view.Notify(new NotificationDTO() { Type = NotificationType.Success });
}
catch(Exception e)
{
this.LogA().Message(string.Format("Error Creating User: {0}", e.Message));
view.Notify(new NotificationDTO() { Type = NotificationType.Failure, Message = "There was an error creating a new member" });
}
}
}
I have my main form validation done using the built in .Net Validation Controls, but now I need to verify that the data sufficiently satisfies the criteria for the Service Layer.
Let's say the following Service Layer messages can show up:
E-mail account already exists (failure)
Refering user entered does not exist (failure)
Password length exceeds datastore allowed length (failure)
Member created successfully (success)
Let's also say that more rules will be in the service layer that the UI cannot anticipate.
Currently I'm having the service layer throw an exception if things didn't go as planned. Is that a sufficent strategy? Does this code smell to you guys? If I wrote a service layer like this would you be annoyed at having to write Presenters that use it in this way? Return codes seem too old school and a bool is just not informative enough.
Edit not by OP: merging in follow-up comments that were posted as answers by the OP
Cheekysoft, I like the concept of a ServiceLayerException. I already have a global exception module for the exceptions that I don't anticipate. Do you find making all these custom exceptions tedious? I was thinking that catching base Exception class was a bit smelly but wasn't exactly sure how progress from there.
tgmdbm, I like the clever use of the lambda expression there!
Thanks Cheekysoft for the follow-up. So I'm guessing that would be the strategy if you don't mind the user being displayed a separate page (I'm primarily a web developer) if the Exception is not handled.
However, if I want to return the error message in the same view where the user submitted the data that caused the error, I would then have to catch the Exception in the Presenter?
Here's what the CreateUserView looks like when the Presenter has handled the ServiceLayerException:
For this kind of error, it's nice to report it to the same view.
Anyways, I think we're going beyond the scope of my original question now. I'll play around with what you've posted and if I need further details I'll post a new question.
That sounds just right to me. Exceptions are preferable as they can be thrown up to the top of the service layer from anywhere inside the service layer, no matter how deeply nested inside the service method implementation it is. This keeps the service code clean as you know the calling presenter will always get notification of the problem.
Don't catch Exception
However, don't catch Exception in the presenter, I know its tempting because it keeps the code shorter, but you need to catch specific exceptions to avoid catching the system-level exceptions.
Plan a Simple Exception Hierarchy
If you are going to use exceptions in this way, you should design an exception hierarchy for your own exception classes.
At a minumum create a ServiceLayerException class and throw one of these in your service methods when a problem occurs. Then if you need to throw an exception that should/could be handled differently by the presenter, you can throw a specific subclass of ServiceLayerException: say, AccountAlreadyExistsException.
Your presenter then has the option of doing
try {
// call service etc.
// handle success to view
}
catch (AccountAlreadyExistsException) {
// set the message and some other unique data in the view
}
catch (ServiceLayerException) {
// set the message in the view
}
// system exceptions, and unrecoverable exceptions are allowed to bubble
// up the call stack so a general error can be shown to the user, rather
// than showing the form again.
Using inheritance in your own exception classes means you are not required to catch multipile exceptions in your presenter -- you can if there's a need to -- and you don't end up accidentally catching exceptions you can't handle. If your presenter is already at the top of the call stack, add a catch( Exception ) block to handle the system errors with a different view.
I always try and think of my service layer as a seperate distributable library, and throw as specific an exception as makes sense. It is then up to the presenter/controller/remote-service implementation to decide if it needs to worry about the specific details or just to treat problems as a generic error.
As Cheekysoft suggests, I would tend to move all major exceptions into an ExceptionHandler and let those exceptions bubble up. The ExceptionHandler would render the appropriate view for the type of exception.
Any validation exceptions however should be handled in the view but typically this logic is common to many parts of your application. So I like to have a helper like this
public static class Try {
public static List<string> This( Action action ) {
var errors = new List<string>();
try {
action();
}
catch ( SpecificException e ) {
errors.Add( "Something went 'orribly wrong" );
}
catch ( ... )
// ...
return errors;
}
}
Then when calling your service just do the following
var errors = Try.This( () => {
// call your service here
tasks.CreateMember( ... );
} );
Then in errors is empty, you're good to go.
You can take this further and extend it with custome exception handlers which handle uncommon exceptions.
In reply to the follow-up question:
As for creating exceptions becoming tedious, you kinda get used to it. Use of a good code generator or template can create the exception class with minimal hand editing within about 5 or 10 seconds.
However, in many real world applications, error handling can be 70% of the work, so it's all just part of the game really.
As tgmdbm suggests, in MVC/MVP applications I let all my unhandlable exceptions bubble up to the top and get caught by the dispatcher which delegates to an ExceptionHandler. I set it up so that it uses an ExceptionResolver that looks in the config file to choose an appropriate view to show the user. Java's Spring MVC library does this very well. Here's a snippet from a config file for Spring MVC's Exception resolver - its for Java/Spring but you'll get the idea.
This takes a huge amount of exception handling out of your presenters/controllers altogether.
<bean id="exceptionResolver"
class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<prop key="UserNotFoundException">
rescues/UserNotFound
</prop>
<prop key="HibernateJdbcException">
rescues/databaseProblem
</prop>
<prop key="java.net.ConnectException">
rescues/networkTimeout
</prop>
<prop key="ValidationException">
rescues/validationError
</prop>
<prop key="EnvironmentNotConfiguredException">
rescues/environmentNotConfigured
</prop>
<prop key="MessageRejectedPleaseRetryException">
rescues/messageRejected
</prop>
</props>
</property>
<property name="defaultErrorView" value="rescues/general" />
</bean>

Categories

Resources