public void PortalLogin()
{
string portalUrl = "URL";
string portalEmail = "email";
string portalPassword = "password";
// Run when page finishes navigating
webBrowser2.DocumentCompleted += (s, e) =>
{
HtmlElement head = webBrowser2.Document.GetElementsByTagName("head")[0];
HtmlElement testScript = webBrowser2.Document.CreateElement("script");
IHTMLScriptElement element = (IHTMLScriptElement)testScript.DomElement;
element.text = "function PortalLogin() { document.getElementById('username').value = '" + portalEmail + "'; document.getElementById('password').value = '" + portalPassword + "'; document.getElementById('credentials').submit(); }";
head.AppendChild(testScript);
webBrowser2.Document.InvokeScript("PortalLogin");
};
// Navigate to the portal
webBrowser2.Navigate(portalUrl);
while (this.webBrowser2.ReadyState != WebBrowserReadyState.Complete)
{
Application.DoEvents();
Thread.Sleep(100);
}
}
I have the code segment above that is supposed to Navigate to a specific URL and then upon Navigate's completion, execute invoke a script to login to the webpage there. Now, because the entire PortalLogin() function is inside of a while loop, I have to include the:
while (this.webBrowser2.ReadyState != WebBrowserReadyState.Complete)
{
Application.DoEvents();
Thread.Sleep(100);
}
segment so that the while loop doesn't just interrupt the Navigate function a ton. However, the code isn't quite working, the flow seems to be off when I step through it with breakpoints. I think part of the problem is I don't quite understand how the while loop testing ReadState != Complete works. Could someone enlighten me?
Better use WebClient with cookies or HttpWebRequest and HttpWebResponse.
Related
I have a database of URLs and the screen will load 9 URLs at once like a table and load another 9 URLs after 5 minutes. I have some script to run after each ULR finished loading using the FrameLoadEnd Event Handler. I keep getting this error when the 19th URL is loading.
unable to execute javascript at this time, scripts can only be executed within a v8context. use the iwebbrowser.canexecutejavascriptinmainframe property to guard against this exception
If there is a mistake, this error should pop up when the 1st URL is loaded but it always pops up when the 19th URL is loaded which is the third round the screen display 9 new URLs.
Here is the Code
wb.FrameLoadEnd += OnBrowserFrameLoadEnd;
private async void OnBrowserFrameLoadEnd(object sender, FrameLoadEndEventArgs e)
{
ChromiumWebBrowser wb = (ChromiumWebBrowser)sender;
await wb.EvaluateScriptAsync("document.body.style.overflow='hidden';");
int clientHeight = 0;
int clientWidth = 0;
int innerHeight = 0;
int innerWidth = 0;
string clientRecHeightScript = #"function myFunction() {" +
"var rect = document.body.getBoundingClientRect();" +
"ch = rect.height;" +
"var rect = document.body.getBoundingClientRect();" +
"cw = rect.width;" +
"var ih = window.innerHeight;" +
"var iw = window.innerWidth;" +
"const webLength = [ch, cw, ih, iw];" +
"return webLength;" +
"}" +
"myFunction();";
await wb.EvaluateScriptAsync(clientRecHeightScript).ContinueWith(x => //Error occurs here
{
var response = x.Result;
if (response.Result != null)
{
var clientRec = response.Result;
string[] arr = ((System.Collections.IEnumerable)clientRec).Cast<object>()
.Select(y => y.ToString())
.ToArray();
Int32.TryParse(arr[0], out clientHeight);
Int32.TryParse(arr[1], out clientWidth);
Int32.TryParse(arr[2], out innerHeight);
Int32.TryParse(arr[3], out innerWidth);
}
});
}
Is there any error I might have done to cause this error?
Does the webpage have JavaScript on it? If not then it won't have a V8Context.
It's also possible the V8Context hasn't finished loading for the main frame. FrameLoadEnd is called once per frame. Sub frames may finish loading first.
The website failed to load, you can check the http://cefsharp.github.io/api/91.1.x/html/P_CefSharp_FrameLoadEndEventArgs_HttpStatusCode.htm
A navigation has occurred and the V8Context has been freed . If Load is called or the html document navigates internally you the frame for which FrameLoadEnd was called may no longer have a valid V8Context.
You can evaluate JavaScript directly against the frame to avoid the check. The FrameLoadEndEventArgs.Frame property can be used to access the frame. You can then directly call IFrame.EvaluateScriptAsync
I'm working on knockout based site using selenium web driver + c# to automate. My test methods fail because of elements not found / not able to click as the site is slow / or the binding/ rendering of html is slow after the ajax calls are finished.
Below is sample code I used to know the ajax calls have finished and I can proceed to search elements.
public static void waitForAjax(IWebDriver driver, String action)
{
try
{
TimeSpan tp = TimeSpan.FromSeconds(1000);
driver.Manage().Timeouts().SetScriptTimeout(tp);
((IJavaScriptExecutor)driver).ExecuteAsyncScript(
"var callback = arguments[arguments.length - 1];" +
"var xhr = new XMLHttpRequest();" +
"xhr.open('GET', '/" + action + "', true);" +
"xhr.onreadystatechange = function() {" +
" if (xhr.readyState == 4 && xhr.status == 200) {" +
" callback(xhr.responseText);" +
" }" +
"};" +
"xhr.send();");
}
catch { }
}
I am calling the above method before going to find the elements.
Test Method
try
{
IWebDriver _Driver;
IWebElement ele;
FirefoxDriverService _Service = FirefoxDriverService.CreateDefaultService(#"D:\CodePlex_C#\SeleniumTestWithHtml\SeleniumTestWithHtml\Drivers");
_Driver = new FirefoxDriver(_Service);
_Driver.Navigate().GoToUrl("HomepageURl");
System.Threading.Thread.Sleep(2000);
waitForAjax(_Driver,"Call1");
waitForAjax(_Driver,"Call2");
System.Threading.Thread.Sleep(2000);
ele = _Driver.FindElement(By.LinkText("DASHBOARD"));
ele.Click();
//System.Threading.Thread.Sleep(2000);
waitForAjax(_Driver,"Call1");
waitForAjax(_Driver,"Call2");
waitForAjax(_Driver,"Call3");
waitForAjax(_Driver,"Call4");
System.Threading.Thread.Sleep(2500);
ele = _Driver.FindElement(By.Id("QuickSearchCnt"));
ele.Click();
}
But my Code Fails. I suspect the code to find the calls have finished to execute is not working properly.
I need help in knowing is my approach right? And need help in fixing the issue.
Good Day Every one here is my code
if (type.Contains("Loan Date"))
{
prenda.LoanMonth = year.ToString() + "/" + month.ToString();
string a = servs.CheckLM(prenda);
if (Convert.ToInt32 (a) != 0)
{
Page.ClientScript.RegisterStartupScript(Page.GetType(), "key", "myFunction();", true);
//create a popup if yes process if no exit
//if yes
prenda.LoanMonth = year.ToString() + "/" + month.ToString();
servs.DeletePrendaLM(prenda);
foreach (DataRow row1 in table.Rows)
{
prenda.Bcode = row1["Bcode"].ToString();
prenda.Jprincipal = Convert.ToDecimal(row1["JPrincipal"].ToString());
prenda.Aprincipal = Convert.ToDecimal(row1["APrincipal"].ToString());
prenda.Cprincipal = Convert.ToDecimal(row1["CPrincipal"].ToString());
prenda.LoanMonth = year.ToString() + "/" + month.ToString();
user.UserID = Session["UserID"].ToString();
servs.UploadPrendaLM(prenda, user);
}
}
the porblem is that the Page.ClientScript.RegisterStartupScript(Page.GetType(), "key", "myFunction();", true); doesnt execute as soon as the process pass over it, it executes myFunction() after finishing the button click proceses, i cant create a if clause below it because it finishes first all of the process before i can use the myFunction() i need that process first before continuing the proceses below //
so can you help me find a work around?
Few things that might help
The script block added by the RegisterStartupScript method executes when the page finishes loading but before the page's OnLoad event is raised. >> Where are you adding script in the page (Which event?) try it in OnInit or init complete events.
You can check whether script added or not through IsStartupScriptRegistered method (Page.ClientScript namespace)
I have a function which have a long execution time.
public void updateCampaign()
{
context.Session[processId] = "0|Fetching Lead360 Campaign";
Lead360 objLead360 = new Lead360();
string campaignXML = objLead360.getCampaigns();
string todayDate = DateTime.Now.ToString("dd-MMMM-yyyy");
context.Session[processId] = "1|Creating File for Lead360 Campaign on " + todayDate;
string fileName = HttpContext.Current.Server.MapPath("campaigns") + todayDate + ".xml";
objLead360.createFile(fileName, campaignXML);
context.Session[processId] = "2|Reading The latest Lead360 Campaign";
string file = File.ReadAllText(fileName);
context.Session[processId] = "3|Updating Lead360 Campaign";
string updateStatus = objLead360.updateCampaign(fileName);
string[] statusArr = updateStatus.Split('|');
context.Session[processId] = "99|" + statusArr[0] + " New Inserted , " + statusArr[1] + " Updated , With " + statusArr[2] + " Error , ";
}
So to track the Progress of the function I wrote a another function
public void getProgress()
{
if (context.Session[processId] == null)
{
string json = "{\"error\":true}";
Response.Write(json);
Response.End();
}else{
string[] status = context.Session[processId].ToString().Split('|');
if (status[0] == "99") context.Session.Remove(processId);
string json = "{\"error\":false,\"statuscode\":" + status[0] + ",\"statusmsz\":\"" + status[1] + "\" }";
Response.Write(json);
Response.End();
}
}
To call this by jQuery post request is used
reqUrl = "AjaxPages/lead360Campaign.aspx?processid=" + progressID + "&action=updatecampaign";
$.post(reqUrl);
setTimeout(getProgress, 500);
get getProgress is :
function getProgress() {
reqUrl = "AjaxPages/lead360Campaign.aspx?processid=" + progressID + "&action=getProgress";
$.post(reqUrl, function (response) {
var progress = jQuery.parseJSON(response);
console.log(progress)
if (progress.error) {
$("#fetchedCampaign .waitingMsz").html("Some error occured. Please try again later.");
$("#fetchedCampaign .waitingMsz").css({ "background": "url(common/images/ajax_error.jpg) no-repeat center 6px" });
return;
}
if (progress.statuscode == 99) {
$("#fetchedCampaign .waitingMsz").html("Update Status :"+ progress.statusmsz );
$("#fetchedCampaign .waitingMsz").css({ "background": "url(common/images/ajax_loded.jpg) no-repeat center 6px" });
return;
}
$("#fetchedCampaign .waitingMsz").html("Please Wait... " + progress.statusmsz);
setTimeout(getProgress, 500);
});
}
But the problem is that I can't see the intermediate message. Only the last message is been displayed after a long lime of ajax loading message
Also on the browser console I just see that after a long time first requested is completed and after that the second request is completed. but there should be for getProgress ?
I have checked jquery.doc and it says that $post is an asynchronous request.
Can anyone please explain what is wrong with the code or logic?
You are in a situation discussed here:
ASP.net session request queuing
While a request for a given user's session is processed, other requests for the same session are waiting. You need to run your long function in a background thread and let the request that initiates it finish. However, the background thread will not have access to session, and you will need a different mechanism to communicate its progress.
From the information you've provided, I would suspect that it's not your javascript code that's being synchronous, but rather the server-side code. You can test this by using Firebug or Chrome's dev tools to look at the start and end times of the two AJAX requests. If I'm right, you'll see that the second request begins after half a second, but doesn't complete until after the first one.
If that's the case, possible causes are:
Running in a dev environment in Visual Studio, especially in debug mode, seems to reduce the amount of asynchronicity. The dev environment seems to like to process one request at a time.
See Igor's answer about session request queueing.
You may have code that explicitly locks resources and causes the second request to block until the long-running request is done.
One other possible culprit is the fact that most browsers only allow a limited number of concurrent requests to a particular domain. If you have a few requests pending at any given moment, the browser may just be queuing up the remaining requests until they return.
using c# .net4.0
I am aware the asp.net button with in the gridview of type link does a post to the same page when clicked, i need make several manipualtion on server side before actually redirecting user to an external site hence i can't use Hyperlinkfield. What i need now is the external site htm page should open up in sperate window. I tried the following which works but source site's fonts get bigger???
heres what i tried
Response.Write("<script>");
Response.Write("window.open('http://www.google.co.uk','_blank')");
Response.Write("</script>");
Response.End();
may be i need a refresh source site??
Thanks
# Curt Here is the code for Hyperlink i tired
on page load added new button on gridview
HyperLinkField LinksBoundField = new HyperLinkField();
string[] dataNavigateUrlFields = {"link"};
LinksBoundField.DataTextField = "link";
LinksBoundField.DataNavigateUrlFields = dataNavigateUrlFields;
LinksBoundField.DataNavigateUrlFormatString = "http://" + Helper.IP + "/" + Helper.SiteName + "/" + Helper.ThirdPartyAccess + "?dispage={0}&token=" + Session["Token"];
LinksBoundField.HeaderText = "Link";
LinksBoundField.Target = "_blank";
GridViewLinkedService.Columns.Add(LinksBoundField);
GridViewLinkedService.RowDataBound += new GridViewRowEventHandler(grdView_RowDataBound);
to append external values (refe and appid) to navigate url
protected void grdView_RowDataBound(object sender, GridViewRowEventArgs e)
{
string strvalue = "";
string strvalue1 = "";
string strRef = "";
string strAppId = "";
foreach (GridViewRow row in GridViewLinkedService.Rows)
{
if (row.RowType == DataControlRowType.DataRow)
{
//reference and appid
strAppId = row.Cells[0].Text;
strRef = row.Cells[1].Text;
HyperLink grdviewLink = (HyperLink)row.Cells[5].Controls[0];
strvalue = grdviewLink.NavigateUrl;
strvalue1 = Regex.Replace(strvalue, "(.*dispage\\=).*/(services.*)", "$1$2");
grdviewLink.NavigateUrl = "~/My Service/FillerPage.aspx?nurl=" + strvalue1 + "&AppID=" + strAppId.ToString() + "&Ref=" + strRef.ToString();
}
}
}
public partial class FillerPage : System.Web.UI.Page
{
private string refno = null;
private string appid = null;
private string nurl = null;
private string strvalue1 = "";
private string newtoken = "";
protected void Page_Load(object sender, EventArgs e)
{
if (Request.QueryString.GetValues("AppID") != null)
{
appid = Request.QueryString.GetValues("AppID")[0].ToString();
}
if (Request.QueryString.GetValues("Ref") != null)
{
refno = Request.QueryString.GetValues("Ref")[0].ToString();
}
if (Request.QueryString.GetValues("nurl") != null)
{
nurl = Request.QueryString.GetValues("nurl")[0].ToString();
}
while receiving the long url it gets messed up(same query multiple times and all jumbled up)?????
is there a better way to pass parameters ???
you need to register script not response.write
so the code for you is :
ClientScript.RegisterStartupScript(this.GetType(), Guid.NewGuid().ToString(), "<script language=JavaScript>window.open('http://www.google.co.uk','_blank')</script>");
Read more : ClientScriptManager.RegisterStartupScript.
In a situation where I need to run server side code, before then opening a new page, I sometimes create a Generic Handler File and link to this with a HyperLink, passing variables as Query Strings. Therefore something like:
/MyGenericFile.ashx?id=123
In this file, I would have some scripting that needs to be carried out, followed by a Response.Redirect().
As long as the HyperLink is set to target="_blank", the user won't even know they've been to a generic file, which is then redirected. It will appear as they've opened a new link.
Therefore the process would be:
User clicks link to .ashx file
Link opens in new window
Necessary scripting is ran
Response.Redirect() is ran
User is taken to web page (www.google.com in your example)
I believe this same process is used by advert management systems to help track clicks.
You can register a script to run on page load with ClientScriptManager.RegisterStartupScript.