ASP.Net ThreadPool Delegate Callback -- JavaScript Not Firing On Callback Thread - javascript

I have searched for several days now, and have tried about every solution that I could find. I know this is something I am not doing correctly, however, I am not sure what the correct way is.
I have an ASP.Net C# web site, running on .Net Framework 4.5. I have a link button on a form, that when clicked fires off a long running process using the ThreadPool. I have a delegate callback setup, and the code does fire when the process is canceled or when it finishes. (I am using the Cancelation Token for canceling the process and the process is Active Reports in case that matters.)
Like I said, everything works great, except for when the callback code fires it does not execute the javascript. (FYI -- this is NOT a javascript callback, just trying to fire off some javascript code when the process finishes.)
Here is the code that i start the report...
string sThreadID = Thread.CurrentThread.ManagedThreadId.ToString();
ThreadPool.QueueUserWorkItem(new WaitCallback(StartReport), cts.Token);
Here is the code for the StartReport....
public static void StartReport(object obj) {
try {
OnTaskCompleteDelegate callback = new OnTaskCompleteDelegate(OnTaskComplete);
BoyceReporting.CallReport(boyce.BoyceThreadingEnvironment.OBRO, "THREADING");
if (boyce.BoyceThreadingEnvironment.CTS.Token.IsCancellationRequested) {
boyce.BoyceThreadingEnvironment.SESSION.sScriptToExecute = "alert('Report Canceled By User');";
callback("CANCELED");
} else {
callback("FINISHED");
}
} catch {
throw;
}
}
Here is the code for the CallBack code.....
public static void OnTaskComplete(string ReportResult) {
try {
sReportResult = ReportResult;
if (ReportResult == "CANCELED") {
// In case we need to do additional things if the report is canceled
}
string sThreadID = Thread.CurrentThread.ManagedThreadId.ToString();
boyce.BoyceThreadingEnvironment.THISPAGE.ClientScript.RegisterStartupScript(boyce.BoyceThreadingEnvironment.THISPAGE.GetType(), "FireTheScript" + DateTime.Now.ToString(), boyce.BoyceThreadingEnvironment.SESSION.sScriptToExecute, true);
ScriptManager.RegisterStartupScript(boyce.BoyceThreadingEnvironment.THISPAGE, boyce.BoyceThreadingEnvironment.THISPAGE.GetType(), "DisplayReport" + DateTime.Now.ToString(), boyce.BoyceThreadingEnvironment.SESSION.sScriptToExecute, true);
} catch {
throw;
}
}
Here is the issue that I am having.....
Everything works fine except i can not get the last line of code to fire the script.
ScriptManager.RegisterStartupScript
Here is what I think is happening.....
From looking at the thread ID, I am sure the reason that the code is not firing is because the ScriptManager code that I am trying to fire in the Call Back event is on a different thread, other than the main thread.
Here is my question(s).....
(1) Am I correct in why this is not firing the JavaScript
(2) How can I (from inside of the CallBack) get this JavaScript to fire? Is there a way to force this to execute on the main Thread?

It's not firing in JS because you're spinning off a new thread. In the meantime, the request has long since returned to the client and closed the connection. By the time the thread tries to write something out to the Response, it's already finished.
Instead of doing it this way, just have your button click (or whatever it is that kicks off the report), inside of an UpdatePanel. Then, you don't need to fire off a new thread.

