c# - WebView和错误管理,怎么了?

标签 c# xamarin.forms error-handling webview connectivity

我正在开发 Xamarin.Forms应用程序,在这里我需要集成WebView来通过外部URL 管理预订。
所以基本上我已经做到了这一点:

<WebView x:Name="webView" Source="{Binding BookingUrl}"
         WidthRequest="1000" HeightRequest="1000">
我想管理用户在打开此页面时可能会遇到的一些错误:无互联网访问,超时,服务器不可用,...
为此,我使用了EventToCommandBehavior来访问 ViewModel 中的事件NavigatingNavigating
所以我的 XAML 看起来像这样:
<WebView x:Name="webView" Source="{Binding AvilaUrlBooking}"
            WidthRequest="1000" HeightRequest="1000">
    <WebView.Behaviors>
        <behaviors:EventToCommandBehavior
            EventName="Navigating"
            Command="{Binding NavigatingCommand}" />
        <behaviors:EventToCommandBehavior
            EventName="Navigated"
            Command="{Binding NavigatedCommand}" />
    </WebView.Behaviors>
</WebView>
ViewModel 像这样:
public ICommand NavigatingCommand
{
    get
    {
        return new Xamarin.Forms.Command<WebNavigatingEventArgs>(async (x) =>
        {
            if (x != null)
            {
                await WebViewNavigatingAsync(x);
            }
        });
    }
}

private Task WebViewNavigatingAsync(WebNavigatingEventArgs eventArgs)
{
    if (!IsConnected)
        ServiceErrorKind = ServiceErrorKind.NoInternetAccess;

    IsBusy = true;
    return Task.CompletedTask;
}

public ICommand NavigatedCommand
{
    get
    {
        return new Xamarin.Forms.Command<WebNavigatedEventArgs>(async (x) =>
        {
            if (x != null)
            {
                await WebViewNavigatedAsync(x);
            }
        });
    }
}

private Task WebViewNavigatedAsync(WebNavigatedEventArgs eventArgs)
{
    IsBusy = false;
    IsFirstDisplay = false;
    switch (eventArgs.Result)
    {
        case WebNavigationResult.Cancel:
            // TODO - do stuff here
            break;
        case WebNavigationResult.Failure:
            // TODO - do stuff here
            break;
        case WebNavigationResult.Success:
            // TODO - do stuff here
            break;
        case WebNavigationResult.Timeout:
            // TODO - do stuff here
            break;
        default:
            // TODO - do stuff here
            break;
    }
    return Task.CompletedTask;
}

bool isFirstDisplay;
public bool IsFirstDisplay
{
    get { return isFirstDisplay; }
    set { SetProperty(ref isFirstDisplay, value); }
}

public BookingViewModel()
{
    _eventTracker = new AppCenterEventTracker();
    IsFirstDisplay = true;
    Title = "Booking";

    IsConnected = Connectivity.NetworkAccess == NetworkAccess.Internet;
    Connectivity.ConnectivityChanged += OnConnectivityChanged;
}
如果我使用正确的URL,则在iOS和Android上都可以正常使用。
但是,如果我使用“错误的” URL(例如,缺少字符),则仅适用于 Android :WebNavigationResult.Failure是在WebViewNavigatedAsync()中捕获的情况,但我没有在 iOS 上输入WebViewNavigatedAsync()
=>这正常吗?
我已经实现了“刷新”按钮来管理“无法访问”错误。可通过ToolBarItem访问此按钮,就像在 ViewModel 中这样:
public void Refresh(object sender)
{
    try
    {
        var view = sender as Xamarin.Forms.WebView;
        view.Reload();
    }
    catch (Exception ex)
    {
    }
}
但是在这种情况下,在激活飞行模式后,我也有两种不同的行为:

上的
  • iOS ,当没有互联网访问时:即使互联网再次可用,我也没有输入WebViewNavigatedAsync(),并且我单击“刷新”按钮,我只通过了WebViewNavigatingAsync()
  • 上的
  • Android ,当没有互联网访问时:我很好地输入WebViewNavigatedAsync(),并且当互联网再次可用时,我单击“刷新”按钮,我同时通过了WebViewNavigatingAsync()WebViewNavigatedAsync()

  • =>这正常吗?有适当的方法来解决这个问题吗?

    最佳答案

    is this normal?


    根据我的测试。是的,我得到了相同的结果,如果我们输入错误的URL,则Webview在iOS中始终为空白 View 。因此NavigatedCommand无法执行。
    如果我们使用正确的url,则webview可能会执行NavigatedCommand,并产生如下屏幕截图所示的运行结果。
    enter image description here

    Is there a proper way to manager this?


    我们可以在iOS中为Webview使用自定义渲染器来处理这种情况。
    [assembly: ExportRenderer(typeof(CustomWebView), typeof(CustomWebViewRenderer))]
    namespace MyCarsourlView.iOS
    {
        [Obsolete]
        class CustomWebViewRenderer : WebViewRenderer
        {
    
            protected override void OnElementChanged(VisualElementChangedEventArgs e)
            {
                base.OnElementChanged(e);
    
                if (e.OldElement == null) { Delegate = new CustomWebViewDelegate(); }
            }
        }
    }
    
    internal class CustomWebViewDelegate : UIWebViewDelegate
    {
    
        #region Event Handlers
    
        public override bool ShouldStartLoad(UIWebView webView, NSUrlRequest request, UIWebViewNavigationType navigationType)
        {
    
            //Could add stuff here to redirect the user before the page loads, if you wanted to redirect the user you would do the redirection and then return false
    
            return true;
        }
    
        public override void LoadFailed(UIWebView webView, NSError error)
        {
            Console.WriteLine("\nIn AppName.iOS.CustomWebViewRenderer - Error: {0}\n", error.ToString());   //TODO: Do something more useful here
            //Here, you can test to see what kind of error you are getting and act accordingly, either by showing an alert or rendering your own custom error page using basic HTML
        }
    
        public override void LoadingFinished(UIWebView webView)
        { //You could do stuff here such as collection cookies form the WebView }
    
            #endregion
        }
    }
    
    如果我输入了错误的URL,则可以执行LoadFailed
    enter image description here

    关于c# - WebView和错误管理,怎么了?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64615003/

    相关文章:

    c# - 如何解决系统找不到指定文件的错误

    C# ReactiveUI UserError 错误处理程序

    c# - 当用户不在授权角色中时,如何提供未授权页面?

    c# - 在 C# 中实现好友(在 C++ 中可用)功能

    tensorflow - 如何为新类别重新训练Inception的最后一层

    c# - Xamarin - 在 WebView 中请求相机权限

    c# - 如何正确绑定(bind)和更新 Xamarin.Forms ListView?

    c# - 文件重命名问题?

    c# - Request Header中的JWT在接收.Net Core API中是不一样的

    c# - 如何使用 Xamarin Form 将流形式的图像上传到多部分休息服务