How to logout on app exit in Silverlight application? - silverlight

I have a silverlight application with custom form authentication.
How i can logout application when the browser window is closed?
I tried something like this:
public App()
{
Startup += ApplicationStartup;
Exit += Application_Exit;
UnhandledException += ApplicationUnhandledException;
var webContext = new WebContext {Authentication = new FormsAuthentication()};
ApplicationLifetimeObjects.Add(webContext);
InitializeComponent();
}
private void ApplicationStartup(object sender, StartupEventArgs e)
{
Resources.Add("WebContext", WebContext.Current);
RootVisual = new MainPage();
}
private void Application_Exit(object sender, EventArgs e)
{
WebContext.Current.Authentication.Logout(false);
}
but this didn't work. Ewery time I close the browser, I receive the exception An AsyncCallback threw an exception without any details.
How can I handle this problem?

you could call an ajax call on the page with onbeforeunload, forget the idea to call logoff with silverlight whilst it is closing.

Related

How to hide the Download dialog in WebView2 while downloading page content or printing with "Save as PDF" option?

I know how to subscribe to the CoreWebview2.DownloadStarting event and use handled = true to stop the Download dialog from showing while a download (i.e. an image) is being made, but the problem is the DownloadStarting event never fires if you right click on a web page and choose "Save as" or "Print > Save as PDF", even though the Download dialog will appear as if a regular download was being made. Does anyone know any workaround for this?
My code:
public Form1()
{
InitializeComponent();
}
private async void button1_Click(object sender, EventArgs e)
{
if (webView != null)
webView.Dispose();
webView = new WebView2();
await webView.EnsureCoreWebView2Async();
webView.CoreWebView2.DownloadStarting += CoreWebView2_DownloadStarting;
panel1.Controls.Add(webView);
webView.Dock = DockStyle.Fill;
webView.Source = new Uri("https://www.microsoft.com");
}
private void CoreWebView2_DownloadStarting(object sender, CoreWebView2DownloadStartingEventArgs e)
{
e.Handled = true;
}
I just found a solution:
subscribe to CoreWebView2.IsDefaultDownloadDialogOpenChanged event:
webView.CoreWebView2.IsDefaultDownloadDialogOpenChanged += webView_CoreWebView2_IsDefaultDownloadDialogOpenChanged;
Close the Download dialog if it's open:
private void webView_CoreWebView2_IsDefaultDownloadDialogOpenChanged(object sender, object e)
{
if (webView.CoreWebView2.IsDefaultDownloadDialogOpen) webView.CoreWebView2.CloseDefaultDownloadDialog();
}

Monitoring ChromiumWebBrowser control initialization

We use the CefSharp's ChromiumWebBrowser control (83.4.20) in Windows Forms application.
We hook up the IsBrowserInitializedChanged event to know when the browser control was initialized so we can start loading our web application. Occasionally this event is not fired at all so our application will be stuck and won't load the web app.
In case the app is stuck in initializing the ChromiumWebBrowser control, the WebView_IsBrowserInitializedChanged or WebView_LoadError are not fired:
public MainForm()
{
InitializeComponent();
this.webView.IsBrowserInitializedChanged += WebView_IsBrowserInitializedChanged;
this.webView.LoadError += WebView_LoadError;
}
private void InitializeComponent()
{
this.webView = new CefSharp.WinForms.ChromiumWebBrowser();
// usual WinForms initialization code from the designer
// ...
}
private void WebView_IsBrowserInitializedChanged(object sender, EventArgs e)
{
if (this.webView.IsBrowserInitialized)
{
this.webView.Load(this.ApplicationUri.AbsoluteUri);
}
}
private void WebView_LoadError(object sender, LoadErrorEventArgs e)
{
// handle the error
// ...
}
Are there any other events we can subscribe to to monitor the state of CefSharp and the browser control which would aid as in troubleshooting this situation?

Best way to continuously monitor a MSMQ queue in WPF

