打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
Silverlight 应用程序退出事件时调用Web Service服务

Silverlight 应用程序退出时,我们经常要做记录用户退出登录系统的行为,修改用户登录状态,或一些其它的数据处理操作,但是在Silverlight应用程序App的Application_Exit事件中,调用Web Service或WCF是无效的,微软官网也无相应的解决该办法。我在Code Project发现Daniel Vaughan关于该问题的解决思路, 遂翻译过来备忘,并与大家分享。
——jcstone        
  

介绍

        今天我读了我的师弟 Laurent Bugnion 的一个好帖,是关于用户关闭浏览器时执行操作的讨论。它让我考虑在Silverlight中当用户试图关闭浏览器窗口或导航到其它网页时能调用web service服务。此前未曾尝试回答这个问题。今天,我决定为此做一些测试。

        我想看看两个方面。首先,我实现在 Silverlight 应用程序退出事件后调用 web 服务。其次,我实现向 Silverlight 应用程序提供取消,或至少中断关闭窗口过程的机会。

        在第一种情况下,我发现可以实现在 Silverlight 应用程序退出事件后引发调用,即从 Silverlight,JavaScript 调用,然后执行 PageMethod去执行自定义的方法。



   图:关闭浏览器窗口后调用WebService的顺序图

 我们看到在 App.xaml.cs的Exit事件被调用,那里可以调JavaScript函数,如下所示:
void Application_Exit(object sender, EventArgs e){    HtmlPage.Window.Invoke("NotifyWebserviceOnClose",           new[] { guid.ToString() });}

我们于是在应用程序的页面中调PageMethod方法,如下所示:

function NotifyWebserviceOnClose(identifier) {    PageMethods.SignOff(identifier, OnSignOffComplete);            }

通过PageMethod,我们可以更新所连接的客户列表,或者其它我们想做的事情:

[WebMethod][System.Web.Script.Services.ScriptMethod] public static void SignOff(string identifier){    /* Update your list of signed in users here etc. */    System.Diagnostics.Debug.WriteLine("*** Signing Off: " + identifier);}

注意, Laurent这种方法可靠所以需要自己去测试火狐 3.5 IE8我已经在本地测试过但是结果可能会不同

现在件事用户尝试关闭浏览器时,能够提供一些用户的交互作用,取消调用 web 服务浏览实际关闭之前

我所做的是在页面的 body 标签中放置  onbeforeunload 事件图所示
<body onbeforeunload="OnClose()">

于是我在JavaScript脚本中创建了一个OnCLose事件,如下所示:

function OnClose() {               var plugin = document.getElementById("silverlightControl");    var shutdownManager = plugin.content.ShutdownManager;    var shutdownResult = shutdownManager.Shutdown();    if (shutdownResult) {        event.returnValue = shutdownResult;    }}

这里我们看到,Silverlight 应用程序APP中创建了一个 ShutdownManager 实例ShutdownManager 一个应用程序正在关闭时,该类能够执行一些任意的事务通过调用toRegisterScriptableObject注册它由它可以访问驻留网页

void Application_Startup(object sender, StartupEventArgs e){    HtmlPage.RegisterScriptableObject("ShutdownManager", shutdownManager);    this.RootVisual = new MainPage();}

ShutdownManager

ShutdownManager 有两个属性修饰他们是 SciptableType  ScriptableMember正如下面我们所看到它们用于允许通过Ajax 调用 ShutdownManager 

[ScriptableType]public class ShutdownManager{    [ScriptableMember]    public string Shutdown()    {        string result = null;        var page = (MainPage)Application.Current.RootVisual;        if (page.Dirty)        {            var messageBoxResult = MessageBox.Show(                "Save changes you have made?", 		"Save changes?", MessageBoxButton.OKCancel);            if (messageBoxResult == MessageBoxResult.OK)            {                var waitingWindow = new WaitingWindow();                waitingWindow.Show();                waitingWindow.NoticeText = "Saving work on server. Please wait...";                page.SetNotice("Saving work on server. Please wait...");                var client = new ShutdownServiceClient();                client.SaveWorkCompleted += ((sender, e) =>                    {                        waitingWindow.NoticeText = 			"It is now safe to close this window.";                        page.SetNotice("It is now safe to close this window.");                        page.Dirty = false;                        waitingWindow.Close();                    });                client.SaveWorkAsync("Test id");                result = "Saving changes.";            }            else            {                result = "If you close this window you will lose any unsaved work.";            }        }        return result;    }}

在这里我们看到一旦调用 Shutdown 方法我们测试(Silverlight) 主页内容是否是被修改过的如果这样我们提示用户保存更改如果保存更改我们派遣我们使用一个服务客户端异步 web 服务调用关键一点请注意这里我们正在返回一个字符串如果主页内容被视为被修改过的字符串然后指示 JavaScript 代码立即关闭窗口一旦调用使回到我们的 JavaScript onbeforeload 处理程序我们将事件返回值 event.returnValue 赋值给字符串如果字符串导致 web 浏览器显示一个对话框 他们是否真的希望离开页面用户

图:浏览器提示“请确认...”的信息

在这个示例程序中 注意到我们模拟用户修改。即用户点击网页复选框表示网页内容被修改

图:模拟在示例应用程序中用户修改数据的操作


