Microsoft.Azure.Mobile客户端-使用自定义IMobileServiceSyncHandler处理服务器错误-Xamarin表单 [英] Microsoft.Azure.Mobile Client - Handling Server Error using custom IMobileServiceSyncHandler - Xamarin Forms

查看:67
本文介绍了Microsoft.Azure.Mobile客户端-使用自定义IMobileServiceSyncHandler处理服务器错误-Xamarin表单的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已根据Microsoft

I have implemented the Azure - Offline Sync based on the documentation / Sample provided by Microsoft Sample in my Xamarin Forms Application.

在提供的样本/文档中,他们正在使用默认的服务处理程序.

In the sample / documentation provided, they are using the default Service Handler.

//简单的错误/冲突处理.真正的应用程序可以通过IMobileServiceSyncHandler处理各种错误,例如网络状况,服务器冲突和其他错误.

由于推/推失败,我需要实施一次重试逻辑3次..根据文档,我创建了一个自定义服务处理程序( IMobileServiceSyncHandler ).

请在这里找到我的代码逻辑.

public class CustomSyncHandler : IMobileServiceSyncHandler
{
    public async Task<JObject> ExecuteTableOperationAsync(IMobileServiceTableOperation operation)
    {
        MobileServiceInvalidOperationException error = null;
        Func<Task<JObject>> tryExecuteAsync = operation.ExecuteAsync;

        int retryCount = 3;
        for (int i = 0; i < retryCount; i++)
        {
            try
            {
                error = null;
                var result = await tryExecuteAsync();
                return result;
            }
            catch (MobileServiceConflictException e)
            {
                error = e;
            }
            catch (MobileServicePreconditionFailedException e)
            {
                error = e;
            }
            catch (MobileServiceInvalidOperationException e)
            {
                error = e;
            }
            catch (Exception e)
            {
                throw e;
            }

            if (error != null)
            {
                if(retryCount <=3) continue;
                else
                {
                     //Need to implement
                     //Update failed, reverting to server's copy.
                }
            }
        }
        return null;
    }

    public Task OnPushCompleteAsync(MobileServicePushCompletionResult result)
    {
        return Task.FromResult(0);
    }
}

但是我不确定在所有3次重试均失败的情况下如何处理/还原服务器副本.

But I am not sure how to handle / revert server copy in case all the 3 retry failed.

在TODO示例中,他们根据 MobileServicePushFailedException .但是当我们实现 IMobileServiceSyncHandler 时可用. 此外,如果我们包含自定义IMobileServiceSyncHandler,则它不会在 PushAsync/PullAsync 之后执行代码.即使遇到任何异常,即使尝试捕获也不会触​​发.

In the TODO sample they where reverting it based on the MobileServicePushFailedException. But which is available when we implement IMobileServiceSyncHandler. More over if we include custom IMobileServiceSyncHandler it wont execute the code after PushAsync / PullAsync. Even the try catch wont fire in case any exception.

        try
        {
            await this.client.SyncContext.PushAsync();

            await this.todoTable.PullAsync(
                //The first parameter is a query name that is used internally by the client SDK to implement incremental sync.
                //Use a different query name for each unique query in your program
                "allTodoItems",
                this.todoTable.CreateQuery());
        }
        catch (MobileServicePushFailedException exc)
        {
            if (exc.PushResult != null)
            {
                syncErrors = exc.PushResult.Errors;
            }
        }

        // Simple error/conflict handling. A real application would handle the various errors like network conditions,
        // server conflicts and others via the IMobileServiceSyncHandler.
        if (syncErrors != null)
        {
            foreach (var error in syncErrors)
            {
                if (error.OperationKind == MobileServiceTableOperationKind.Update && error.Result != null)
                {
                    //Update failed, reverting to server's copy.
                    await error.CancelAndUpdateItemAsync(error.Result);
                }
                else
                {
                    // Discard local change.
                    await error.CancelAndDiscardItemAsync();
                }

                Debug.WriteLine(@"Error executing sync operation. Item: {0} ({1}). Operation discarded.", error.TableName, error.Item["id"]);
            }
        }
    }

注意

在我的应用程序中,如果服务器发生错误,我只会尝试重试3次.我不是要解决冲突.这就是我没有添加相同代码的原因.

In my application I am only trying to achieve retry for 3 time in case any server error. I am not looking for to resolve conflicts. Thant is the reason I haven't added the code for the same.

如果有人遇到类似问题并解决了该问题,请提供帮助.

If someone came across similar issues and resolved it please help.

Stez.

推荐答案

您说您不是要解决冲突,但是您需要通过一种或另一种方式解决冲突(也许不告诉用户发生了什么事),方法是接受对象的服务器版本或更新客户端操作.否则,它将在每次重试操作时始终告诉您相同的冲突.

You say you aren't trying to resolve conflicts, but you need to resolve them one way or another (without telling the user what's going on, perhaps) by accepting the server version of the object or updating the client operation. Otherwise it will just keep telling you about the same conflict each time it retries the operation.

您需要具有Microsoft.WindowsAzure.MobileServices.Sync.MobileServiceSyncHandlerHandler的子类,该类重写OnPushCompleteAsync()以便处理冲突和其他错误.我们将其称为SyncHandler类:

You need to have a subclass of the Microsoft.WindowsAzure.MobileServices.Sync.MobileServiceSyncHandler class, which overrides OnPushCompleteAsync() in order to handle conflicts and other errors. Let's call the class SyncHandler:

public class SyncHandler : MobileServiceSyncHandler
{
    public override async Task OnPushCompleteAsync(MobileServicePushCompletionResult result)
    {
        foreach (var error in result.Errors)
        {
            await ResolveConflictAsync(error);
        }
        await base.OnPushCompleteAsync(result);
    }

    private static async Task ResolveConflictAsync(MobileServiceTableOperationError error)
    {
        Debug.WriteLine($"Resolve Conflict for Item: {error.Item} vs serverItem: {error.Result}");

        var serverItem = error.Result;
        var localItem = error.Item;

        if (Equals(serverItem, localItem))
        {
            // Items are the same, so ignore the conflict
            await error.CancelAndUpdateItemAsync(serverItem);
        }
        else // check server item and local item or the error for criteria you care about
        {
            // Cancels the table operation and discards the local instance of the item.
            await error.CancelAndDiscardItemAsync();
        }
    }
}

在初始化MobileServiceClient时包括此SyncHandler()的实例:

Include an instance of this SyncHandler() when you initialize your MobileServiceClient:

await MobileServiceClient.SyncContext.InitializeAsync(store, new SyncHandler()).ConfigureAwait(false);

Read up on the MobileServiceTableOperationError to see other conflicts you can handle as well as its methods to allow resolving them.

这篇关于Microsoft.Azure.Mobile客户端-使用自定义IMobileServiceSyncHandler处理服务器错误-Xamarin表单的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