I need my WPF exe to start monitoring a queue as soon as it starts up, and then respond to messages as they come in.
The way I have it now is:
public partial class App
{
readonly BackgroundWorker _worker = new BackgroundWorker();
protected override void OnStartup(StartupEventArgs e)
{
_worker.DoWork += worker_DoWork;
_worker.RunWorkerCompleted += worker_RunWorkerCompleted;
_worker.RunWorkerAsync();
}
void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
_worker.DoWork += worker_DoWork;
_worker.RunWorkerAsync();
}
static void worker_DoWork(object sender, DoWorkEventArgs e)
{
//do work
}
Obviously, this is pretty pathetic IMO.
Also, I don't like the approach of using while(true), inside the thread to keep it running indefinitely..
It's enough to read the messages from queue not permanently but periodically.
The common approach for this is using timer. For example, System.Threading.Timer.
public partial class App : Application
{
private System.Threading.Timer _msmqReadTimer;
public App()
{
_msmqReadTimer = new System.Threading.Timer(MsmqReadTimerTick);
_msmqReadTimer.Change(0, 1000); // call MsmqReadTimerTick immediatelly and each 1000 ms
}
private void MsmqReadTimerTick(object state)
{
// do work
// if you want to update some UI components after work, you should post this to UI thread dispatcher:
this.Dispatcher.Invoke(()=>
{
// logic for updating UI should be here
},
System.Windows.Threading.DispatcherPriority.Background);
}
}

MVVM - how show view?

My MVVM application started with App.xaml.cs
Here I create a main window. It has frame. Here I put LoginView.
It has button "Login". I have command, which checks and do login.
This code I have in LoginViewModel.
If all ok - I should show the next View. How I can do it?
App.xaml.cs
private void OnStartup(object sender, StartupEventArgs e)
{
LoginViewModel loginVM = new LoginViewModel();
MainView mainView = new MainView();
LoginView loginView = new LoginView();
loginView.DataContext = loginVM;
mainView.Frame.Content = loginView;
mainView.Show();
}
LoginViewModel.cs
// this method calls by binding after Click Login in LoginView
private void Login()
{
//TODO: Realize it
if (LoginModel.Login("User1", "Password"))
{
// HERE I SHOULD CLOSE LOGINVIEW AND SHOW NEXT VIEW
}
}
How and where I should show all necessary views?
I Use now WPF MVVM Toolkit.
In a situation such as this you could have your startup form be your main program, and the Login is a dialog box. If the dialog box fails, exit the program. If it succeeds, proceed in loading up the main form.
private void OnStartup(object sender, StartupEventArgs e)
{
LoginViewModel loginVM = new LoginViewModel();
LoginView loginView = new LoginView();
loginView.DataContext = loginVM;
loginView.ShowDialog(); // Change this to a ShowDialog instead of Show
if (!login.DialogResult.GetValueOrDefault())
{
// Should probably handle error in login class, not here");
Environment.Exit(0);
}
// This code will never get reached if Login fails
MainView mainView = new MainView();
mainView.Frame.Content = loginView;
mainView.Show(); // Change this to a ShowDialog instead of Show
}
I don't know anything about the MVVM Toolkit, but a simple way I did this was to have a delegate to do it, something like: (simplified code)
private void OnStartup(object sender, StartupEventArgs e)
{
LoginViewModel loginVM = new LoginViewModel();
loginVM.ShowNextScreen += () => {
SomeOtherVM nextVM = new SomeOtherVM();
nextVM.ShowForm();
}
// ...
}
So you have a 'ShowNextScreen' action on your VM which calls this code.
I have a small app on Google Code which does that (it also deals with only having one form open, error handling etc). Note that in this case, it's the ViewModel which has responsibility for opening the view.
But this is going to get complicated quickly, for any reasonable size of app you'd want to split this functionality out into some kind of 'application controller' which dealt with opening screens, navigation etc.

Winforms: Best way to keep winforms app unlocked?

I have a winforms app, that's locking up during a web service request
I've tried using doEvents to keep the app unlocked, but its still not responsive enough,
How can I get around this locking, so that the app is responsive at all times?
The best way is simply to do your IO work on another thread, perhaps via BackgroundWorker, or the async methods of WebClient.
See perhaps here. Be sure to use Invoke when talking back to the UI controls (thread affinity); full example:
using System;
using System.Net;
using System.Windows.Forms;
class MyForm : Form
{
Button btn;
TextBox txt;
WebClient client;
public MyForm()
{
btn = new Button();
btn.Text = "Download";
txt = new TextBox();
txt.Multiline = true;
txt.Dock = DockStyle.Right;
Controls.Add(btn);
Controls.Add(txt);
btn.Click += new EventHandler(btn_Click);
client = new WebClient();
client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(client_DownloadStringCompleted);
}
void client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
Invoke((MethodInvoker)delegate
{
if (e.Cancelled) txt.Text = "Cancelled";
else if (e.Error != null) txt.Text = e.Error.Message;
else txt.Text = e.Result;
});
}
void btn_Click(object sender, EventArgs e)
{
client.DownloadStringAsync(new Uri("http://google.com"));
}
}
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.Run(new MyForm());
}
}
Do the web service request in a background thread. Be cautious of too many calls to Application.DoEvents().

Resources