ReplaceItemAsync in Azure Mobile Apps and offline sync DatasyncClient - xamarin

I am using DatasyncClient for Updating a class Item that includes two subitems List and List.
1.I do an update to item by adding some elements to Lists of element 1 or 2. The request is succesfuul it trigger the API.
2. i go back to the page and I see the update.
3. I try to add aditional elements to list and I recive an error of bad request. I checked the Lists and they have the values correctly with old elements including the Ids and new ones without Ids
at Microsoft.Datasync.Client.Http.ServiceHttpClient.SendAsync (Microsoft.Datasync.Client.Http.ServiceRequest serviceRequest, System.Threading.CancellationToken cancellationToken) [0x0013a] in <38458483b2a14e59b81ac72e4b1c1b4d>:0
at Microsoft.Datasync.Client.Table.RemoteTable.SendRequestAsync (Microsoft.Datasync.Client.Http.ServiceRequest request, System.Threading.CancellationToken cancellationToken) [0x00095] in <38458483b2a14e59b81ac72e4b1c1b4d>:0
at Microsoft.Datasync.Client.Table.RemoteTable1[T].TransformHttpExceptionAsync (System.Func1[TResult] action) [0x0006d] in <38458483b2a14e59b81ac72e4b1c1b4d>:0
at Microsoft.Datasync.Client.Table.RemoteTable`1[T].ReplaceItemAsync (T instance, System.Threading.CancellationToken cancellationToken) [0x000d8] in <38458483b2a14e59b81ac72e4b1c1b4d>:0

Azure Mobile Apps does not support lists inside objects. The generally accepted method of doing this is to create a join table (where you have Id of list object and whatever data you need in the list items), then produce a repository on the client side that synchronizes both tables and constructs the client side.

Related

Cache emitted value for dependent observable but not source observable

I am currently implementing a new feature at work. The app wants to give sellers an admin where they can see various things. An example of one of the things they can see on their dashboard is their last 10 orders.
The order's API only returns an array of various ids (customer id, product id, seller id, etc) In order to populate the orders page, I have to make 3 different API call on each order to get the data to render on the order list page
Now that I have to create a dashboard that is different from the order list page, I do not want to make such a tedious API call again. I want to create a dashboard$ observable that has the last emitted value of orderList$ but I do not want anything subscribed to orderList$ to be cached.
So when orderList$ is called, it gets the lastest orderList data from the server (I do not feel something as sensitive as order list should be cached), when dashboard$ is called, get the last emitted value of orderList$ and if orderList$ has not emitted any values then dashboard$ can make a request to retrieve order list.
When working with a reactive state of mind, I like to define what should happen based on events. By this I mean that I'll have a Subject in which in can push values into to notify an event and from there we can react to these events.
In your case, here's an idea for what you want:
const navigationToOrdersPage$$ = new Subject<void>();
const refreshOrdersButtonClicked$$ = new Subject<void>();
const orders$: Order[] = merge(
navigationToOrdersPage$$,
refreshOrdersButtonClicked$$
).pipe(
switchMap(() => yourOrderService.getOrders()),
shareReplay({
bufferSize: 1,
// make sure that even if we don't have anyone subscribed to that observable
// we keep the result in the cache and if we ever go to the orders page or click
// on the refresh button it'll be updated anyway but with this it's safe to navigate
// to another page than orders and the dashboard and if you go back to the dashboard
// you'd still get an instant result
refCount: false,
})
);
So here it'd be safe to reuse this observable on both the admin and the dashboard page. Of course, you'll need to call next on the 2 subjects when appropriate so that the orders can be refreshed when they need to.

Axon - Cannot emit query update in different microservice

I'm bothering with situation when I want to emit query update via queryUpdateEmitter but in different module (microservice). I have application built upon microservices and both are connected to the same Axon Server. First service creates subscriptionQuery, and sends some commands. After a while (through few commands and events) second service handles some event, and emits update for firstly subscribed query. Unfortunately it seems like this emit doesn't get to subscriber. Queries are exactly the same and sits in the same packages.
Subscription:
#GetMapping("/refresh")
public Mono<MovieDTO> refreshMovies() {
commandGateway.send(
new CreateRefreshMoviesCommand(UUID.randomUUID().toString()));
SubscriptionQueryResult<MovieDTO, MovieDTO> refreshedMoviesSubscription =
queryGateway.subscriptionQuery(
new GetRefreshedMoviesQuery(),
ResponseTypes.instanceOf(MovieDTO.class),
ResponseTypes.instanceOf(MovieDTO.class)
);
return refreshedMoviesSubscription.updates().next();
}
Emitter:
#EventHandler
public void handle(DataRefreshedEvent event) {
log.info("[event-handler] Handling {}, movieId={}",
event.getClass().getSimpleName(),
event.getMovieId());
queryUpdateEmitter.emit(GetRefreshedMoviesQuery.class, query -> true,
Arrays.asList(
MovieDTO.builder().aggregateId("as").build(),
MovieDTO.builder().aggregateId("be").build()));
}
This situation is even possible in the newest version of Axon? Similar configuration but within one service is working as expected.
#Edit
I have found a workardound for this situation:
Second service instead of emitting query via queryUpdateEmitter, publishes event with list of movies
First service handles this event and then emits update via queryUpdateEmitter
But still I'd like to know if there is a way to do this using queries only, because it seems natural to me (commandGateways/eventGateways works as expected, queryUpdateEmitter is the exception).
This follows from the implementation of the QueryUpdateEmitter (regardless of using Axon Server yes/no).
The QueryUpdateEmitter stores a set of update handlers, referencing the issued subscription queries. It however only maintains the issued subscription queries handled by the given JVM (as the QueryUpdateEmitter implementation is not distributed).
It's intent is to be paired in the component (typically a Query Model "projector") which answers queries about a given model, updates the model and emits those updates.
Hence, placing the QueryUpdateEmitter operations in a different (micro)service as where the query is handled will not work.

How to detected dead conversation references when using proactive conversations

We are using ContinueConversationAsync to send a Proactive Message to existing conversations which is working, what we want it a way to detect if that conversation is still active for instance if the conversation channel is webchat that session may no longer exists or a teams channel and the user has now left the organisation. Otherwise our ConversationReference table will just grow indefinably. At the moment SetProactiveMessage still just continues with no error even if there is no longer a user on the other end.
var conversationReference = botProactiveMessageConversation.ConversationReferenceJson.FromJson<ConversationReference>();
conversationReference.ActivityId = null;
MicrosoftAppCredentials.TrustServiceUrl(conversationReference.ServiceUrl);
await defaultAdapter.ContinueConversationAsync(botProactiveMessageConversation.BotAppId, conversationReference, async (ITurnContext turnContext, CancellationToken cancellationToken) =>
{
turnContext.SetProactiveMessage(botProactiveMessageConversation.ProactiveMessageData);
await dialogBot.OnTurnAsync(turnContext, cancellationToken);
}, default);
Unfortunately, there is no concept of a dead conversation in Direct Line. Subsequently, there is no method you can rely upon that is built in. A conversation's Conversation.Id is stored by the service for 14 days (subject to change, so don't rely on this as a rule) at which point it is purged. When storing your conversation reference, you can append a lastAccessed date and, when your time threshold is reached, it is purged from your store.
As for determining if a member is still part of a team or in an org, you will need to rely on a separate service call. Your best bet would be to use Microsoft's Graph API to check statuses.
Hope of help!

Responding to Conversations async: Graph or Bot?

I have a Teams Message extension that returns a Task response which is a medium sized embedded web view iFrame
This is working successfully; including added a custom Tab within the channel and other nice magic calls to Microsoft Graph.
What I am confused about is how to do (and this is probably my not understanding the naming of things)
insert "something" Back into the Message/Post stream which is a link to newly created Tab ... like the what you get when you have a "configureTabs" style Tab created -- there is a friendly Message (Post) in the chat pointing to this new Tab.
do I do this with Microsoft Graph or back through the Bot?
the code that does the communication may be a different service elsewhere that is acting async ... so it needs to communicate with something somewhere with context. Confused if this is the Bot with some params or Microsoft Graph with params.
how to insert an image (rather than a link to the tab) into the Message/Post stream -- but showing the image not a link off to some random URL (ie: )
could not find any samples that do this; again, will be async as per above; but the format of the message will be a Card or something custom?
So just to be clear, a Task Response is NOT the same as a Tab, albeit that they might end up hosted in the same backend web application (and also albeit that your TAB can actual bring up your Task Response popup/iframe using the Teams javascript library).
Aside from that, in order to post something back to the channel, like when the Tab is created, there are two ways to do so:
First is to use Graph Api's Create ChatMessage option (this link is just for a channel though - not sure if your tab/task apply to group chats and/or 1-1 chats as well).
2nd Option is to have a Bot be part of your application as well. Then, when you're ready to send something to the channel, you'd effectively be sending something called a "pro-active messaging". You need to have certain reference data to do this, which you would get when the bot is installed into the channel ("conversation reference", "ServiceUrl", and so on). I describe this more in my answer at Programmatically sending a message to a bot in Microsoft Teams
With regards sending the image, either of the above would work here too, in terms of how to send the image. As to the sending of an image, you'd need to make use of one of the kinds of "Cards" (basically "richer" messages than just raw text). You can learn more about this at Introducing cards and about the types of cards for Teams at Card reference. There are a few that can be used to send an image, depending on perhaps what else you want the card to do. For instance, an Adaptive Card can send an image, some text, and an action button of some sort.
Hope that helps
To close the loop for future readers.
I used the following Microsoft Graph API docs, and the posting above, and this is working: Create chatMessage in a channel and Creating a Custom Microsoft Graph call from the SDK
The custom graph call (as it is not implemented in the .NET SDK at the time of this response) looks something like:
var convoReq = $"https://graph.microsoft.com/beta/teams/{groupId}/channels/{channelId}/messages";
var body = this.TeamsMessageFactory(newCreatedTabUrl, anotherstring).ToJson();
var postMessage = new HttpRequestMessage(HttpMethod.Post, convoReq)
{
Content = new StringContent(body, System.Text.Encoding.UTF8, "application/json")
};
await _graphClient.CurrentGraphClient.AuthenticationProvider.AuthenticateRequestAsync(postMessage);
var response = await _graphClient.CurrentGraphClient.HttpProvider.SendAsync(postMessage);
if (response.IsSuccessStatusCode)
{
var content = await response.Content.ReadAsStringAsync();
return true;
}
The groupId and channelId are found elsewhere; and the TeamsMessageFactory is just some boilerplate that serialized the C# object graph for the POST request, as detailed in Create chatMessage in a channel

WCF Data Service Operation loses order of subEntities in Silverlight Client

I have a WCF DataService operation, which exposes Businesses and Customers.
On the server side, I sort each Business's Customers by LastName, this way:
List<Customers> orderedCustomers = business.Customers.OrderBy(c=> c.LastName).ToList<Customers>()
business.Customers.Clear()
foreach (Customers customer in orderedCustomers )
business.Customers.Add(customer )
And on the client side (asynchronously, in Silverlight), I expand each business's customers like this:
Context.BeginExecute<Business>(new Uri(serviceurl + BeginGetAllBusinessData&$expand=Cutomers, UriKind.Relative), GettingBusinessDataCompleted, Context);
My issue is: The customers in businesses are not sorted on the client side (they are sorted server-side). It happens the same with any field I choose for the OrderBy. Looks like serialization chooses its own order. I'd like to sort them on the server side.
Am I missing something???
Are you sure the returned List is out of order? If your GettingBusinessDataCompleted callback is responsible for adding the expanded content to the UI then things can appear out of sequence.
Asynchronous operations are not guaranteed to complete in the order they were begun.

Resources