How to print a huge number of images in Asp.Net? - c#

I have PrintTest.aspx page load images paths from database and render it in div to print these images maybe up to 20000 image .
for (int i = 0; i < Files.Count; i++)
{
HtmlImage image=new HtmlImage();
image.ID="ImageAN"+i.ToString();
image.Src=Files[i].ToString();
image.Alt="PrintImage";
image.Attributes.Add("class","PrintImage");
div_Print.Controls.Add(image);
}
Then call JavaScript function to print the content of div_Print
this.ClientScript.RegisterStartupScript(this.GetType(), "ClientScript", " PrintContent('div_Print')", true);
java-script function >
<script type="text/javascript">
function PrintContent(divName) {
var DocumentContainer = document.getElementById(divName);
var WindowObject = window.open();
WindowObject.document.writeln(DocumentContainer.innerHTML);
WindowObject.document.close();
WindowObject.focus();
WindowObject.print();
WindowObject.close();
}
</script>
But this scenario causes my browser keep crashing and closed.
I want any scenario to avoid this or print images without render it inside HTML

You don't . This is why people invented pagination and search.
And there are several reasons why:
Memory is a limited resource, especially on mobile devices (if you support them)
TMI, people cannot visually understand 20k images put on a single page, without spending hours staring at it
Something like this
public ControlsTypeHere PrintImages(int take, int skip)
{
int filesPrinted;
for (int i = skip; i < Files.Count; i++)
{
if(filesPrinted >= take)
break;
HtmlImage image=new HtmlImage();
image.ID="ImageAN"+i.ToString();
image.Src=Files[i].ToString();
image.Alt="PrintImage";
image.Attributes.Add("class","PrintImage");
div_Print.Controls.Add(image);
filesPrinted++;
}
return div_Print.Controls;
}

Related

Selenium Error: StaleElementReferenceException in C#

I'm working on an application that downloads images from the internet in Selenium. However, I get the same error in the code seen in the picture and I cannot continue the process. This code, you can see the error in the image below.
IWebDriver driver;
int PictureID = 0;
private void button1_Click(object sender, EventArgs e)
{
var ChromeService = ChromeDriverService.CreateDefaultService();
driver = new ChromeDriver(ChromeService);
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(30);
driver.Navigate().GoToUrl("https://oblivious212.artstation.com/");
var Projects = driver.FindElements(By.ClassName("album-grid-item"));
for(int i = 0; i < Projects.Count(); i++)
{
if (Projects.ElementAt(i) == null)
{
continue;
}
Projects[i].Click();
var Images = driver.FindElements(By.TagName("img"));
for(int x = 0; x < Images.Count(); x++)
{
PictureID++;
WebClient Downloader = new WebClient();
var ImageUrl = Images[x].GetAttribute("src");
var ImageName = Images[x].GetAttribute("alt");
Downloader.DownloadFile(ImageUrl, "C:\\Users\\DeLL\\Pictures\\Images\\" + ImageName + PictureID + ".jpg");
}
driver.Navigate().Back();
}
Screenshot of exception when running in debug mode:
How do I solve this?
As soon as you navigate to a new page, which I guess is what your Projects[i].Click(); call does, any IWebElement objects you saved from an earlier page (oblivious212.artstation.com/) become "stale" and you can no longer use them. You must design your code around this fact; there are several ways you might do this.
Basically, while you're still on page oblivious212.artstation.com/, you need to save off any data you need from the IWebElement objects returned by your driver.FindElements(By.ClassName("album-grid-item")) call, into a local object, rather than saving the IWebElement objects themselves. Then, replace your Projects[i].Click(); call with code which uses your saved local data, rather than using the IWebElement objects themselves.

Get page by name or by number interop Word

I'm trying to access a page in Word by it's name or number. I thought I was going in the right direction but there doesn't seem to be a page.name or page.number property. The issue is in my if statement where I'm trying to say if there is a page named Page 4 Content then select it.
var wordApplication = (word.Application)System.Runtime.InteropServices.Marshal.GetActiveObject("Word.Application");
string path = CommonMethods.getFile(fileName);
myDoc = wordApplication.Documents.Open(path);
wordApplication.Visible = true;
wordApplication.WindowState = word.WdWindowState.wdWindowStateMaximize;
word.Pages pages = myDoc.ActiveWindow.ActivePane.Pages;
foreach (word.Page p in pages )
{
if (p.)
{
}
}
As you already mentioned there is no number or name property on the page object.
In order to get the page number you have to access the Information property of a Range or Selection object on that page.
In addition to that I recommend to study the article Selecting or referring to a page in the Word object model by Shauna Kelly. In her article she explains in detail why it is often not a good idea to rely on the page object for automated document processing. The reason for that is that Word uses a flow layout instead of a fixed layout. In order to determine the current page rendering Word has to talk to the current printer driver. This means that your page breaks may vary depending on your printer.
I ended up doing the following and it works like a charm.
object What = Microsoft.Office.Interop.Word.WdGoToItem.wdGoToPage;
object Which = Microsoft.Office.Interop.Word.WdGoToDirection.wdGoToAbsolute;
object Miss = System.Reflection.Missing.Value;
word.Pages pages = doc.ActiveWindow.ActivePane.Pages;
for (int i = 0; i < pages.Count; i++)
{
if (i == pageNumber)
{
doc.Application.Selection.GoTo(ref What, ref Which, pageNumber, ref Miss);
}
}
}