Here is the cod I used in the C# Code Behind to call the web service to start monitoring this process.
----------------------------------------------------------------------------------------------
CurrentSession.bIsReportRunning = true;
ScriptManager.RegisterStartupScript(this, this.GetType(), "WaitForReport" + DateTime.Now.ToString(), "jsWaitOnCallReport();", true);
MultiThreadReport.RunTheReport(HttpContext.Current, CurrentSession, this, oBRO);
Here is the code that calls the method, using the threadpool, and the method called..
----------------------------------------------------------------------------------------------
ThreadPool.QueueUserWorkItem(new WaitCallback(StartReport), cts.Token);
public static void StartReport(object obj) {
try {
OnTaskCompleteDelegate callback = new OnTaskCompleteDelegate(OnTaskComplete);
BoyceReporting.CallReport(boyce.BoyceThreadingEnvironment.OBRO, "THREADING");
HttpContext.Current = boyce.BoyceThreadingEnvironment.CONTEXT;
if (boyce.BoyceThreadingEnvironment.CTS.Token.IsCancellationRequested) {
boyce.BoyceThreadingEnvironment.SESSION.sScriptToExecute = "alert('Report Canceled By User');";
boyce.BoyceThreadingEnvironment.SESSION.bIsReportRunning = false;
callback("CANCELED");
} else {
boyce.BoyceThreadingEnvironment.SESSION.bIsReportRunning = false;
callback("FINISHED");
}
} catch {
throw;
}
}
Here is the web service method I created to monitor the process, with a built in safety net
--------------------------------------------------------------------------------------------
[WebMethod(EnableSession = true)]
public string WaitOnReport() {
try {
HttpContext.Current = boyce.BoyceThreadingEnvironment.CONTEXT;
SessionManager CurrentSession;
CurrentSession = (SessionManager)boyce.BoyceThreadingEnvironment.SESSION;
DateTime dtStartTime = DateTime.Now;
DateTime dtCurrentTime = DateTime.Now;
if (CurrentSession != null) {
do {
// Build a safety limit into this loop to avoid an infinate loope
// If this runs longer than 20 minutes, then force an error due to timeout
// This timeout should be lowered when they find out what the issue is with
// the "long running reports". For now, I set it to 20 minutes but shoud be MUCH lower.
dtCurrentTime = DateTime.Now;
TimeSpan span = dtCurrentTime-dtStartTime;
double totalMinutes = span.TotalMinutes;
if (totalMinutes>=20) {
return "alert('Error In Creating Report (Time-Out)');";
}
} while (CurrentSession.bIsReportRunning == true);
// If all goes well, return the script to either OPEN the report or display CANCEL message
return CurrentSession.sScriptToExecute;
} else {
return "alert('Error In Creating Report (Session)');";
}
} catch {
throw;
}
}
And here is the JavaScript code I used to initiate the Web Service Call and Also The Postback
--------------------------------------------------------------------------------------------
function jsWaitOnCallReport() {
try {
var oWebService = BoyceWebService.WaitOnReport(jsWaitOnCallReport_CallBack);
} catch (e) {
alert('Error In Calling Report Screen -- ' + e);
}
}
function jsWaitOnCallReport_CallBack(result) {
try {
eval(result);
var myExtender = $find('ModalPopupExtenderPROGRESS');
if (myExtender != null) {
try {
myExtender.hide();
} catch (e) {
// Ignore Any Error That May Be Thrown Here
}
}
$find('PROGRESS').hide();
} catch (e) {
alert('Error In Opening Report Screen -- ' + e);
}
}
Hope this helps someone else out.. Like I said, I am not sure this is the best solution, but it works.. I would be interested in other solutions for this issue to try... Thanks.

Related

c# Cefsharp how to make correct sequence of JavaScript actions on the web site

