title: Strategy to handle token expiration event across all view models
body: <p>The application architecture is: MVVM[Views -> ViewModels] -> Repositories -> API.</p>
  
  <p>The API layer can throw a <code>TokenExpiredException</code> exception, which we ultimately want to handle at the UI layer (by showing a message box and redirecting to login).</p>
  
  <p>Today, our VMs interact with the repositories like so:</p>
  
  <pre><code>SomeCommand {
      await _repo.DoSomethingAsync();
  }
  </code></pre>
  
  <p>My question is on finding a good pattern to handle this exception from the API layer. I can think of 3 approaches:</p>
  
  <p><strong>1)</strong> Wrap every repository call in a <code>BaseViewModel</code> method that takes care of catching and handling this view model-agnostic exception.</p>
  
  <pre><code>SomeCommand {
      await base.RepoRequest(() =&gt; _repo.DoSomethingAsync());
  }
  </code></pre>
  
  <p>where <code>BaseViewModel</code> would have:</p>
  
  <pre><code>RepoRequest(action) {
      try { action() }
      catch (TokenExpiredException) {
          // show message box
          // redirect
      }
  </code></pre>
  
  <p>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.</p>
  
  <p><strong>2)</strong> Every VM catches this exception</p>
  
  <pre><code>SomeCommand {
      try { await _repo.DoSomethingAsync(); }
      catch (InvalidUsernameException) { ... }
      catch (TokenExpiredException) {
          // show message box
          // redirect
      }
  </code></pre>
  
  <p>Not really different from 1), same issues and requires more code duplication.</p>
  
  <p><strong>3)</strong> Using an event aggregator to publish a message from the API layer to the <code>BaseViewModel</code>.</p>
  
  <pre><code>ApiRequest {
      var response = await _httpClient.ExecuteAsync&lt;..&gt;(...);
  
      if (response.ErrorId == "InvalidUsername")
          throw new InvalidUsernameException();
      else if (response.ErrorId == "TokenExpired")
          EventAggregator.Publish(new TokenExpiredException());
  }
  </code></pre>
  
  <p>and <code>BaseViewModel</code></p>
  
  <pre><code>onMessage(TokenExpiredException e) {
      // show message box
      // redirect
  }
  </code></pre>
  
  <p>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 <code>Messenger</code> (its event aggregator).</p>
  
  <p>Does anyone have a suggestion as to how to cleanly implement this functionality?</p>