Clear session/cookies on Browser tab/window exit - c#

I'm working on an asp.net project (written awhile ago), and users say they want to be able to log out on "x'ing" out the tab or browser.
I've been looking around this site and have tried a few things with no luck. It doesn't seem like there is an easy way about this with there being different browsers.
First, here's a logout function which is called from a logout button.
public void LoginStatus1_LoggingOut(object sender, LoginCancelEventArgs e)
{
Response.Cookies.Clear();
Session.Clear();
HttpContext.Current.User = null;
FormsAuthentication.SignOut();
}
It would be nice if I could somehow call that when closing the tab/browser.
There is this javascript in the master page:
<script type="text/javascript">
// Copyright 2006-2007 javascript-array.com
var timeout = 500;
var closetimer = 0;
var ddmenuitem = 0;
// open hidden layer
function mopen(id)
{
// cancel close timer
mcancelclosetime();
// close old layer
if(ddmenuitem) ddmenuitem.style.visibility = 'hidden';
// get new layer and show it
ddmenuitem = document.getElementById(id);
ddmenuitem.style.visibility = 'visible';
}
// close showed layer
function mclose()
{
if(ddmenuitem) ddmenuitem.style.visibility = 'hidden';
}
// go close timer
function mclosetime()
{
closetimer = window.setTimeout(mclose, timeout);
}
// cancel close timer
function mcancelclosetime()
{
if(closetimer)
{
window.clearTimeout(closetimer);
closetimer = null;
}
}
// close layer when click-out
document.onclick = mclose;
</script>
However, it doesn't seem to work. I messed around w/ the timeout variable and no matter how long I wait after I exit the tab/browser, the cookies/session do not clear out. I know chrome has a "continue where you left off" feature, and other browsers have similar I'm sure. Unfortunately, all of the users don't use the same browsers.
Any ideas would be most welcome!

Related

How do I pass the C # Selenium Error Page?

I'm writing a bot with c # selenium. (The working logic of the bot is simply that there are 20 companies on each page, they go back to the detail page and get the data back. They go through all the companies in order. After getting the data of the last company, they continue to the next page.) After visiting 200-250 companies, the page in the picture opens. Bot's stopping progress. If I press the F5 menu manually, the bot continues to progress, but it doesn't work when we try with the code.
How do I resolve this error?
Error Page
I noticed it was on the way back from the detail page of this page. To go back;
driver.navigate().Back();
driver.navigate().GoToUrl("");
//I tried to go back with the codes but the solution was not.
I get this Error because the error page does not pass.
Bot needs to visit all companies without encountering an error page.
A correct approach for this is to wait for some amount of time for some element you expect on the page using WebDriverWait.
In this example, I wait for 10 seconds and look for element id 'some-id'.
You can change the criteria by replacing By.Id("some-id") with some other condition.
More about By class.
var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
driver.Navigate().GoToUrl("https://www.somedomain.com");
var validPage = false;
try
{
validPage = wait.Until(c =>
{
try
{
return driver.FindElement(By.Id("some-id")) != null;
}
catch
{
return false;
}
});
}
catch
{
// not exist
}
if (validPage == true)
{
// ok.
}
else
{
}

SignalR message being sent to every opened page instance. How to send to only exact one?

