I have a form that on load show login form on webbrowser. When user login and then exit without loging out, it automatically logging him out on next start up and showing him again the login form. To logout from site 2 navigations needed but I don't user to see that navigations, I want the browser to be white until all navigations complete or something similar.
bool f = true;
private void Form1_Load(object sender, EventArgs e)
{
wbLoad.Navigate("http://login.uid.me/?site=dmysite&ref=http://mysite.ucoz.com/");
}
private void wbLoad_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
if (f == true)
{
if (wbLoad.DocumentText.Contains("Sign up"))
{
wbLoad.Navigate("http://login.uid.me/?site=dmysite&ref=http://mysite.ucoz.com/");
f = false;
}
else if (wbLoad.DocumentText.Contains("Log out"))
{
wbLoad.Navigate("http://mysite.ucoz.com/index/10");
f = true;
}
else
{
wbLoad.Navigate("http://uid.me/logout/?mode=1&noajax=1");
f = true;
}
}
}
Logging out means in most cases just removing cookies for current host. If it's your case, you can do it by using javascript. Note, that this JS will remove cookies only for current host. You can call it in FormClosing event
wbLoad.Navigate("javascript:void((function(){var a,b,c,e,f;f=0;a=document.cookie.split('; ');for(e=0;e<a.length&&a[e];e++){f++;for(b='.'+location.host;b;b=b.replace(/^(?:%5C.|[^%5C.]+)/,'')){for(c=location.pathname;c;c=c.replace(/.$/,'')){document.cookie=(a[e]+'; domain='+b+'; path='+c+'; expires='+new Date((new Date()).getTime()-1e11).toGMTString());}}}})())");
You need to write the logout concept in Form Close event or some where else. So next time when user opens that time it will automatically redirects to login page. And need to refresh all your objects after logout.
Related
This answer shows how to trigger the onbeforeunload event in a WebBrowser control in the following way:
protected override void OnFormClosing(FormClosingEventArgs e)
{
if (!this.formsWebBrowser.IsDisposed)
{
//// Generate SHDocVw.dll: Visual Studio Developer Command Prompt "tlbimp.exe ieframe.dll /out: C:\temp\SHDocVw.dll",
var activeX = this.formsWebBrowser.ActiveXInstance;
var input = Type.Missing;
object leavePage = true;
((SHDocVw.WebBrowser)activeX).ExecWB(
SHDocVw.OLECMDID.OLECMDID_ONUNLOAD,
SHDocVw.OLECMDEXECOPT.OLECMDEXECOPT_DODEFAULT,
ref input,
ref leavePage);
if (!(bool)leavePage)
{
e.Cancel = true;
return;
}
}
base.OnFormClosing(e);
}
But now trying to move away from IE11 (as used by WebBrowser) to Edge Chromium with the WebView2 control, I can't figure out how to do the same thing in WebView2.
The dialog shows correctly when navigating the WebView2 to another page.
The problem comes when the user closes the application or the window containing the WebView2.
It then just closes without showing any dialog.
That's what the code above does for the WebBrowser control, when closing the application the (on)beforeonload event is triggered in the IE11 browser and a bool is returned. True if the user pressed "Leave" or there isn't an beforeonload event active and false if the user pressed "Stay on the page".
Short of calling ExecuteScriptAsync("onbeforeunload();") (which doesn't work when setting the event with window.addEventListener("beforeunload", function(event) { ... });) how can the same be done in WebView2?
Edit:
The problem is that I don't want to show the dialog always when closing, unless I really have to.
I only want to show it if the page has unsaved changes (and it communicates that in the beforeunload event in JavaScript).
The only way I know how handle that in the C#-code is by triggering the built in onunload event showing the beforeunload dialog in the browser.
That is exactly what the ActiveXInstance.ExecWB(OLECMDID_ONUNLOAD) does for the WebBrowser control and IE11.
It may simply not be possible to trigger that event in WebView2/Chromium in the same way? That's really what I'm asking.
I've tried calling JavaScripts in the FormClosing event, but the application just closes w/o waiting for the response.
I guess the only other option is to remove the x-close button and use a custom close button that can do the needed checks and then close the application.
This is working for me. You can combine it with a form closing or something. Don't forget to properly detach events / dispose where proper. This is just a sample.
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
private void Form2_Load(object sender, EventArgs e)
{
DoWork();
}
private async Task DoWork()
{
await webView21.EnsureCoreWebView2Async();
webView21.CoreWebView2.Settings.AreDefaultScriptDialogsEnabled = false;
webView21.CoreWebView2.ScriptDialogOpening += CoreWebView2_ScriptDialogOpening;
await webView21.CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync("window.addEventListener('beforeunload', function(e) { return event.returnValue = 'prompt';});");
webView21.Source = new Uri("https://www.google.com");
}
private void CoreWebView2_ScriptDialogOpening(object sender, Microsoft.Web.WebView2.Core.CoreWebView2ScriptDialogOpeningEventArgs e)
{
if (MessageBox.Show("do you want to leave", "Leave?", MessageBoxButtons.OKCancel) == DialogResult.OK)
{
e.Accept();
}
else
{
e.GetDeferral();
}
}
Okay, this one will be a fun one. I am building an authentication flow in my application. My application will open a modal window with a webbrowser element and browse to the auth URL. Then it wil monitor the URL changes of the webbrowser element for a specific string. When it finds the string, it does it's work to retrieve the access code, closes the window and then returns the code to the parent. My code is as follows:
The modal window:
public partial class Browser : Window
{
private string code = "";
private Uri navi;
public TwitchBrowser(Uri url)
{
InitializeComponent();
this.navi = url;
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
webBrowser.Navigate(this.navi);
webBrowser.Navigating += webBrowser_Navigating;
}
void webBrowser_Navigating(object sender, NavigatingCancelEventArgs e)
{
if (e.Uri.ToString().Contains("?code="))
{
this.code = e.Uri.ToString().Split('?')[1].Split('&')[0].Replace("code=", "");
this.DialogResult = true;
}
}
public string result
{
get { return code; }
}
}
The call from the parent:
string url = ...
Browser browser = new Browser(new Uri(url));
browser.Owner = parent;
if (browser.ShowDialog() == true)
{
password.Password = browser.result;
...
}
And of course, the error I get:
DialogResult can be set only after Window is created and shown as dialog.
The interesting thing is, the app WORKS! It gets the code and stores it in the password field as it's supposed to. So whats the point of the error? I mean, I know I can suppress it with a Try-Catch; but I'm afraid its the root of a larger problem.
You original code had a race condition in there. You were navigating in the creation of browser. The navigation complete could be fired before you called ShowDialog().
Instead stash away the url in a private variable and setup the WebBrowser in your Loaded event.
Now that you have fixed that, I am guessing that you want the Nagivated event instead of the Navigating event to check the returned URI.
It is still interesting that the Navigating event gives that error. I was able to reproduce it with a button click on the form, so I know the form is completely shown at that point.
I am developing a Web app for conducting a Online examination. I want to stop the contestants from refreshing the page in the browser. If they do I want to navigate them to a page which says they are disqualified. How can I implement this?
The following code snippet detects 'Refresh' in page_load function
bool IsPageRefresh = false;
protected void Page_Load(object sender, EventArgs e)
{
//this section of code checks if the page postback is due to genuine submit by user or by pressing "refresh"
if (!IsPostBack)
{
ViewState["ViewStateId"] = System.Guid.NewGuid().ToString();
Session["SessionId"] = ViewState["ViewStateId"].ToString();
}
else
{
if (ViewState["ViewStateId"].ToString() != Session["SessionId"].ToString())
{
IsPageRefresh = true;
}
Session["SessionId"] = System.Guid.NewGuid().ToString();
ViewState["ViewStateId"] = Session["SessionId"].ToString();
}
}
You can then use the 'IsPageRefresh' boolean flag in the code-behind to determine if it's a postback due to genuine User submit action or by browser 'Refresh'.
On start of my Application Login Form comes up I have simply stored username and password and compared for validating user, if user is valid than MDIparent Form gets opened, Now I want to create logout for this Application. How I can do this?
When I searched I Found That I can do this on FormClosing Event or FormClosed Event but what code should be written in that and for which form, only Dispose(); is enough or something more?
What if I want Login Form to get displayed back?
Showing MDI Form after Successful Login Like this
private void login_Click(object sender, EventArgs e)
{
//if password true then send true
bool value = namePasswordEntry(getHashedUserName, txtUserName.Text, getHashedPassword, txtPassword.Text);
if (value ==true)
{
MessageBox.Show("Thank you for activation!");
this.Hide();
Form2 pfrm = new Form2(txtUserName.Text);
pfrm.ShowDialog();
}
else
{
MessageBox.Show("Invalid LoginName or Password..");
}
}
Try the following codes in the form closing event
Application.Exit(); - Informs all message pumps that they must terminate, and then closes all application windows after the messages have been processed.
System.Environment.Exit(1); - Terminates this process and gives the underlying operating system the specified exit code.
Application.Restart() - Shuts down the application and starts a new instance immediately.
Source : http://msdn.microsoft.com/
You Should try this on cancel button or your form closing event........................... Application.Exit();
if (value ==true)
{
MessageBox.Show("Thank you for activation!");
this.Hide();
Form2 pfrm = new Form2(txtUserName.Text);
pfrm.ShowDialog();
pfrom.Dispose(); //because user has logged out so the data must be flushed, by "Disposing" it will not be in the RAM anymore, so your hanging problem will be solved
this.Show(); //just add this line here
}
To Logout using Link Label you just need to raise the click event of it. Write this code in the Form2 constructor:
linkLabel1.Click += linkLabel1_Click;
and then create a method:
void linkLabel1_Click(object sender, EventArgs e)
{
this.Close();
}
If anyone still needs this solution:
private void logoutButton_Click(object sender, EventArgs e)
{
this.close();
}
I have this form called MainForm.cs. When I click Enter The Progam button I display another form using the .ShowDialog() method.
In this new form called LoginBox.cs, I check if the entered credentials are valid and if they are I want my MainForm.cs to react with either a positive responde (the actual software form opens) or negative response a MessageBox alerting him of the failure.
It's a very simple use case, but I don't know how to solve this correctly and efficiently. Thank you.
private void button1_Click(object sender, EventArgs e)
{
LoginBox login = new LoginBox();
login.ShowDialog();
}
//And in the LoginBox.cs file:
private void button1_Click(object sender, EventArgs e)
{
if ((txtUser.Text == "admin") && (txtPassword.Text == "123"))
{
}
}
If you open the form with ShowDialog it returns a DialogResult which you can check in your main form.
LoginBox login = new LoginBox();
DialogResult dialogResult = login.ShowDialog();
if (dialogResult == DialogResult.OK)
{
// etc...
}
You can set the value of DialogResult in your LoginBox form:
DialogResult = DialogResult.OK;
Others have mentioned using DialogResult, which can work--but might be abused a bit in this use-case. Its intended purpose is to let the parent form know what the user did on a child form--did they click OK or Cancel? Did they click Retry or Abort? It's not intuitive that it should be used for authentication purposes.
So--what's better? Probably a combination...
Your LoginBox class is a Dialog, so returning a DialogResult should be expected--but should also only be used to indicate what the user did on the Form, not the outcome of the authentication.
I would suggest looking into the usage of some other dialogs, such as OpenFileDialog. It returns a DialogResult to specify whether to go ahead with the file opening, but it doesn't actually open the file until being explicitly told to do so. This means the consuming code has to both check the result and instruct the dialog to perform it's function, so it's not perfectly simple--but it's fairly conventional.
Here's an example of how I would suggest you use LoginBox:
private void button1_Click(object sender, EventArgs e)
{
LoginBox login = new LoginBox();
if (login.ShowDialog() == DialogResult.OK) // Let the user input their credentials and click OK or Cancel
{
if (!login.ValidateCredentials) // Perform the authentication with the collected credentials
{
MessageBox.Show("The specified Credentials were invalid!");
}
}
}
Add an Event to the LoginBox. Then have the MainForm handle that event. In the event handler proceed with the additional logic that you want to perform.