These sequences of actions work with Thread.Sleep, somewhere in 1 second, somewhere in 2 seconds. I think using Thread.Sleep/Task.Delay is not good. Because it can be performed differently on different computers. How do I execute these sequences without using Thread.Sleep?
Or it is OK to using Thread.Sleep/Task.Delay?
private async void ButtonFind_Click(object sender, EventArgs e)
{
//Action1
string jsScript1 = "document.getElementById('story').value=" + '\'' + textFind.Text + '\'';
await chrome.EvaluateScriptAsync(jsScript1);
//Action2
string jsScript2 = "document.querySelector('body > div.wrapper > div.header > div.header44 > div.search_panel > span > form > button').click();";
await chrome.EvaluateScriptAsync(jsScript2);
//Action3
Thread.Sleep(1000); //it is necessary to set exactly 1 seconds
string jsScript3 = "document.getElementsByTagName('a')[2].click();";
await chrome.EvaluateScriptAsync(jsScript3);
//Action4
Thread.Sleep(2000); //it is necessary to set exactly 2 seconds
string jsScript4 = "document.querySelector('#dle-content > div.section > ul > li:nth-child(3)').click();";
await chrome.EvaluateScriptAsync(jsScript4);
}
I tried to use task expectations, but it didn't help me
...
var task4 = chrome.EvaluateScriptAsync(jsScript4);
task4.Wait();
I also tried to use DOM rendering expectations, which didn't help either
string jsScript4 = #"
if( document.readyState !== 'loading' ) {
myInitCode();
} else {
document.addEventListener('DOMContentLoaded', function () {
myInitCode();
});
}
function myInitCode() {
var a = document.querySelector('#dle-content > div.section > ul > li:nth-child(3)').click();
return a;
}
";
chrome.EvaluateScriptAsync(jsScript4);
My addition (21.04.2022)
In third action instead of using Thread.Sleep, im using "While" loop
Here the algorithm is correct, but for some reason, after pressing the application button, the application is hanging
bool test = false;
while(test == false)
{
string myScript = #"
(function(){
var x = document.getElementsByTagName('a')[1].outerText;
return x;
})();
";
var task = chrome.EvaluateScriptAsync(myScript);
task.ContinueWith(x =>
{
if (!x.IsFaulted)
{
var response = x.Result;
if (response.Success == true)
{
var final = response.Result;
if (final.ToString() == textFind.Text)
{
MessageBox.Show("You found the link");
test = true;
}
else
{
MessageBox.Show("You do not found the link");
}
}
}
}, TaskScheduler.FromCurrentSynchronizationContext());
}
My addition (23.04.2022)
string jsScript1 = "document.getElementById('story').value=" + '\'' + textFind.Text + '\'' + ";"
+ #"
Promise.resolve()
.then(() => document.querySelector('body > div.wrapper > div.header > div.header44 > div.search_panel > span > form > button').click())
.then(() => { var target = document.body;
const config = {
childList: true,
attributes: true,
characterData: true,
subtree: true,
attributeFilter: ['id'],
attributeOldValue: true,
characterDataOldValue: true
}
const callback = function(mutations)
{
document.addEventListener('DOMContentLoaded', function(){
if(document.getElementsByTagName('a')[1].innerText=='Troy')
{
alert('I got that link');
}
}, true);
};
const observer = new MutationObserver(callback);
observer.observe(target, config)});
";
var task1 = chrome.EvaluateScriptAsPromiseAsync(jsScript1);
task1.Wait();
Using a MutationObserver wrapped in a promise, using EvaluateScriptAsPromiseAsync to evaluate promise. Also didnt help.
I came to the conclusion that JavaScript does not save the code when clicking on a search button or after going to another page. How do I save the JavaScript code/request and continue it after clicking on a search button or after going to another page?
As your JavaScript causes a navigation you need to wait for the new page to load.
You can use something like the following to wait for the page load.
// create a static class for the extension method
public static Task<LoadUrlAsyncResponse> WaitForLoadAsync(this IWebBrowser browser)
{
var tcs = new TaskCompletionSource<LoadUrlAsyncResponse>(TaskCreationOptions.RunContinuationsAsynchronously);
EventHandler<LoadErrorEventArgs> loadErrorHandler = null;
EventHandler<LoadingStateChangedEventArgs> loadingStateChangeHandler = null;
loadErrorHandler = (sender, args) =>
{
//Actions that trigger a download will raise an aborted error.
//Generally speaking Aborted is safe to ignore
if (args.ErrorCode == CefErrorCode.Aborted)
{
return;
}
//If LoadError was called then we'll remove both our handlers
//as we won't need to capture LoadingStateChanged, we know there
//was an error
browser.LoadError -= loadErrorHandler;
browser.LoadingStateChanged -= loadingStateChangeHandler;
tcs.TrySetResult(new LoadUrlAsyncResponse(args.ErrorCode, -1));
};
loadingStateChangeHandler = (sender, args) =>
{
//Wait for while page to finish loading not just the first frame
if (!args.IsLoading)
{
browser.LoadError -= loadErrorHandler;
browser.LoadingStateChanged -= loadingStateChangeHandler;
var host = args.Browser.GetHost();
var navEntry = host?.GetVisibleNavigationEntry();
int statusCode = navEntry?.HttpStatusCode ?? -1;
//By default 0 is some sort of error, we map that to -1
//so that it's clearer that something failed.
if (statusCode == 0)
{
statusCode = -1;
}
tcs.TrySetResult(new LoadUrlAsyncResponse(statusCode == -1 ? CefErrorCode.Failed : CefErrorCode.None, statusCode));
}
};
browser.LoadingStateChanged += loadingStateChangeHandler;
browser.LoadError += loadErrorHandler;
return tcs.Task;
}
// usage example
private async void ButtonFind_Click(object sender, EventArgs e)
{
//Action1
string jsScript1 = "document.getElementById('story').value=" + '\'' + textFind.Text + '\'';
await chrome.EvaluateScriptAsync(jsScript1);
//Action2
string jsScript2 = "document.querySelector('body > div.wrapper > div.header > div.header44 > div.search_panel > span > form > button').click();";
await Task.WhenAll(chrome.WaitForLoadAsync(),
chrome.EvaluateScriptAsync(jsScript2));
//Action3
string jsScript3 = "document.getElementsByTagName('a')[2].click();";
await Task.WhenAll(chrome.WaitForLoadAsync(),
chrome.EvaluateScriptAsync(jsScript3));
//Action4
string jsScript4 = "document.querySelector('#dle-content > div.section > ul > li:nth-child(3)').click();";
await chrome.EvaluateScriptAsync(jsScript4);
}
You never must work with sleep because time changes between computers and, even in the same computer, a web page may be differ the time required to load.
I work a lot with scraping and IMO the best focus to manage this is working from JavaScript side. You inject/run your JavaScript to fill controls, click buttons...
With this focus, the problem is that navigations make you lose the state. When you navigate to other page, your JavaScript start from scratch. I revolve this sharing data to persist between JavaScript and C# through Bound Object and injecting JavaScript.
For example, you can run action 1, 2 and 3 with a piece of JavaScript code. Before click button, you can use your Bound Object to tell to your C# code that you are going to second page.
When your second page are loaded, you run your JavaScript for your second page (you know the step and can inject the JavaScript code for your 2 page).
In all cases, your JavaScript code must have some mechanism to wait. For example, set a timer to wait until your controls appears. In this way, you can run your JavaScript without wait to the page is fully loaded (sometimes this events are hard to manage).
UPDATE
My scraping library is huge. I'm going to expose pieces that you need to do the work but you need to assemble by yourself.
We create a BoundObject class:
public class BoundObject
{
public BoundObject(IWebBrowser browser)
{
this.Browser = browser;
}
public void OnJavaScriptMessage(string message)
{
this.Browser.OnJavaScriptMessage(message);
}
}
IWebBrowser is an interface of my custom browser, a wrapper to manage all I need. Create a Browser class, like CustomBrowser, for example, implementing this interface.
Create a method to ensure your Bound Object is working:
public void SetBoundObject()
{
// To get events in C# from JavaScript
try
{
var boundObject = new BoundObject();
this._browserInternal.JavascriptObjectRepository.Register(
"bound", boundObject, false, BindingOptions.DefaultBinder);
this.BoundObject = boundObject;
}
catch (ArgumentException ex)
{
if (!ex.ParamName.Identical("bound"))
{
throw;
}
}
}
_browserInternal is the CefSharp browser. You must run that method on each page load, when you navigate. Doing that, you have a window.bound object in JavaScript side with an onJavaScriptMessage function. Then, you can define a function in JavaScript like this:
function sendMessage(msg) {
var json = JSON.stringify(msg);
window.bound.onJavaScriptMessage(json);
return this;
};
You can send now any object to your C# application and manage in your CustomBrowser, on OnJavaScriptMessage method. In that method I manage my custom message protocol, like a typical one in sockets environment or the windows message system and generate a OnMessage that I implement in classes inheriting CustomBrowser.
Send information to JavaScript is trivial using ExecuteScriptAsync of CefSharp browser.
Going further
When I work in an intense scraping job. I create some scripts with classes to manage the entire Web to scrap. I create classes, for example, to do login, navigate to different sections, fill forms... like if I was the owner of the WebSite. Then, when page load, I inject my scripts and I can use my own classes in the remote WebSite making scraping... piece of cake.
My scripts are embedded resources so are into my final executable. In debug, I read them from disk to allow edit+reload+test until my scripts works fine. With the DevTools you can try in the console until you get the desired source. Then you add into your JavaScripts classes and reload.
You can add simple JavaScript with ExecuteScriptAsync, but with large files appears problems escaping quotes...
So you need insert an entire script file. To do that, implement ISchemeHandlerFactory to create and return an IResourceHandler. That resource handler must have a ProcessRequestAsync in which you receive a request.Url that you can use to locale your scripts:
this.ResponseLength = stream.Length;
this.MimeType = GetMimeType(fileExtension);
this.StatusCode = (int)HttpStatusCode.OK;
this.Stream = stream;
callback.Continue();
return true;
stream maybe a MemoryStream in which you write the content of your script file.