This question has been answered multiple times, but I'm still not getting it.
I am using an example from this page: https://www.codeproject.com/Articles/1124691/SignalR-Progress-Bar-Simple-Example-Sending-Live-D
However, I've modified the SendProgress method a bit, to send the message only to the specific connection, not all clients:
public static void SendProgress(string connectionId, string progressMessage, int progressCount, int totalItems)
{
var hubContext = GlobalHost.ConnectionManager.GetHubContext<RealTimeProgressBar.ProgressHub>();
var percentage = (progressCount * 100) / totalItems;
hubContext.Clients.Client(connectionId).AddProgress(progressMessage, percentage + "%");
}
I am getting connection Id from overrided OnConnected method:
public override Task OnConnected()
{
Environments.ConnectionId = Context.ConnectionId;
return base.OnConnected();
}
I'm currently storing it in a static class Environments, I guess there is a better way for doing so, but I don't know it yet :)
The question is, when I open for example two instances of my web page in browser, the progress bar is still being shown for all of these instances, though the connectionIds on these pages are different (checked it in SendProgress function).
What is wrong here?
Perhaps, I should change something in js code?
$(function () {
// Reference the auto-generated proxy for the hub.
var progress = $.connection.progressHub;
console.log(progress);
// Create a function that the hub can call back to display messages.
progress.client.AddProgress = function (message, percentage) {
ProgressBarModal("show", message + " " + percentage);
$('#ProgressMessage').width(percentage);
if (percentage == "100%") {
ProgressBarModal();
}
};
$.connection.hub.start().done(function () {
var connectionId = $.connection.hub.id;
console.log(connectionId);
});
});
As i'm not really sure if js funcs really uses Environments.ConnectionId or smthing else..
Thanks!
Edit: What I want to achive is to send unique progress bars for every opened page. e.g. when I press the button on a first page, I'm starting to collect data and progress bar reflects that. I also open another page in a browser, and collect data from another source, so the progress bar should reflect that for this page as well.
my controller method:
public ActionResult Generate(InputDataViewModel viewModel, string connectionId)
{
...
var Tasks = getResultsWithProgressBar(viewModel.jobId, connectionId);
...
return RedirectToAction("Details", new { id = job.JobDataId });
}
and somewhere inside this "getResult" is a function that actually calls progress bar(SendProgress)
Your change should work fine.
You are using a static ConnectionId, so only your last browser, the browser you opened last(or connected last) will see the progress bar as well as updates.
This is the only one i made apart apart from adding in the static Environment.ConnectionId.
//PUSHING DATA TO ALL CLIENTS
// hubContext.Clients.All.AddProgress(progressMessage, percentage + "%");
hubContext.Clients.Client(Environments.ConnectionId).AddProgress(progressMessage, percentage + "%");
So if you open 10 browser windows and click on the button on all those, one by one, only the browser you initially opened last will see the the progress bar as well as updates, but it will see updates from all the 10 browsers shown on that single progress bar!
It is fun to see though!
When I tried your code, I saw the behavior you observed initially. But when I opened two separate Incognito browsers, I see the correct behavior. Close the IIS express site, rebuild and retry it.
Edit:
If you need each tab to have its own progress bar, then you will need one of the two approaches below:
A way to identify which rest request came from which connectionId. If you want to continue using the current code. Just pass in the connection Id to the LongRunningProcess. Client code below:
var progress = $.connection.progressHub;
var connectionId = $.connection.hub.id;
$.getJSON("/Home/LongRunningProcess",
{"connectionId":connectionId},
function (data) {
if (!data) {
alert("Success");
}
else
{
alert(data);
}
});
Server code would be:
public JsonResult LongRunningProcess(string connectionId)
{
//THIS COULD BE SOME LIST OF DATA
int itemsCount = 100;
for (int i = 0; i <= itemsCount; i++)
{
//SIMULATING SOME TASK
Thread.Sleep(500);
//CALLING A FUNCTION THAT CALCULATES PERCENTAGE AND SENDS THE DATA TO THE CLIENT
Functions.SendProgress(connectionId, "Process in progress...", i , itemsCount);
}
return Json("", JsonRequestBehavior.AllowGet);
}
The other option is to call a signalr method on the server instead of a rest method. Create a new hub method in the ProgressHub like below:
public void LongRunningHubMethod()
{
//THIS COULD BE SOME LIST OF DATA
int itemsCount = 100;
for (int i = 0; i <= itemsCount; i++)
{
//SIMULATING SOME TASK
Thread.Sleep(500);
//CALLING A FUNCTION THAT CALCULATES PERCENTAGE AND SENDS THE DATA TO THE CLIENT
Functions.SendProgress(Context.ConnectionId, "Process in progress...", i, itemsCount);
}
}
The client would then just call in the hub method on click like below:
var progress = $.connection.progressHub;
var connectionId = $.connection.hub.id;
progress.invoke('LongRunningHubMethod');

Refresh web api