On a web performance test, can I specify multiple expected response pages?

When dealing with a coded web performance test (in C#), is it possible to tell the web test to expect multiple valid response pages? We have certain criteria that happen on login, and the user may be taken to a few different pages depending on some flags, so expecting a single response URL isn't really possible.
Can't you simply use the extract rules to extract something from each page you could get redirected to?
Here you can find some guidance of how to set things up:
http://www.dotnetfunda.com/articles/show/901/web-performance-test-using-visual-studio-part-i
or if this doesn't work for you, you could also code your custom validation rule:
http://msdn.microsoft.com/en-us/library/ms182556.aspx
On a Coded UI test of a web page that could return either of two quite different pages I wrote the following code. It worked fine for that test, there are several possible tidy ups that I would investigate if I needed similar again. So please consider this as a starting point.
The basic idea is to see check the current web page for text identifying which of the expected pages is currently shown. If found then deal with that page. If not found then pause for a short time to allow the page to load, then look again. Added in a time out in case an expected page never appears.
public void LookForResultPages()
{
Int32 maxMilliSecondsToWait = 3 * 60 * 1000;
bool processedPage = false;
do
{
if ( CountProperties("InnerText", "Some text on most common page") > 0 )
{
... process that page;
processedPage = true;
}
else if ( CountProperties("InnerText", "Some text on another page") > 0 )
{
... process that page;
processedPage = true;
}
else
{
const Int32 pauseTime = 500;
Playback.Wait(pauseTime); // In milliseconds
maxMilliSecondsToWait -= pauseTime;
}
} while ( maxMilliSecondsToWait > 0 && !processedPage );
if ( !processedPage )
{
... handle timeout;
}
}
public int CountProperties(string propertyName, string propertyValue)
{
HtmlControl html = new HtmlControl(this.myBrowser);
UITestControlCollection htmlcol = new UITestControlCollection();
html.SearchProperties.Add(propertyName, propertyValue, PropertyExpressionOperator.Contains);
htmlcol = html.FindMatchingControls();
return htmlcol.Count;
}

wkhtmltopdf Header, Image & Pagenumbers

I want to add a Header to my PDF with this:
--header-center TEST
and it works fine, but if i want to insert Whitespace:
--header-center TEST test
it wont be displayed. Do I have to write something instead of " "?
Another question is how to insert pagenumbers into the footer. I found this code-snippet, but I'm new in this issue and have no idea how to implement it:
var pdfInfo = {};
var x = document.location.search.substring(1).split('&');
for (var i in x) { var z = x[i].split('=',2); pdfInfo[z[0]] = unescape(z[1]); }
function getPdfInfo() {
var page = pdfInfo.page || 1;
var pageCount = pdfInfo.topage || 1;
document.getElementById('pdfkit_page_current').textContent = page;
document.getElementById('pdfkit_page_count').textContent = pageCount;
}
And my last question is how to insert Images into the footer with --header-html ~\image.html.
I inserted a link referencing a simple html with a picture but it wont be displayed.
I know... many questions. This issue is very tricky for me.
Thanks in advance!
LG FG
As in my comment, the whitespace in the text header should work if you surround it in quotes, ex --header-center "TEST test"
Okay, so I played around and found how to get the page numbers and image to work. Your header.html should look something like (notice how the image URL is the absolute path) :
<html>
<head>
<script type="text/javascript">
var pdfInfo = {};
var x = document.location.search.substring(1).split('&');
for (var i in x) { var z = x[i].split('=',2); pdfInfo[z[0]] = unescape(z[1]); }
function getPdfInfo() {
var page = pdfInfo.page || 1;
var pageCount = pdfInfo.topage || 1;
document.getElementById('pdfkit_page_current').textContent = page;
document.getElementById('pdfkit_page_count').textContent = pageCount;
}
</script>
</head>
<body onload="getPdfInfo()">
<img src="/var/sites/mysite/htdocs/images/logo.jpg" />
<br />Page <span id="pdfkit_page_current"></span> Of <span id="pdfkit_page_count"></span>
</body>
</html>
Then generate the with something like wkhtmltopdf --margin-top 40mm --header-html /var/sites/mysite/pdf/header.html content.html output.pdf
You'll have to play with --margin-top to get the right spacing. The same procedure should work for footers as well.
My source for this was http://metaskills.net/2011/03/20/pdfkit-overview-and-advanced-usage/ (PDFkit is a wrapper for wkhtmltopdf)

Looping through values from c# array using javascript

Okay, I've created an array in c# and want to access the values in a javascript for loop. Here's my global c# variables:
protected int count;
protected string[] arr = new string[20];
From there I add string values to the array in, let's say, the Page_Load() event.
And here's my ideal javascript code:
var count = <%= count %>;
for (var i = 0; i < count; i++)
{
document.write(<%= arr[i] %>);
}
Now if I were to just use arr[0] that would pop up with the correct information for arr[0], so I know I've got that part right, but is there a way to use that javascript variable "i" inside the <%= %> tag?
The ASP.NET parts of the code execute on the server. JavaScript is executed in the browser. The server just sees the JavaScript as text, it is meaningless and non-functional. Only when the browser receives the page and interprets the JS is it executed.
Remember, the server and the client PC are two different systems connected by a network. If you want to process data from system A on system B, you need to send the data to B.
If you want to send the data in the array to the browser so it can use it in some JavaScript, you need to serialize the array.
Something like this:
var myArray = <% = new JavaScriptSerializer().Serialize(serverSideArray) %>;
for(var i = 0; i < myArray.length; i++) {
document.write(myArray[i]);
}
Hope it is useful to you...
It was run fine in my test
<script language ="javascript">
var count = <%= count %>;
alert(count);
<%
for(int i=0;i<count;i++){
%>
document.write(<%= arr[i] %>);
<%}%>
</script>
Sadly, I don't think so; because the Javascript is evaluated at run-time in the browser, but the server block is evaluated at compile time on the server.
You can probably just expand the scope of your server block and just loop through arr in C#
I am going to get flamed for this, but here goes:
Server-side:
protected void Page_Load(object sender, EventArgs e)
{
string[] arr = new string[] { "1", "2", "3" };
StringArr = string.Join(",", arr.Select(a => string.Format("\"{0}\"", a)).ToArray());
}
protected string StringArr;
Client-side:
<script language="javascript" type="text/javascript">
var arr = [<%=StringArr %>];
alert(arr.length);
</script>
Let the ridicule begin.

Categories

Resources