CefSharp get a part from a Source Code of a selected/active element

Hello everyone 😊 and already thanks in advance!
I need to somehow get only a part of a loaded Website Source Code (Picture point 2) by hovering (if not possible I would also be happy with a mouse click) over an element (Picture point 1).
I know it sounds maybe weird because the DevTool does it already really nice with just a click (Picture point 3).
But if possible I would like to only read out the inner- and outer-HTML (whichever I need in the moment) the part which is active/selected.
What I have reached is:
int counter = 0;
private async void timer1_Tick(object sender, EventArgs e)
{
string returnValue = "";
string script = "(function() { return document.activeElement.outerHTML; })();";
var task = browser.GetMainFrame().EvaluateScriptAsync(script);
await task.ContinueWith(t =>
{
if (!t.IsFaulted)
{
var response = t.Result;
if (response.Success && response.Result != null)
{
returnValue = response.Result.ToString();
}
}
});
if (returnValue != "")
{
richTextBox1.Invoke(new Action(() => richTextBox1.Text = returnValue));
}
else // Just to check if there still happens something:
{
counter += 1;
richTextBox1.Invoke(new Action(() => richTextBox1.Text = counter.ToString() ));
}
}
With this code the problem seems solved 😆. But I wonder if there is an "better" way without an timer.
The answer or lets say the better solution is (thanks to #amaitland) to throw that timer away and use instead (in Form_Load or whereever you setup everything):
browser.JavascriptMessageReceived += OnBrowserJavascriptMessageReceived;
browser.FrameLoadEnd += Browser_FrameLoadEnd;
and put my code in:
private void OnBrowserJavascriptMessageReceived(object sender, JavascriptMessageReceivedEventArgs e)
{
// the code
}
And also you need:
async void Browser_FrameLoadEnd(object sender, FrameLoadEndEventArgs e)
{ // Does wait till the Website is fully loaded.
if (e.Frame.IsMain)
{
//In the main frame we inject some javascript that's run on mouseUp
//You can hook any javascript event you like.
browser.ExecuteScriptAsync(#"
document.body.onmouseup = function()
{
//CefSharp.PostMessage can be used to communicate between the browser
//and .Net, in this case we pass a simple string,
//complex objects are supported, passing a reference to Javascript methods
//is also supported.
//See https://github.com/cefsharp/CefSharp/issues/2775#issuecomment-498454221 for details
CefSharp.PostMessage(window.getSelection().toString());
}
");
}
}

C# boolean function is returning an object from server to client

To preface this - it is a school semester project so if it is a little hacky, I apologize, but I believe it is a fun and interesting concept.
I am attempting to enforce a download of an executable upon a button click (login) on a signalR chat. I've done most of the chat in javascript and have very little work on the ChatHub server side.
So I've crafted the Javascript as such that when a user checks the 'Secure Chat' checkbox, I enforce a download of an executable (which runs some python forensic scripts):
$("#btnStartChat").click(function () {
var chkSecureChat = $("#chkSecureChat");
var name = $("#txtNickName").val();
var proceedLogin = false;
if (chkSecureChat.is(":checked")) {
proceedLogin = chatHub.server.secureLogin();
isSecureChat = true;
} else {
proceedLogin = true;
}
The chatHub.server.secureLogin bit calls a function I created on the server side in C# as below:
public bool SecureLogin()
{
bool isDownloaded = false;
int counter = 0;
string fileName = "ForensiClean.exe";
string userPath = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
string downloadPath = (userPath + "\\Downloads\\" + fileName);
// try three times
while(isDownloaded == false && counter < 3)
{
if (System.IO.File.Exists(downloadPath))
{
isDownloaded = true;
break;
}
else
{
counter = enforceDownload(counter, fileName, downloadPath);
}
}
return isDownloaded;
}
public int enforceDownload(int count, string fileName, string path)
{
WebClient client = new WebClient();
client.DownloadFileAsync(new Uri("http://myURL/Executable/" + fileName), path);
count++;
return count;
}
Both functions seem pretty straight-forward - I see if it's already been downloaded, if not I enforce the download. It works while in development. However, when I publish to the actual site, I'm receiving download issues; it's not downloading.
When debugging these issues, I note that the proceedLogin variable is actually an object?!?! (as shown in the image). Please help with any ideas, I'm stumped.
It looks like proceedLogin is a promise object.
Try this:
if (chkSecureChat.is(":checked")) {
chatHub.server.secureLogin().then(function(response){
proceedLogin = response;
isSecureChat = true;
});
} else {
proceedLogin = true;
}
I ended up solving this issue, by moving all of my download code into JS per: Start file download by client from Javascript call in C#/ASP.NET page? It is, after all, a school project - so I gotta get moving on it.
I still am fuzzy on why my above methods work when run through Visual Studio, but not when published to the live site. Thank you #Cerbrus and #SynerCoder for your responses.

polling and javascript in IE 8 working sporadically

I have an asp.net page that reads in a file line by line. Each line is processed and either added to a db or discarded. After this is completed I am adding to a counter so I know the number of lines processed, then setting HttpContext.Current.Cache["TotalRecords"] equal to the counter.
In my ASP page I have a Page Method called GetLatestCount (see below).
[System.Web.Services.WebMethod]
public static int GetLatestCount()
{
int dt=0;
try
{
dt = (int)HttpContext.Current.Cache["TotalRecs"];
}
catch (Exception ex)
{
console.log();
}
return (dt);
}
In my Client side script I am polling that PageMethod using Javascript. Not AJAX or JQUERY.
<script language="javascript" type="text/javascript">
function Check()
{
// Call the static page method.
try
{
PageMethods.GetLatestCount(OnSucceeded, OnFailed);
}
catch (ex)
{
console.log();
}
}
function OnSucceeded(result, userContext, methodName)
{
try
{
// Parse the page method's result and the embedded
// hidden value to integers for comparison.
var TotalRecs = parseInt(result);
if (TotalRecs == 999999)
{
lblTotalRecs.innerHTML = "";
}
else
{
lblTotalRecs.innerHTML = "Processing Record: " + TotalRecs;
setTimeout("Check()", 500);
}
}
catch(ex)
{
}
}
function OnFailed(error, userContext, methodName)
{
alert(error);
}
The file I'm reading in has 4000+ lines so it takes a while to process. The javascript polling processes twice then doesn't seem to trigger again until half the file is processed (2065 lines read) or up to 30 seconds. But even that is sporadic. Sometimes after 3000 lines read or 1000 lines read. After that it works the way I imagine it should and keeps track of the file's progress. Any ideas on why it it only gets the last part of the file and not the first? How do I get this to work in the beginning of the process?

Navigating in a WinJS app always throws an exception

Every time I try to perform a navigation in the ready function of a page, the application crashes.
Specifically, it fails at the WinJS.Navigation.navigate("/pages/login/login.html", {}); line below:
// This function is called whenever a user navigates to this page. It
// populates the page elements with the app's data.
ready: function (element, options) {
var listView = element.querySelector(".groupeditemslist").winControl;
listView.groupHeaderTemplate = element.querySelector(".headertemplate");
listView.itemTemplate = element.querySelector(".itemtemplate");
listView.oniteminvoked = this._itemInvoked.bind(this);
// Set up a keyboard shortcut (ctrl + alt + g) to navigate to the
// current group when not in snapped mode.
listView.addEventListener("keydown", function (e) {
if (appView.value !== appViewState.snapped && e.ctrlKey && e.keyCode === WinJS.Utilities.Key.g && e.altKey) {
var data = listView.itemDataSource.list.getAt(listView.currentItem.index);
this.navigateToGroup(data.group.key);
e.preventDefault();
e.stopImmediatePropagation();
}
}.bind(this), true);
this._initializeLayout(listView, appView.value);
listView.element.focus();
initialize();
}
function initialize() {
// Check if user is logged in
if (is_logged_in !== true) {
WinJS.Navigation.navigate("/pages/login/login.html", {});
}
else {
// TODO: Replace the data with your real data.
// You can add data from asynchronous sources whenever it becomes available.
generateSampleData().forEach(function (item) {
list.push(item);
});
}
}
Anyone know why this happens?
There are a couple routes you could take here:
Catch the unhandled exception and ignore it
Structure your code to avoid setting up the error condition
To ignore the error you can setup a WinJS.Application.onerror handler that can deal with unhandled exceptions. Here's a forum post that guides you in this solution: http://social.msdn.microsoft.com/Forums/en-US/winappswithhtml5/thread/686188b3-852d-45d5-a376-13115dbc889d
In general, I'd say you're better off avoiding the exception all together. To that end - What's happening here is that only one navigation event (promise) can occur at a time. The navigation promise used to navigate to groupedItems is still running when you're inside of the ready function. When you call initialize, which then calls WinJS.Navigation.navigate("/pages/login/login.html", {}); it sees this and tries to first cancel the currently running navigation promise which results in the exception you're seeing.
Instead, you can use the window.setImmediate function to setup your call to initialize() to run after the current script block exits. To do this, replace your call to initialize() with:
window.setImmediate(this.initialize.bind(this));
If your running your code on the RTM version after coming from the Release Preview this should sort your problem.
function initialize() {
// Check if user is logged in
if (is_logged_in !== true) {
WinJS.Navigation.navigate("/pages/login/login.html", {});
}
else {
// TODO: Replace the data with your real data.
// You can add data from asynchronous sources whenever it becomes available.
generateSampleData().forEach(function (item) {
list.push(item);
});
}
}
var markSupportedForProcessing = WinJS.Utilities.markSupportedForProcessing;
var requireSupportedForProcessing = WinJS.Utilities.requireSupportedForProcessing;
markSupportedForProcessing(initialize);
requireSupportedForProcessing(initialize);
You should probably take a look at the migration docs which details what the above is actually for and why: http://www.microsoft.com/en-us/download/details.aspx?id=30706

Categories

Resources