Hello I initialize the api/page using a simple web api controller, my question is how to reinitialize the xml values every few seconds without refreshing the whole page. The scope of this is to detect the database changes (if any) and show them in real time on the page.
My api is similar to this:
https://learn.microsoft.com/en-us/aspnet/web-api/overview/getting-started-with-aspnet-web-api/tutorial-your-first-web-api
the api is initialized with data from the db, but i want to continously recall the function so the values would change if the the db values change.
Per your example, something like:
$(document).ready(function () {
setInterval(
// Send an AJAX request
$.getJSON(uri)
.done(function (data) {
//clear products list
$('#products').html('');
// On success, 'data' contains a list of products.
$.each(data, function (key, item) {
// Add a list item for the product.
$('<li>', { text: formatItem(item) }).appendTo($('#products'));
});
});
, 3000);
});
This will call your API endpoint every three seconds, clear the products element and reload the list. This method is called polling and will be called whether your data has changed or not. You could also implement this via SignalR, which would be closer to real-time and would be event driven refreshing, but that might be more complicated than what you are trying to do.
As per your request, this is a simple timer function
using System.Timers:
Timer timer; = new Timer();
timer.Interval = 10000; // 10 seconds, change this as required
timer.Elapsed += new ElapsedEventHandler(Timer_Elapsed);
timer.Enabled = true;
timer.Start();
void Timer_Elapsed(object sender, ElapsedEventArgs e)
{
timer.Stop();
//Call your database function and initialize as you want here
timer.Start();
}
Or you can refer this (recommended)-
Scheduling Web Api method to run on set intervals
I think you are getting something from particular table and tables values always change right . Ones you are created web api and if you want to refresh . You need to schedule the api(url). Which means that just need to trigger it.
If you are using windows you can schedule your api(url).
step1: Go to control panel and select administrative Tools.
Step2: After that select tack scheduler .
step3: Right side Actions you can see "Create Task"
step4:it will redirect to new window . In general just add name .
Step4.1:- click on Trigger . There you can schedule it properly(Time and date or daily)
Step4.2:-After that click on Action . Create click new .
There youn can see Program\script: add your path like this:
"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe"
one more option is there "Add Arguments(optional)": "Here you can
add your api link or url"
click ok . its completed . have a wonderful day. Thank you .
public class MachineController : ApiController
{
Machine[] machines = Gateway.test2(10);
public IEnumerable<Machine> GetAllMachines()
{
return machines;
}
public IHttpActionResult GetMachine(int id)
{
var machine = machines.FirstOrDefault((p) => p.id == id);
if (machine == null)
{
return NotFound();
}
else
return Ok(machine);
}
}
}
public static Machine[] test2(int i)
{
Machine[] result = new Machine[i+1];
for (int j = 0; j < 10; j++)
{
result[j] = testDatabaseCon(j + 1);
result[j].id = j + 1;
}
result[i] = new Machine();
result[i].name = "test";
result[i].description = "test";
result[i].EnteredCount++;
return result;
}

How to Implement Progress Bar for Long Running HTTP Request

I have an HTTP server written in C# based off the HttpListenerContext class. The server is for processing binary log files and converting them to text, and can take quite a long time to do the conversion. I would like to indicate progress back to the user, but I am unsure on the best way to do this. On the server side, in handling my HTTP request, I essentially have this function:
public async Task HandleRequest()
{
try
{
await ProcessRequest();
}
catch (HttpListenerException)
{
// Something happened to the http connection, don't try to send anything
}
catch (Exception e)
{
SendFailureResponse(500);
}
}
Currently, ProcessRequest() sends the HTML response when finished, but I would like to essentially add the IProgress interface to the function and somehow indicate that progress back to the Web client. What is the best way to do this?
One way of doing it would be to store progress on server side and periodically pull the information from client.
However, if you want the server to notify the client ( push ), then you will need to implement some kind of bi-directional communication between the server and client (I am currently using ASP.NET Web API and SignalR to achieve this at work).
Here is what I got I'll try to explain and I hope you notice its not FULL FULL complete, you'll have to understand the logic behind this and accept or not as a plausible option.
The Method: Set a custom object to store progress of your ongoing operations, make a global static list containing this metadata. Notice how I track them with Ids: I don't store that on DB, the natural act of instantiating the class will auto_increment their Id.
Then, you can add a new controller to respond the progress of a particular ongoing process.
Now that you have a controller to respond the progress of an ongoing process by Id, you can create a javascript timer to call it and update the DOM.
When creating your process, dont hold the htmlrequest until its over, open a background operation instead and just respond with the newly created ProgressTracker.Id, through that class/list you can keep track of the progress and reply accordingly.
As said in another answer, when an operation finishes you can send a push notification and the clientside javascript will interrupt the timers and proceed to the next view/result/page, or you can increment the looping timer to detect when its done and call the results from another controller. (this way you can avoid using push if needed.)
Here is the partial code:
public class ProgressTracker {
private static GlobalIdProvider = 0;
public int _id = ++GlobalIdProvider;
public int Id { get { return _id; } }
bool IsInProgress = false;
bool IsComplete = false;
float Progress;
public YourProgressObject Data;
}
public class GlobalStatic {
public static List<ProgressTracker> FooOperations = new List<ProgressTracker>();
}
public class SomeWebApiController {
[HttpGet]
[Authorize]
public HttpResponseMessage GetProgress(int Id) {
var query = (from a in GlobalStatic.FooOperations where a.Id==Id select a);
if(!query.Any()) {
return Request.CreateResponse(HttpStatusCode.NotFound, "No operation with this Id found.");
} else {
return Request.CreateResponse(HttpStatusCode.Ok, query.First());
}
}
}
// this is javascript
// ... Your code until it starts the process.
// You'll have to get the ProgressTracker Id from the server somehow.
var InProgress = true;
window.setTimeout(function(e) {
var xmlhttp = new XMLHttpRequest();
var url = "<myHostSomething>/SomeWebApiController/GetProgress?Id="+theId;
xmlhttp.setRequestHeader("Authentication","bearer "+localStorage.getItem("access_token"));
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
var data = JSON.parse(xmlhttp.responseText);
updateProgressBar(data);
}
}
xmlhttp.open("GET", url, true);
xmlhttp.send();
function updateProgressBar(data) {
document.getElementById("myProgressText").innerHTML = data.Progress;
}
}, 3000);
Disclaimer: If my javascript is shitty, pardon me but I'm too used to using jQuery and all this fancy stuff x_x

