MVVM Light Messenger - How do you unit test targeted messages? - mvvm-light

If I target a message from ViewModelA to ViewModelB, is there a way to catch this notification from my unit test that is testing ViewModelA where the Message is raised?
Messenger.Default.Send<string, ViewModelB>("Something Happened");

I see two options:
First, you could mark ViewModelB with a "marker" interface, and use that instead of your actual class name.
Messenger.Default.Send<string, IMessageTarget>("Something Happened");
This is not my favorite solution, but it should work.
Or, you could register for messages with a specific token in ViewModelB while sending the disambiguated message from ViewModelA:
In ViewModelA:
Messenger.Default.Send<string>("Something Happened", "MessageDisambiguator");
In ViewModelB:
Messenger.Default.Register<string>(
this,
"MessageDisambiguator",
(action) => DoWork(action)
);
Much cleaner, and will still allow you to mock out ViewModelB for testing purposes.
There could be more options, but these are the ones that pop to the top of my head at this late hour...

Related

Fluxor: An effect which doesn't dispatch an action?

I'm using Fluxor to manage state in a Blazor wasm app.
I have the following effect which is triggered after getting a result from deleting an item:
[EffectMethod]
public Task HandleDeleteBudgetResultAction(DeleteBudgetResultAction action, IDispatcher dispatcher)
{
if (action.Success)
{
NavigationManager.NavigateTo("/budgets", false);
}
return Task.CompletedTask;
}
Essentially, if the delete was successful, navigate back to the list page. If it wasn't, do nothing as we need to remain on the detail page.
In this scenario I do not need to dispatch an action, but I have to include the dispatcher parameter, as demanded by the EffectMethod attribute. And since I have no async processes in this method, I am returning Task.CompletedTask.
This obviously feels wrong, so my question is: is this a limitation of Fluxor, or have I architected the flow incorrectly? As far as I'm aware, an effect doesn't have to dispatch an action.
I was thinking I might need to move my navigation state into the store, but I think I'll just come across the same problem again because I'll still need to call NavigationManager from somewhere.
Any help or better solutions appreciated :)
It is a limitation of Fluxor. You can dispatch a GoAction instead of injecting the NavigationManager, as long as you have called UseRouting on the Fluxor options.
builder.Services.AddFluxor(options => options
.UseRouting()
.ScanAssemblies(typeof(Program).Assembly)

Firebase-Authentication error in objects 'mAuth' and 'mCallbacks'

the mAuth and mCallbacks object is giving red-font-error. How to resolve this?
Do I need to make the object outside of the codeblock?
here is the code block in which the red-font errors are showing up:
PhoneAuthOptions options =
PhoneAuthOptions.newBuilder(mAuth)
.setPhoneNumber(phoneNumber) // Phone number to verify
.setTimeout(60L, TimeUnit.SECONDS) // Timeout and unit
.setActivity(this) // Activity (for callback binding)
.setCallbacks(mCallbacks) // OnVerificationStateChangedCallbacks
.build();
PhoneAuthProvider.verifyPhoneNumber(options);
If you keep following the documentation on implementing phone authentication on Android, you'll see that the mCallbacks object is defined in the next step, right under the code you have above. It is explained as:
When you call PhoneAuthProvider.verifyPhoneNumber, you must also provide an instance ofOnVerificationStateChangedCallbacks, which contains implementations of the callback functions that handle the results of the request.
Under that explanation is a code sample, and then an explanation of each individual callback and its purpose.
I recommend reading the entire page first, so that you understand the complete flow, and only then starting to copy/paste the relevant code snippets.

In Disassembler pipeline component - Send only last message out from GetNext() method

I have a requirement where I will be receiving a batch of records. I have to disassemble and insert the data into DB which I have completed. But I don't want any message to come out of the pipeline except the last custom made message.
I have extended FFDasm and called Disassembler(), then we have GetNext() which is returning every debatched message out and they are failing as there is subscribers. I want to send nothing out from GetNext() until Last message.
Please help if anyone have already implemented this requirement. Thanks!
If you want to send only one message on the GetNext, you have to call on Disassemble method to the base Disassemble and get all the messages (you can enqueue this messages to manage them on GetNext) as:
public new void Disassemble(IPipelineContext pContext, IBaseMessage pInMsg)
{
try
{
base.Disassemble(pContext, pInMsg);
IBaseMessage message = base.GetNext(pContext);
while (message != null)
{
// Only store one message
if (this.messagesCount == 0)
{
// _message is a Queue<IBaseMessage>
this._messages.Enqueue(message);
this.messagesCount++;
}
message = base.GetNext(pContext);
}
}
catch (Exception ex)
{
// Manage errors
}
Then on GetNext method, you have the queue and you can return whatever you want:
public new IBaseMessage GetNext(IPipelineContext pContext)
{
return _messages.Dequeue();
}
The recommended approach is to publish messages after disassemble stage to BizTalk message box db and use a db adapter to insert into database. Publishing messages to message box and using adapter will provide you more options on design/performance and will decouple your DB insert from receive logic. Also in future if you want to reuse the same message for something else, you would be able to do so.
Even then for any reason if you have to insert from pipeline component then do the following:
Please note, GetNext() method of IDisassembler interface is not invoked until Disassemble() method is complete. Based on this, you can use following approach assuming you have encapsulated FFDASM within your own custom component:
Insert all disassembled messages in disassemble method itself and enqueue only the last message to a Queue class variable. In GetNext() message then return the Dequeued message, when Queue is empty return null. You can optimize the DB insert by inserting multiple rows at a time and saving them in batches depending on volume. Please note this approach may encounter performance issues depending on the size of file and number of rows being inserted into db.
I am calling DBInsert SP from GetNext()
Oh...so...sorry to say, but you're doing it wrong and actually creating a bunch of problems doing this. :(
This is a very basic scenario to cover with BizTalk Server. All you need is:
A Pipeline Component to Promote BTS.InterchageID
A Sequential Convoy Orchestration Correlating on BTS.InterchangeID and using Ordered Delivery.
In the Orchestration, call the SP, transform to SOAP, call the SOAP endpoint, whatever you need.
As you process the Messages, check for BTS.LastInterchagneMessage, then perform your close out logic.
To be 100% clear, there are no practical 'performance' issues here. By guessing about 'performance' you've actually created the problem you were thinking to solve, and created a bunch of support issues for later on, sorry again. :( There is no reason to not use an Orchestration.
As noted, 25K records isn't a lot. Be sure to have the Receive Location and Orchestration in different Hosts.

Basic SignalR IMessageBus implementation

I have a service application that works pretty much like a SignalR backplane, so I thought it would be good idea to create my own IMessageBus implementation to talk with the backend, rather than roll out my own thing. The problem is that I cannot find much information about this contract. Although I have been taking a look at the code (that looks very good), I'm struggling to understand some concepts.
public interface IMessageBus
{
Task Publish(Message message);
IDisposable Subscribe(ISubscriber subscriber, string cursor, Func<MessageResult, object, Task<bool>> callback, int maxMessages, object state);
}
Task Publish(Message message);
This one is easy, basically it must send a message to the backend. I am not worried about this one, because my app is unidirectional from server to client.
IDisposable Subscribe(ISubscriber subscriber, string cursor, Func<MessageResult, object, Task<bool>> callback, int maxMessages, object state);
return: Despite of saying IDisposable, I have seen it always return a Subscription object, but why IDisposable?
subscriber identifies a connection. That connection can subscribe or unsubscribe to groups.
cursor: is the last received message id.
callback: when is this callback executed?
state: what is this exactly?
Can somebody explain me how this method work?
I would recommend to inherit from ScaleoutMessageBus (https://msdn.microsoft.com/en-us/library/microsoft.aspnet.signalr.messaging.scaleoutmessagebus(v=vs.111).aspx)
It provides an abstraction and encapsulates all subscription management, so it is possible to focus on a back plane implementation.
You can also take a look on Redis base implementation (https://github.com/SignalR/SignalR/blob/master/src/Microsoft.AspNet.SignalR.Redis/RedisMessageBus.cs) just as example.
If it is interesting SignalR is open source, so you can look at ScaleoutMessageBus implementation as well (https://github.com/SignalR/SignalR/blob/master/src/Microsoft.AspNet.SignalR.Core/Messaging/ScaleoutMessageBus.cs)
Hope that helps.

mvvm-light RaisePropertyChanged messenger not broadcasted

I cant seem to get this working properly.
I've got two ViewModels. VM1 registers a message with the following code
Messenger.Default.Register<PropertyChangedMessage<int>>(
this,
(action) => DispatcherHelper.CheckBeginInvokeOnUI(() => UpdateOverlayIcon(action.NewValue))
);
VM2 fires the RaisePropertyChanged when property is being set.
// Update bindings and broadcast change using GalaSoft.MvvmLight.Messenging
RaisePropertyChanged(UnreadTweetsPropertyName, oldValue, value, true);
Now, shouldn't the VM1.UpdateOverlayIcon() method run right after the RaisePropertyChanged is fired in VM2? Or have i missed an essential part of this, because it doesn't work for me? I have been struggling with this all day long and tried a number of different methods.
This should work quite easily - just make sure that the Message Register code is being registered before the RaisePropertyChanged notification is called.
The other thing to check is that your types match - so you are listening for a Message with INT - is this the type of UnreadTweetsPropertyName? (it wont receive it if they dont match).
The problem with this approach is that ANY int property that is broadcasting will be received... I would like to be able to pass in a token so that I can match them up...

Resources