I am migrating to version 6 of Reactive UI, and am trying to more completely use the tools it provides, namely ThrownExceptions. Nothing happens when I subscribe to the thrown exceptions property. I'm sure I'm missing something just not sure what it is right now.
In my simplified example, there is a button with a command bound it it.
public ReactiveCommand<object> Delete { get; private set; }
public MainWindowViewModel()
{
Delete = ReactiveCommand.Create();
Delete.Subscribe(e => CommandExec());
Delete.ThrownExceptions.Subscribe(ex => HandleException(ex));
}
private object HandleException(Exception ex)
{
MessageBox.Show("Exception Handled");
return null;
}
public IObservable<object> CommandExec()
{
throw new Exception("throwing");
}
My assumption is that I would see an "Exception Handled" MessageBox when the exception was thrown. I'm sure i'm subscribing to something, it's just not clear what it is right now.
ThrownExceptions only applies to the background operation declared with CreateAsyncXYZ:
var someCmd = ReactiveCommand.CreateAsyncObservable(_ =>
Observable.Throw<Unit>(new Exception("Oh Noes!"));
someCmd.ThrownExceptions.Subscribe(ex => Console.WriteLine(ex.Message));
await someCmd.ExecuteAsync();
>>> Oh Noes!
In ReactiveUI, you should never put Interesting™ code inside the Subscribe block - Subscribe is solely to log the result of operations, or to wire up properties to other properties.
Related
What is a good way to bubble up a DbUpdateConcurrencyException to the view from the grain?
I'm currently working on an Orlean's prototype that has a custom state that I'm using Entity Framework Core to communicate with the DB and using the optimistic concurrency patterns built into EF Core to manage the concurrency issues.
Where I'm having an issue is that I want to bubble up my Exception from the grain to the view and am not receiving it on the view end.
I'm trying to accomplish this because I want to deal with some of the concurrency issues that are more pressing on the view so that the user can decide or at least be alerted to the issue.
I brought this up on the Orlean's Gitter, but didn't get many ideas from it.
Example of my code for updating:
public Task UpdateUser(User user)
{
//Reason for second try/catch is to bubble the error to controller
try
{
userState = new User
{
Username = this.GetPrimaryKeyString(),
accountType = user.accountType,
FName = user.FName,
LName = user.LName,
RowVersion = user.RowVersion,
CreatedDate = user.CreatedDate
};
UpdateState();
}
catch (DbUpdateConcurrencyException ex)
{
throw ex;
}
return Task.CompletedTask;
}
public Task UpdateState()
{
using (var context = new OrleansContext())
{
context.users.Update(userState);
try
{
context.SaveChanges();
}
catch ( DbUpdateConcurrencyException ex)
{
var entry = ex.Entries.Single();
var clientValues = (User)entry.Entity;
var databaseEntry = entry.GetDatabaseValues();
//Make sure the row wasn't deleted
if(databaseEntry != null)
{
var databaseValues = (User)databaseEntry.ToObject();
if(clientValues.accountType != databaseValues.accountType)
{
//Bubble up the exception to controller for proper handling
throw ex;
}
//Update Row Version to allow update
userState.RowVersion = databaseValues.RowVersion;
context.SaveChanges();
}
}
}
return Task.CompletedTask;
}
I'm open to any suggestions on this as long as it allows the user to be alerted to the Exception and can view their data and the current DB values.
There is a chance that the exception is not being serialized or deserialized correctly. The primary reasons for this could be:
The Exception class does not correctly implement the ISerializable pattern.
The assembly which contains the Exception class is not present on the client, so the client does not understand how to create the Exception type.
In this case, I would lean towards the second reason, because most (but not all!) Exception classes do correctly implement the ISerializable pattern.
In either case, you can catch your exception and turn it into a generic exception.
You could create a helper method to do this using the LogFormatter.PrintException(Exception) method from Orleans to format the exception as a string.
public static void ThrowPlainException(Exception e) =>
throw new Exception(Orleans.Runtime.LogFormatter.PrintException(e));
The solution I came to was to create a custom exception class that serializable add the database values object to it and bubble that up to the views.
[Serializable]
public class UpdateException : Exception
{
public object databaseValues { get; set; }
public UpdateException(object databaseValues)
{
this.databaseValues = databaseValues;
}
public UpdateException(string message, object databaseValues) :base(message)
{
this.databaseValues = databaseValues;
}
}
I have a simple entity and trying to make fail the save method for my unit test.
The question is, how can I make the save method to fail and return false?
public class Sampple
{
public int Id { get; set; }
public string Name{ get; set; }
}
public bool Save()
{
return (_applicationDbContext.SaveChanges() >= 0);
}
Like #Yohannis said, dont waste your time testing EF itself.
If you are looking to test what might happen if a dbcontext.SaveChanges() failed, whether that be for an incorrectly parsed property or whatever.
try something like this:
`try {
//_applicationDbContext.SaveChanges()
throw new Exception();
// Remember to replace _applicationDbContext.SaveChanges() with
//'new Exception' when you are outside of the development db
return(true); //whilst exception active, here is not hit
}
catch (Exception e) {
//Error handling here
return(false);
}`
A try catch will try to complete a process, if it cant, the catch will 'catch' the thrown exception. In our case we have purposely thrown anew Exception so that we can see exactly what would happen if _applicationDbContext.SaveChanges() did fail. I have included a very basic Exception but there are many types that you can use and tailor to exactly what kind of error you might want to test for.
I have included a link with some relatively simple examples for your consideration.
https://www.codeproject.com/Articles/850062/Exception-handling-in-ASP-NET-MVC-methods-explaine
I would like to react to user's typing within a text box.
Actually my question is similar to what has already been posted at Reactive Extensions Instant Search for WPF/MVVM.
Now that we're at the release 6 of ReactiveUI, the previous code is out of date. How can I implement it (with MVVM, i.e. not using events)?
The compelling example # http://reactiveui.net/ should help alot. You also want to make sure your xaml TextBox uses the UpdateSourceTrigger
<TextBox Text="{Binding SearchQuery, UpdateSourceTrigger=PropertyChanged}" Width="50" />
Code from RXUI copied here:
public class SearchViewModel : ReactiveObject, IRoutableViewHost
{
public ReactiveList<SearchResults> SearchResults { get; set; }
private string searchQuery;
public string SearchQuery {
get { return searchQuery; }
set { this.RaiseAndSetIfChanged(ref searchQuery, value); }
}
public ReactiveCommand<List<SearchResults>> Search { get; set; }
public ISearchService SearchService { get; set; }
}
and the constructor code
// Constructor
public SearchViewModel(ISearchService searchService = null)
{
SearchService = searchService ?? Locator.Current.GetService<ISearchService>();
// Here we're describing here, in a *declarative way*, the conditions in
// which the Search command is enabled. Now our Command IsEnabled is
// perfectly efficient, because we're only updating the UI in the scenario
// when it should change.
var canSearch = this.WhenAny(x => x.SearchQuery, x => !String.IsNullOrWhiteSpace(x.Value));
// ReactiveCommand has built-in support for background operations and
// guarantees that this block will only run exactly once at a time, and
// that the CanExecute will auto-disable and that property IsExecuting will
// be set according whilst it is running.
Search = ReactiveCommand.CreateAsyncTask(canSearch, async _ => {
return await searchService.Search(this.SearchQuery);
});
// ReactiveCommands are themselves IObservables, whose value are the results
// from the async method, guaranteed to arrive on the UI thread. We're going
// to take the list of search results that the background operation loaded,
// and them into our SearchResults.
Search.Subscribe(results => {
SearchResults.Clear();
SearchResults.AddRange(results);
});
// ThrownExceptions is any exception thrown from the CreateAsyncTask piped
// to this Observable. Subscribing to this allows you to handle errors on
// the UI thread.
Search.ThrownExceptions
.Subscribe(ex => {
UserError.Throw("Potential Network Connectivity Error", ex);
});
// Whenever the Search query changes, we're going to wait for one second
// of "dead airtime", then automatically invoke the subscribe command.
this.WhenAnyValue(x => x.SearchQuery)
.Throttle(TimeSpan.FromSeconds(1), RxApp.MainThreadScheduler)
.InvokeCommand(this, x => x.Search);
}
I've implemented the following pattern by jbogard:
http://lostechies.com/jimmybogard/2014/05/13/a-better-domain-events-pattern/
Imagine the following entity Coupon and event CouponActivatedEvent:
public class Coupon : DomainEntity
{
public virtual User User { get; private set; }
// ...omitted...
public void Activate(User user)
{
if (User != null)
throw new InvalidOperationException("Coupon already activated");
User = user;
Events.Add(new CouponActivatedEvent(this));
}
}
The following event handler CouponActivatedHandler:
public class CouponActivatedHandler : IDomainEventHandler<CouponActivatedEvent>
{
public void Handle(CouponActivatedEvent e)
{
// user gets 5 credits because coupon was activated
for (int i = 0; i < 5; i++)
{
e.Coupon.User.AddCredit(); // raises UserReceivedCreditEvent and CreditCreatedEvent
}
}
}
The following SaveChanges override on DbContext (Entity Framework 6), taken from jbogard's blog post:
public override int SaveChanges()
{
var domainEventEntities = ChangeTracker.Entries<IDomainEntity>()
.Select(po => po.Entity)
.Where(po => po.Events.Any())
.ToArray();
foreach (var entity in domainEventEntities)
{
var events = entity.Events.ToArray();
entity.Events.Clear();
foreach (var domainEvent in events)
{
_dispatcher.Dispatch(domainEvent);
}
}
return base.SaveChanges();
}
If we now activate a coupon, this will raise the CouponActivatedEvent. When calling SaveChanges, the handler will be executed, and UserReceivedCreditEvent and CreditCreatedEvent will be raised. They won't be handled though. Am I misunderstanding the pattern? Or is the SaveChanges override not appropriate?
I've considered creating a loop that will repeat until no new events are raised before moving on to base.SaveChanges();... but I'm worried that I will create endless loops accidentally. Like so:
public override int SaveChanges()
{
do
{
var domainEventEntities = ChangeTracker.Entries<IDomainEntity>()
.Select(po => po.Entity)
.Where(po => po.Events.Any())
.ToArray();
foreach (var entity in domainEventEntities)
{
var events = entity.Events.ToArray();
entity.Events.Clear();
foreach (var domainEvent in events)
{
_dispatcher.Dispatch(domainEvent);
}
}
}
while (ChangeTracker.Entries<IDomainEntity>().Any(po => po.Entity.Events.Any()));
return base.SaveChanges();
}
Yeah, you misunderstood things. A Domain Event is not like a C# event, it's a message about what changed in the Domain. One rule is that an event is something that happened, it's in the past. Thus, an event handler simply can't (it shouldn't) change the event, it's like changing the past.
You CouponActivatedHandler should at least get the User entity form a repository then update it with the number of credits, then save it, then publish an UserCreditsAdded event. Even better, the handler should just create and send a command AddCreditsToUser .
With Domain Events pattern, an operation is simply a chain of command->event-> command-> event etc. The event handler is usually a service (or a method in one) which takes care only of that bit. The sender of the event won't know anything about the handler and vice-versa.
As a thumb rule, a Domain object generates an event when its state has changed. A service will take those events then send them to a service bus (for a simple app, a DI Container is enough) which will publish them to be handled by anyone interested (this means services from the local app or other apps subscribed to that bus).
Never forget that Domain Events is a high level pattern used when doing the architecture of an app, it's not just another way to do object events (like C#'s events).
The linked implementation of domain events does not handle potentially nested events raised by event handlers. If you read through the authors comments, he himself once mentioned that he "tries to avoid it".
IMO, what you implemented with the loop makes sense. But if you are not certain about getting into an indefinite loop, I suggest you implement a circuit breaker pattern there.
Let us say I have this ReactiveUI view model structure, with Model being some arbitrary model type.
class ViewModel : ReactiveObject
{
private readonly ReactiveList<Model> _models;
public IReactiveList<Model> Models { get { return _models; } }
public IReactiveCommand LoadModels { get; private set; }
public bool LoadingModels { get; private set; } // Notifies;
}
And these models come from a task-based asynchronous API modeled by this interface:
interface ITaskApi
{
Task<IEnumerable<Model>> GetModelsAsync();
}
After taking a look at how Octokit.net's reactive library was written, I wrote the following class to adapt the API to a reactive world:
class ObservableApi
{
private readonly ITaskApi _taskApi;
public IObservable<Model> GetModels() {
return _taskApi.GetModelsAsync().ToObservable().SelectMany(c => c);
}
}
And now, I have written the following ways to implement loading of models inside of the the LoadModels command, in the ViewModel() constructor:
// In both cases, we want the command to be disabled when loading:
LoadModels = new ReactiveCommand(this.WhenAny(x => x.LoadingModels, x => !x.Value));
// First method, with the Observable API;
LoadModels.Subscribe(_ =>
{
LoadingModels = true;
_models.Clear();
observableClient.GetModels().ObserveOnDispatcher()
.Subscribe(
m => _models.Add(m),
onCompleted: () => { LoadingModels = false; });
});
// Second method, with the task API;
LoadModels.Subscribe(async _ =>
{
LoadingModels = true;
try {
var loadedModels = await taskClient.GetModelsAsync();
_models.Clear();
_models.AddRange(loadedModels);
} catch (Exception ex) {
RxApp.DefaultExceptionHandler.OnNext(ex);
} finally {
LoadingModels = false;
}
});
While I think that both ways will do the job, I have the following misgivings:
In the first sample, should I dispose the inner subscription or will that be done when the inner observable completes or errors?
In the second sample, I know that exceptions raised in the GetModelsAsync method will be swallowed.
What is the "best", most idiomatic way to populate a ReactiveList<T> from an asynchronous enumeration (either IObservable<T> or Task<IEnumerable<T>> (or would IObservable<IEnumerable<T>> be better?))?
After taking a look at how Octokit.net's reactive library was written, I wrote the following class to adapt the API to a reactive world:
While you sometimes want to do this (i.e. flatten the collection), it's usually more convenient to just leave it as IEnumerable<T> unless you then plan to invoke an async method on each item in the list. Since we just want to stuff everything in a List, we don't want to do this. Just leave it as Task<T>
In the first sample, should I dispose the inner subscription or will that be done when the inner observable completes or errors?
Any time you have a Subscribe inside another Subscribe, you probably instead want the SelectMany operator. However, there is a better way to do what you're trying to do, you should check out this docs article for more info.
So, here's how I would write your code:
// In both cases, we want the command to be disabled when loading:
LoadModels = new ReactiveCommand();
LoadModels.RegisterAsyncTask(_ => taskClient.GetModelsAsync())
.Subscribe(items =>
{
// This Using makes it so the UI only looks at the collection
// once we're totally done updating it, since we're basically
// changing it completely.
using (_models.SuppressChangeNotifications())
{
_models.Clear();
_models.AddRange(items);
}
});
LoadModels.ThrownExceptions
.Subscribe(ex => Console.WriteLine("GetModelsAsync blew up: " + ex.ToString());
// NB: _loadingModels is an ObservableAsPropertyHelper<bool>
LoadModels.IsExecuting
.ToProperty(this, x => x.LoadingModels, out _loadingModels);