Selenium RC Reminiscing the "End of the World"

To explain the title.. Selenium RC keeps insisting that
A system shutdown has already been scheduled
and refusing to conduct automated tests because of this.. I can understand the logic here, I mean you're not going to do your homework if you thought the world would end with a nuclear holocaust...
However.. this is not the Cold War and when I inspect several basic things (such as using shutdown \a, completing a full restart) I find that this is actually not the case!
How can I convince selenium that the world is not going to end and that it should probably do the work I'm telling it to?
N.B. Here, selenium has "refused" to initialise any instance of IE, and will continue to hang until it times out, regardless of clicking Yes or No. I'm using NUnit, c#/.net4.0 to control the tests.
To fix this I replaced the default "runSeleniumTest" function with the below patched version as a user extension:
function runSeleniumTest() {
runOptions = new RemoteRunnerOptions();
var testAppWindow;
if (runOptions.isMultiWindowMode()) {
try{
testAppWindow = openSeparateApplicationWindow('Blank.html', true);
}
catch (e) {
window.onunload = function () { };
window.location.reload();
return;
}
} else if (sel$('selenium_myiframe') != null) {
var myiframe = sel$('selenium_myiframe');
if (myiframe) {
testAppWindow = myiframe.contentWindow;
}
}
else {
proxyInjectionMode = true;
testAppWindow = window;
}
selenium = Selenium.createForWindow(testAppWindow, proxyInjectionMode);
if (runOptions.getBaseUrl()) {
selenium.browserbot.baseUrl = runOptions.getBaseUrl();
}
if (!debugMode) {
debugMode = runOptions.isDebugMode();
}
if (proxyInjectionMode) {
LOG.logHook = logToRc;
selenium.browserbot._modifyWindow(testAppWindow);
}
else if (debugMode) {
LOG.logHook = logToRc;
}
window.selenium = selenium;
commandFactory = new CommandHandlerFactory();
commandFactory.registerAll(selenium);
currentTest = new RemoteRunner(commandFactory);
var doContinue = runOptions.getContinue();
if (doContinue != null) postResult = "OK";
currentTest.start();
}
I found that the "a system shutdown has already been scheduled" error occurred inside of "openSeparateApplicationWindow". I also found that refreshing the selenium test runner window after the error occurred would "restart" the test without the error. Therefore, I patched the "runSeleniumTest" with the following try catch statement so the test runner window reloads if there's an error in "openSeparateApplicationWindow":
try{
testAppWindow = openSeparateApplicationWindow('Blank.html', true);
}
catch (e) {
window.onunload = function () { };
window.location.reload();
return;
}
I also used my blog post for a more specific example of selenium user extensions
Selenium isn't doing anything in this case. That's the IE HTA agent (a built-in Windows process) that's preventing you from doing anything. Perhaps rebooting the machine will do the trick? It looks like you may just have a pending Windows update that's scheduled a future reboot.

Categories

Resources