2010-09-07 4 views
2

Приложение My Silverlight 4 поддерживает связь с сервером через службу wcf. Всякий раз, когда пользователь обновляется, перемещается или завершает работу браузера, я должен выполнить некоторую очистку на стороне сервера.Как обнаружить обновление браузера от Silverlight 4?

Я не могу использовать событие Exit Exit; мой wcf-клиент мертв до того, как он в конечном итоге вызван. Я не могу использовать (новое в SL4) событие FrameworkElement Unloaded; он не вызывается, когда приложение Silverlight отключается.

Итак, как определить обновление браузера, новую страницу или завершение работы во времени выполнить мою очистку?

ответ

2

Баба,

я это точно вещь, когда пользователь переходит от моего Silverlight приложения (или делает обновление). Выполните следующие действия, чтобы поймать это событие.

1.) Начните прослушивание "onbeforeunload" событие HTML-страницы, как так ...

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.) Реализовать Application_BeforeExit() для установки и называем ASP.NET "PageMethod", как так ...

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.) Добавьте PageMethod на свой код страницы позади (Index.aspx.cs), как это так,

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.) Разрешить PageMethods на странице (Indx.aspx), как это так,

<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%"> 

Успехов,
Джим McCurdy, YinYangMoney.com

+0

Большое спасибо Джим! Я признаю, что надеялся на более чистое решение, т. Е. Без aspx/javascript. Я считаю, что лучше держаться подальше от браузера. Но я неохотно начинаю понимать, что другого пути не может быть. Кстати; ваше решение работает в Firefox и Chrome, а также в IE? – BaBu

+0

Я просто понял, что вы можете позвонить в службу WCF вместо того, чтобы делать подход PageMethod; это будет работать так же хорошо. Единственное, что вы не сможете сделать, это получить завершенное событие из асинхронного вызова, так как после того, как вы покинете метод Application_BeforeExit(), приложение Silverlight исчезнет. И он должен работать в любом браузере; вот почему я перечислил 2 разных вызова AttachEvent(). –

+0

Еще раз спасибо Джим. Извините, что вызов службы wcf из Application_BeforeExit() никогда не доходит до сервера. Я провел некоторое исследование, и кажется, что ваше первоначальное решение или подобные подходы - единственный способ справиться с этим. См. http://forums.silverlight.net/forums/t/20279.aspx. Я предполагаю, что какая-то будущая версия Silverlight предложит решение этой проблемы. Ведь «save on exit» - очень полезная функция. – BaBu

0

Я не думаю, что вы можете сделать что-нибудь серверное после того, как пользователь решил перейти или браузер был прерван. Однако вы можете написать JavaScript, чтобы предотвратить выгрузку текущей страницы, где вы можете предупредить пользователя о том, чтобы не закрывать его.

Во-вторых, используйте небольшой таймер сеанса, который тикает каждые две минуты или около того. В вашем сеансе должен быть тайм-аут, но когда приложение Silverlight открыто и работает в браузере, вы должны пинговать свой сервер, написав какой-нибудь метод ping, который будет поддерживать вашу сессию в течение одной минуты.

Итак, если ваш сеанс заканчивается (он не получил пинг за последние 60 секунд), ваш сеанс будет уничтожен, и вы можете написать код очистки на конце сеанса сервера.

+0

Акаши, Спасибо за ваш ответ. У меня действительно есть сеансовый таймер, как вы описываете, но пользователь может быть злым, обновить браузер и повторно зайти в систему * до того, как он запустится. Во всяком случае, было бы неплохо сделать очистку упорядоченным образом, когда это произойдет а не зависеть от таймера сеанса (keepalive), чтобы забрать. – BaBu

0

У меня было подобное требование для приложения MVC. То, что я сделал с помощью JQuery, чтобы подписаться на событие разгрузки и сделать Ajax вызов действия контроллера, который убил сессию:

$(window).unload(function() { 
    $.ajax({url: Url.Action("KillSession")}); 
}); 

public ActionResult KillSession() 
{ 
    Session.Abandon(); 
    return new HttpStatusCodeResult(System.Net.HttpStatusCode.NotModified); 
}