I am having problems with the event handler in my office addin . Below is an example code i got from microsoft website to explain what i mean.
I have a manifest file that uses the on-send hook as well as a click-based event triggering.
My button calls appendMessageBodyOnClick and onsend i call appendMessageBodyOnSend. Both function primarily do the same thing. I never want to block sending emails regardless.
The problem is that the event object is not properly cleaned up i think.
Scenario 1
When i click my button ; which calls event.completed(), and then after i try to send the message, it says my app is blocking the message, but then when i try to send again it goes through.
Scenario 2
When i leave the subject empty and then send the message, as expected i am prompted that the subject is empty. If i cancel sending the message on this note and then click on my button, the message tries to send as though i clicked send.
I am supposing the is some sort or state clean up issue. What am i doing wrong here?
Function-File.js
function appendMessageBodyOnClick(event) {
// Append string to message body
event.completed();
}
// In the following example, the checkMessage function has
// been registered as an event handler for ItemSend.
function appendMessageBodyOnSend(event) {
// Append string to message body
event.completed({allowEvent = true});
}
Not sure if this will help, but I also have faced some seemingly inconsistent behavior while understanding how to signal that event is fully completed. Once I got my edge cases fixed, then it worked.
One suggestion: Appending string to message body should be an async function. Call the event.completed() from inside the callback function. (i.e: make sure when you are calling event.completed(), nothing else is pending -like another async result)
Something like the following:
Office.context.mailbox.item.body.setAsync("new body", function(asyncResult) {
// handle success and failure
event.completed()
});
Same would be for your scenario 2, make sure event.completed() is called at the very end.
Related
I am designing a call manager with the help of RXSwift (ReactiveX) that continuously interacts with an API. The call manager comprises several objects that itself comprises an indicator (indicating status information loaded from the API) and control (requests to be sent to the API).
class CallManagerObjectA() {
var control = PublishSubject<String>()
var indicator = BehaviorSubject<String>(value: "string status")
}
Within the call manager, a scheduler regularly provides new values to the indicator observable:
<... API response ...>
indicator.onNext(newValue)
Somewhere else in a view controller, the indicator will be observed for a label:
indicator.subscribe(onNext: { label.stringValue = $0 })
Within the same view controller, the user can control the object status via GUI elements continuously:
control.onNext(commandValue)
Within the call manager, the control will be observed for an API call:
control.subscribe(onNext: { (command) in
// API request call
})
So far so good, this is working very well with reactive patterns.
Now, I am looking for a good solution to handle errors, if the call manager recognizes errors during the API interaction and show these errors to the user in the view controller. I was immediately thinking of something like this:
// Call manager recognizes the error
control.onError(error)
...
// Call manager ignores errors for the subscriber
control.retry().ignoreErrors().subscribe(onNext: { (command) in
// API request call
})
...
// View controller shows the errors
indicator.subscribe(onNext: { label.stringValue = $0 })
control.subscribe(onError: { print("error", $0) })
This however ends up in an infinite loop.
I fear that I have a fundamental understanding issue with reactive programming, or I miss something very important, but I am not able to understand how the handle errors in this reactive pattern environment.
Based on the code you have shown, you have a big misunderstanding, not just with how to handle Errors, but with how to program reactively in general. Try watching this video "Reactive Programming: Why It Matters"
To answer your specific question, there are two misunderstandings here:
When you call control.onError(_:) it will be the last call you will be able to make on control. Once it emits an error it will stop working.
The retry() operator asks its source to "try again on Error". If it's source is determinate, then it will just do the exact same thing it did before and emit the exact same output (i.e., the same error it emitted last time.) In the case of a PublishSubject, it doesn't know why onError was called. So the best it can do is just emit the error again.
Honestly, I consider this a bug in the API because subscribing to a publish subject that emitted an error at some point in the past should just do nothing. But then, you wouldn't be asking why you got an infinite loop. Instead you would be asking why your control stopped emitting events.
I have successfully setup a facebook-messenger webhook. Until yesterday I was able to send and receive messages as well. But today, when I am sending one message from user, I am getting multiple calls at server webhook POST API. They never seem to stop.
Do all of those calls have the same content or are they different? You could log the exact message string that facebook sends to you and see what they include.
For example there's a message delivery callback that informs you that the user received the message. The JSON looks like this:
{'delivery': {'mids': ['mid.146174459xxx:30a42600a95exxxxx'], 'seq': 429, 'watermark': 146174459xxx}, 'recipient': {'id': xxxxxxxx}, 'sender': {'id': xxxxxx}}
Edit: It could also be the case that your are not confirming incoming calls with a http status 200. If facebook receives an error from your webhook the message will be sent multiple times.
Figured it out. I was sending response to every communication that came from facebook. So I ended up responding to ACK messages as well. In turn one more ACK came. Thats why it led to infinite loop.
In this page we can find different object structures for messages recieved:
text
{
"object":"page",
"entry":[
{
"id":PAGE_ID,
"time":1457764198246,
"messaging":[
{
"sender":{
"id":USER_ID
},
"recipient":{
"id":PAGE_ID
},
"timestamp":1457764197627,
"message":{
"mid":"mid.1457764197618:41d102a3e1ae206a38",
"seq":73,
"text":"hello, world!"
}
}
]
}
]
}
Message-Delivered callback
{
"object":"page",
"entry":[
{
"id":PAGE_ID,
"time":1458668856451,
"messaging":[
{
"sender":{
"id":USER_ID
},
"recipient":{
"id":PAGE_ID
},
"delivery":{
"mids":[
"mid.1458668856218:ed81099e15d3f4f233"
],
"watermark":1458668856253,
"seq":37
}
}
]
}
]
}
So, for differentiating we can refer to entry[0].messaging[0].message this exist only in user sent message. Callback or postbacks do not contain this part.
Check for this, before responding. If it exists, respond, otherwise dont.
My problem was similar but I was getting Multiple Message delivery posts. After a few hours of frustration, I realized that Message Delivered callback is called every time the message is delivered to EVERY DEVICE. So, if you are logged into both web and mobile app, the callback would be called twice.
When working with messenger of facebook you need to take in account two things after you send the message :
A) Message Delivery
B) Message Read
Since you are working with webhooks this will be trigger everytime one of the events happen (receive a message , deliver the message you sent , the user read the message). So if you activate for example message_deliveries in your webhook and you send a message as action , you will end up in a loop.
The proper way to handle this is in the base code. PHP example :
// Skipping delivery messages
if (!empty($message['delivery'])) {
#Do something here if you want
continue;
}
// Skipping read messages
if (!empty($message['read'])) {
#Do something here if you want
continue;
}
Hope it helps !
consider the following (pseudo) code:
let request = Alamofire.request(...) {
//handler called when requests has been completed
//do some processing here
}
//some processing here, could take a while
request.cancel()
Question:
what happens if the request has already been fully completed (and the handler called) when the request.cancel() is done?
Will this return an error?
Is the handler called again?
Or (what I am hoping for) nothing...?
If the handler called that means request has its answer that can mean two things: Either request is succesfull, you have what you asked or request is not succesfull which means you will get an error.
Either way if you got your response request.cancel() will mean nothing.
Just out of curiosity if I have a chat application with an unread message counter...
How do I reset that counter?
Simply put, when User A writes a message, B increments there unread counter. When B is on the message page, I would like to reset that counter each refresh of the messages (it is running on subscribe).
Any ideas?
or this.model.del("yourdata.count");
Actually it was pretty simple.
You can write the following code in your html:
{{yourMethodName();}}
Then in your server you write some code:
app.proto.yourMethodName = function(){
//Clear data
this.model.del("yourdata.count");
//similar to: this.model.set("yourdata.count",0);
}
Super simple.... Updated based off of Aleksey
I'm using the MVVM Light Toolkit. I could not find any Ctor of Messenger or Notification class to send a empty message.
ViewModel1:
private int _selectedWeeklyRotation;
public int SelectedWeeklyRotation
{
get { return _selectedWeeklyRotation; }
set
{
if(_selectedWeeklyRotation == value)
return;
_selectedWeeklyRotation = value;
this.OnPropertyChanged("SelectedWeeklyRotation");
if(value > 1)
Messenger.Default.Send();
}
}
ViewModel2:
Ctor:
Messenger.Default.Register(this, CreateAnotherTimeTable);
private void CreateAnotherTimeTable()
{
}
I just need to send a Notification to another ViewModel, no sending of data at all.
Is that possible with MVVM Light Toolkit library?
Unless I'm misunderstanding something, couldn't you accomplish this by creating and sending a custom "signal message" type via the Messenger?
public class WeeklyRotationSignal {}
Messenger.Default.Send(new WeeklyRotationSignal());
Then register to that in another view model:
Messenger.Default.Register<WeeklyRotationSignal>(this, msg => doWork);
You can try sending a simple message with a string tag and receive that message by matching the string tag. Something like this:
Sender portion of the code located possibly in something like ViewModel1.cs
Messenger.Default.Send<string>("Dummy text message", "String_ToHelpMatchTheMsg");
Receiving end portion of the code responding to that message above, possibly located in some other file, something like ViewModel2.cs
...
Messenger.Default.Register<string>(this, "String_ToHelpMatchTheMsg", executeThisFunction);
private void executeThisFunction(string strMsg)
{
//your code would go here to run upon receiving the message
// The following line will display: "Dummy text message"
System.Windows.Browser.HtmlPage.Window.Alert("msg passed: " + strMsg);
}
Please note that you dont have to do anything with the text message that is passed around with the messaging code above. Just one part of the code sending some ping to another part of the code to ask some other section to execute some code. The important string is the one where I used "String_ToHelpMatchTheMsg" because that is the key used to match the sender and the receiver. Almost like creating your own quasi-event, once the Send method runs, the Register method is notified and fire its own function to run also.
I used this with a Close button on a Child Window to close it. The Close button on the View of the Child Window binds to a relay command on its childWindowViewModel. That relay command has the code above to send a message to the ParentViewModel. The Register portion on the ParentViewModel responds to that message by firing a method that closes the ChildWindow which was initially instantied from that parentViewModel.
Once you get more familiar with messaging, there are more attributes that you will be able to use so that the receiver can call back the sender to give a status or some data back. Look for Delegates and lambda function to achieve this.
All this to avoid placing code in the code behind to close the child window! :-)
Use as you see fit.
Cheers.
Mario
There really isn't a way to accomplish this and in someways defies the point of the messenger class. I didn't want to write a your doing it wrong post, but I feel I am stuck. The way the messenger class works is that you have two parties that both subscribe to the same concept, its an observer model. Without that similar concept or message there really isn't a way to tie the two objects together. The generic message whether a simple string or custom message act as the meeting point of the Subscribing and Publishing classes.
If the ViewModel publishing knows the type of ViewModel its trying to Send to it could...
Messenger.Default.Send<Type>(typeof(ViewModelToSendTo);
This would act as a very simple interaction point, you also wouldn't have to create a custom class. Some purist may have an issue with this approach as it couples the publishing class to the subscriber.
I don't think that it is possible and frankly I don't see the point of having that kind of message. You could just as well send a string "SelectedWeeklyRotation". It seems strange to have an empty message that has some kind of meaning as you increase the number of broadcast messages - and receivers in your application.
In the version of MVVM Light that I'm using it is not even possible to send an empty message.
However I did see a method in the ViewModelBase that is :
// Update bindings and broadcast change using GalaSoft.MvvmLight.Messenging
RaisePropertyChanged(MyPropertyPropertyName, oldValue, value, true);
This might be of interest for you.