不点击复选框,关闭浏览器将立即关闭,点击复选框

图:提示保存修改对话框


如果用户取消操作会发生什么还记得我们在 JavaScript OnClose 函数的事件返回event.returnValue 字符串如果用户取消分配一个字符串"如果关闭窗口失去任何未保存工作我们可以看到浏览器是怎样选择并显示字符串的如下所示

图:浏览器启动对话框提示用户

很显然我们必须处理用户选择确定按钮保存对话框为了提供一个稍微更加令人愉快用户体验 Silverlight程序中引入 ChildWindow 作为进度控制

图:进度条提示用户正在保存


一旦用户点击确定保存更改对话框中web 服务几乎立即调用为了使 web服务调用发生我们必须执行中断线程以便我们的 Silverlight 应用程序机会调度调用操作我们用 JavaScript 警报调用可以做到一点或者正如我们看到在这里我们分配 event.returnValue事件返回值导致相同方式显示对话框

结论

篇文章我们看到如何实现一个 Silverlight 应用程序退出事件发生调用的 web 服务虽然可能可靠我会有兴趣知道实现种方法,或任何替代方法经验最后我们用户的交互,以允许取消关闭窗口事件执行最后一分钟的 web 服务调用交互方法使用 onbeforeunload 事件JavaScript 处理程序实现

谢谢阅读

许可

篇文章以及任何关联源代码文件,遵循 GNU 通用公共许可证(LGPLv3)版权许可 

原文地址:
http://www.codeproject.com/Articles/43157/Calling-Web-Services-from-Silverlight-after-the-Br


另:在Stack Overflow中相关问题:


How to detect a browser refresh from Silverlight 4?

My Silverlight 4 application keeps in contact with a server side through a wcf service. Whenever the user refreshes, navigates away or terminates the browser I should do some cleanup towards the server side.

I can not use the Application Exit event; my wcf client is dead before it eventually gets called. I can not use the (new in SL4) FrameworkElement Unloaded event; it ain't called when the Silverlight app shuts down.

So, how do I detect the browser refresh, newpage or shutdown in time to do my cleanup?


Jim McCurdy关于此问题的回复,本人尚未测试,原文如下:

I do this exact thing when a user navigates away from my Silverlight app (or does a refresh). Follow the steps below to catch this event.

1.) Start by listening for the HTML page's "onbeforeunload" event, like so...

public void Application_Startup(object sender, StartupEventArgs e){    bool ok = HtmlPage.Window.AttachEvent("onbeforeunload", Application_BeforeExit);    ok = HtmlPage.Document.AttachEvent("onbeforeunload", Application_BeforeExit);    MainPage mainPage = new MainPage();    base.RootVisual = mainPage;}

2.) Implement Application_BeforeExit() to setup and call an ASP.NET "PageMethod", like so...

private void Application_BeforeExit(object sender, HtmlEventArgs args){    string methodName = "ModelShutdown";    params object[] args = new Guid().ToString());;    try    {        ScriptObject pageMethods = (ScriptObject)HtmlPage.Window.GetProperty("PageMethods");        if (pageMethods == null)            throw new ArgumentException("Web page does not support PageMethods");        object[] pageMethodArgs = { new PageMethodEventHandler(Success), new PageMethodEventHandler(Failure), null/*userContext*/};        object[] combinedArgs = new object[args.Length + pageMethodArgs.Length];        args.CopyTo(combinedArgs, 0);        pageMethodArgs.CopyTo(combinedArgs, args.Length);        pageMethods.Invoke(methodName, combinedArgs);    }    catch (Exception ex)    {        //ex.Alert();    }}

3.) Add the PageMethod to your page code behind (Index.aspx.cs), like so,

public partial class Index : Page{    [WebMethod] // a PageMethod called from Silverlight    public static void ModelShutdown(string identifier)    {        System.Diagnostics.Debug.WriteLine("*** Signing Off: " + identifier);    }}

4.) Allow PageMethods on your page (Indx.aspx), like so,

<asp:ScriptManager runat="server" EnablePageMethods="true" /><div id="silverlightControlHost">    <object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="100%" height="100%">

Good luck,
Jim McCurdy, YinYangMoney.com



笔者测试,对该问题的处理方法进行了如下改进:

void Application_Exit(object sender, EventArgs e){    HtmlPage.Window.Invoke("OnUserSignOff",           new[] { "UserName" });}
  

在页面javascript添加脚本
function OnUserLogOff(identifier) {
            PageMethods.SignOff(identifier, OnSignOffComplete);
        }

        function OnSignOffComplete(result) {
        }


在index.asp.cs后台添加方法
       [WebMethod]
        public static void SignOff(string identifier)
        {
//WCF服务
            BServiceReference.BusinessServiceClient client = new BServiceReference.BusinessServiceClient();
            client.UserLogOff();
            //System.Diagnostics.Debug.WriteLine("*** Byebye: " + identifier);
        }

以上即可实现WCF在web页面服务端对wcf的调用

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
电脑网络-全面优化你的系统,让它飞起来吧~(申精)
面向领域驱动的应用开发框架Apworks 2.5发布
MapBasic资料
MEF程序设计指南二:Silverlight中使用CompositionInitializer宿主MEF
Excel Application对象应用大全
一步一步学Silverlight 2系列(1):创建一个基本的Silverlight应用
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服