Export web page to pdf - asp.net

I am having a web page in which there is a canvas js chart. When I generated a pdf, the only canvas js chart do not displayed in the pdf.
How can I solve this problem?

I previously had this issue, we ended up using: http://www.highcharts.com/ then exported to png -> http://www.highcharts.com/docs/export-module/export-module-overview.
After the svg-> png conversion we converted to PDF using standard libraries.

To export JS Chart into PDF, First you have to convert chart data into canvas image byte stream and then to PDF.
The following code will help you to convert JS Chart into PDF
In Aspx Page
<asp:HiddenField ID="hfImageData" runat="server" />
<div id="dvTable">
<div class="row">
<div class="col-md-6 col-sm-6 col-xs-12">
<div class="x_panel">
<div class="x_title"> Your chart data comes here <h2> SLA </h2>
</div>
<div class="x_content">
<canvas id="canvas000"></canvas>
</div>
</div>
</div>
</div>
</div>
<asp:Button ID="btnExport" runat="server" Text="Export to PDF" CssClass="btn btn-primary" onclick="btnExport_Click" OnClientClick="return ConvertToImage(this)" />
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script type="text/javascript" src="http://cdn.rawgit.com/niklasvh/html2canvas/master/dist/html2canvas.min.js"></script>
<script type="text/javascript">
function ConvertToImage(btnExport) {
html2canvas($("#dvTable")[0]).then(function (canvas) {
var base64 = canvas.toDataURL();
$("[id*=hfImageData]").val(base64);
__doPostBack(btnExport.name, "");
});
return false;
}
</script>
In Aspx.cs Page
protected void btnExport_Click(object sender, EventArgs e)
{
string base64 = Request.Form[hfImageData.UniqueID].Split(',')[1];
byte[] bytes = Convert.FromBase64String(base64);
string fileName = "Chart.pdf";
iTextSharp.text.Image image = iTextSharp.text.Image.GetInstance(bytes);
using (MemoryStream memoryStream = new MemoryStream())
{
var pgSize = new iTextSharp.text.Rectangle(1600, 1000);
Document document = new Document(pgSize, 88f, 88f, 10f, 10f);
PdfWriter writer = PdfWriter.GetInstance(document, memoryStream);
document.Open();
document.Add(image);
document.Close();
bytes = memoryStream.ToArray();
memoryStream.Close();
}
Response.Clear();
Response.Buffer = true;
Response.Charset = "";
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.ContentType = "application/pdf";
Response.AppendHeader("Content-Disposition", "attachment; filename=" + fileName);
Response.BinaryWrite(bytes);
Response.Flush();
Response.End();
}
whatever data present under div id "dvTable" will be converted to PDF when we click on Export

PhantomJS sounds like an option for you, take a look at the NReco wrapper for using it with .Net https://www.nrecosite.com/phantomjs_wrapper_net.aspx

Related

Displaying multiple entries on a database into an aspx page

I am trying to display multiple lines from a database into an aspx page. My aspx page name is news.aspx and my table is called news.
I have configured my aspx with the code to display what I want my page to look like. I have attached an image to show I would like it to look like when the page is loaded. The aspx page uses ItemTemplate & asp:Repeater to display the multiple lines.
My aspx page is configured as follows:
<div class="row">
<div class="col-md-6 col-md-offset-3">
<div class="col-lg-12">
<div class="form-group alert alert-info">
<asp:label runat="server" ID="lblNewsEdits">Latest Sports & Social News Items</asp:label>
</div>
</div>
</div>
</div>
<asp:Repeater ID="Repeater1" runat="server">
<ItemTemplate>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<div class="col-lg-12">
<p>
Title:
<asp:Literal ID="litTitle" runat="server"></asp:Literal>
(<asp:Literal ID="litDatePosted" runat="server"></asp:Literal>)
</p>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<div class="col-lg-12">
<p>
Title:
<asp:Literal ID="litNewsContent" runat="server"></asp:Literal>
</p>
</div>
</div>
</div>
</ItemTemplate>
</asp:Repeater>
My aspx.cs page is configured to pull the information from the news table, I want three column of data to be display in the aspx page (Title, DatePosted and NewsContent).
For the three lines below, I am getting error: "The name "..." does not exist in the current context.
litTitle.text = reader ["Title"].ToString();
litDatePosted.Text = reader["Date Posted"].ToString();
litNewsContent.Text = reader["News Content"].ToString();
The aspx.cx page is configured as follows:
protected void Page_Load(object sender, EventArgs e)
{
SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["AppConnectionString"].ConnectionString);
string getNewsQuery = "SELECT Id, Title, DataPosted, Newsontent FROM News WHERE Id = #id";
//get email based on id
SqlCommand getNewsCommand = new SqlCommand(getNewsQuery, connection);
object id = null;
getNewsCommand.Parameters.AddWithValue("#id", id);
connection.Open();
SqlDataReader reader = getNewsCommand.ExecuteReader();
while (reader.Read())
{
litTitle.txt = reader ["Title"].ToString();
litDatePosted.Text = reader["Date Posted"].ToString();
litNewsContent.Text = reader["News Content"].ToString();
}
reader.Close();
connection.Close();
}
My database table is configured as follows:
CREATE TABLE [dbo].[News] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[Title] NVARCHAR (100) NOT NULL,
[DatePosted] DATE NOT NULL,
[NewsContent] NTEXT NOT NULL,
[IsRead] BIT DEFAULT ((0)) NULL,
PRIMARY KEY CLUSTERED ([Id] ASC)[![enter image description here][1]][1]
);
Any ideas?
Try to format your code like this:
litTitle.txt = reader["Title"].ToString();
litDatePosted.Text = reader["DatePosted"].ToString();
litNewsContent.Text = reader["NewsContent"].ToString();
Also in your sql query you have a typo in the SELECT statement, you typed
'Newsontent' instead of 'NewsContent'
EDIT:
Try using the grid view instead of table. GridView should format it selfe acording to the sorce provided by the SqlDataAdapter
protected void Pageaaa_Load(object sender, EventArgs e)
{
SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["AppConnectionString"].ConnectionString);
string getNewsQuery = "SELECT Id, Title, DataPosted, Newsontent FROM News WHERE Id = #id";
//get email based on id
SqlCommand getNewsCommand = new SqlCommand(getNewsQuery, connection);
object id = null;
getNewsCommand.Parameters.AddWithValue("#id", id);
connection.Open();
SqlDataReader reader = getNewsCommand.ExecuteReader();
SqlDataAdapter da = new SqlDataAdapter();
DataTable dataTable = new DataTable();
da.Fill(dataTable);
GridView1.DataSource = dataTable;
GridView1.DataBind();
connection.Close();
da.Dispose();
}

Bootstrap grid not aligned properly when dynamically creating div

I am trying to retrieve product information such as name,imagepath etc from database using repeater and display in the dataview using code behind. I could successfully retrieve and display the detail but the alignment of the div is not proper.
aspx code:
<div class="row">
<asp:Repeater ID="Repeater2" runat="server"></asp:Repeater>
<asp:Repeater ID="Repeater1" runat="server">
<ItemTemplate>
<div class="col-sm-4 col-lg-4 col-md-4">
<div class="thumbnail">
<img width="250px" height="300px" src="images/<%#Eval("ImagePath") %>" alt="<%#Eval("ProductName") %>">
<div class="caption">
<h4><%#Eval("ProductName") %></h4>
<h4><%#Eval("UnitPrice")%></h4>
</div>
<div class="clearfix">
</div>
</div>
</div>
</ItemTemplate>
</asp:Repeater>
</div>
code behind:
SqlDataAdapter sda = new SqlDataAdapter("SELECT ProductName, UnitPrice, ImagePath FROM Products", con);
DataTable dt = new DataTable();
sda.Fill(dt);
DataView dv = new DataView(dt);
dv.Sort = "ProductName"; // Sort by product name
Repeater1.DataSource = dv;
Repeater1.DataBind();
current output:
screenshot
Expected output:
The fourth image should come below the first image according to bootstrap gridview concept which is not happening in my case and because of which the entire layout changes.
I am a beginner and have just started to learn bootstrap.
There are two ways to resolve this issue:
1) End the row after 3 columns and start 2nd row for next 3 columns.
2) Add equal height for columns. You can use following script and add 'resize-height' class to each column.
function setHeight(column) {
var maxHeight = 0;
//Get all the element with class = col
column = jQuery(column);
column.css('height', 'auto');
//Loop all the column
column.each(function () {
//Store the highest value
if (jQuery(this).height() > maxHeight) {
maxHeight = jQuery(this).height();
}
});
//Set the height
column.height(maxHeight);
}
jQuery(window).on('load resize', function () {
setHeight('.resize-height');
});

MVC 5 - raise Bootstrap Modal from Controller

Coming from WebForms getting my head around some MVC stuff is not quite intuitive and I am struggling to find a way to modal to pop-up from the controller (depending upon the postback result)..
The modal
<div id="PopupModal" class="modal fade in out">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button class="close" aria-hidden="true" type="button" data-dismiss="modal">×</button>
<h4 class="modal-title" id="ModalTitle"></h4>
</div>
<div class="modal-body" id="ModalBody">
<h5 id="ModalBodyText"></h5>
</div>
<div class="modal-footer">
<button class="btn btn-default" type="button" data-dismiss="modal">Close</button>
</div>
</div>
</div>
This is how I would have raised the event in WebForms
Private Sub ModalValidation(Message As String)
Try
Dim SB As New StringBuilder
SB.Append("$(document).ready(function(){")
SB.Append("$('#PopupModal').modal();")
SB.Append("var vBody = document.getElementById('ModalBodyText');")
SB.Append("vBody.innerHTML = '" & Message & "';")
SB.Append("var vTitle = document.getElementById('ModalTitle');")
SB.Append("vTitle.innerHTML = 'Validation';")
SB.Append("vTitle.style.color = 'orange';")
SB.Append("});")
ScriptManager.RegisterStartupScript(Me, Me.GetType(), "ValidationShowModal", SB.ToString, True)
Catch ex As Exception
Dim vError As New SendError
vError.MailError(60, PageName, ex)
End Try
End Sub
How can I raise the same event from the controller?
Thanks
Edit = Big thank you to Vitor Salgado for pointing me in the right direction
Added this to the controller - Index
Function Index() As ActionResult
Dim vPopup As New UploadFilesResult
If Not Session("PopupMessage") Is Nothing Then
vPopup.PopupMessage = Session("PopupMessage")
Else
vPopup.PopupMessage = "None"
End If
ViewData("UploadFilesResult") = vPopup
Return View("BlueImpMinView")
End Function
Added this to Controller - ActionResult (where the action completed normally)
Session("PopupMessage") = "The file was successfully uploaded!"
Return Redirect("/blueimp/Index#Completed")
Added a hidden field to the view
#code
Dim vPopup As MVPTest.UploadFilesResult = CType(ViewData("UploadFilesResult"), MVPTest.UploadFilesResult)
Dim vPopupMessage As String = vPopup.PopupMessage
#Html.TextBox("MessageTB", vPopupMessage, New With {.type = "hidden"})
End Code
and the javascript for the modal
<script>
window.onload = function () {
var vType = location.hash;
var vMessage = document.getElementById('MessageTB').value;
switch (vType) {
case '#Completed':
//run code for completed modal
$(document).ready(function () {
$('#PopupModal').modal();
var vBody = document.getElementById('ModalBodyText');
vBody.innerHTML = vMessage;
var vTitle = document.getElementById('ModalTitle');
vTitle.innerHTML = 'Success';
vTitle.style.color = 'green';
});
break;
case '#Error':
//run code for error modal
break;
case '#Validation':
//run code for validation modal
}
}
</script>
In controller code, you could append to your querystring some marker parameter or return a specific cookie, then, in your javascript code, you can identify one of these marker values and show your modal window.
Here some sample code..
The controller
public ActionResult Register()
{
return View();
}
[HttpPost]
public ActionResult Register(RegisterModel model)
{
return Redirect("/Home/Register#registered");
}
The view
#using (Html.BeginForm())
{
<label>Login</label><br />
#Html.TextBoxFor(x => x.Login)
<br />
<label>Name</label><br />
#Html.TextBoxFor(x => x.Name)
<br />
<label>Email</label><br />
#Html.TextBoxFor(x => x.Emai)
<br />
<input type="submit" value="Register" />
}
<script type="text/javascript">
window.onload = function () {
if (window.location.hash == '#registered') {
alert('Your modal code here!');
}
};
</script>
The action Register(POST) is the server side code that will create some marker to your client side code. In the sample, a added a hash value to url. You could return a cookie value or better, add some value to hidden field and read the value from it. In the view, a have simple JS code that executes on page load. The JS search for the hash value and show the modal.
There are several ways to do this that fit within the MVC way of doing things. Here's what I would do...
If you need the server to decide whether or not to show the modal, but you don't wish to refresh the page, then AJAX is probably what you want. Use can use jQuery's ajax calls to post data to a controller action, make a decision on the server, then send back a result that your js can use to either show the modal or not. This way, the page does not need to refresh yet you make a round trip to the server to decide what you need to do.

how to get uploaded file from one page to another page in asp.net?

I want to get uploaded file from one page to another page and then save to my online server.
My Code is
First Page:
<html>
<body>
<form action="http://localhost:3132/Sample/api/Test.aspx?frm=31" method="post" target="_blank">
Name: <input type="text" name="f1" id="f1"><br>
Email: <input type="text" name="email" id="email"><br>
FileName: <input type="file" name="file" id="file"><br>
<input type="submit" value="Submit">
</form>
</body>
</html>
Second Page:Entries.aspx
<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
System.Data.DataTable dtData=new System.Data.DataTable();
foreach (string strKey in Request.Form.AllKeys)
{
if(strKey.Equals("data.xml") || dtData.Columns.Contains(strKey))
continue;
dtData.Columns.Add(strKey);
System.Data.DataRow dr=dtData.NewRow();
if(dtData.Rows.Count>0)
dr=dtData.Rows[0];
dr[strKey]=Request.Form[strKey];
if(dtData.Rows.Count<1)
dtData.Rows.Add(dr);
}
string strFileName = string.Empty;
string newFilename = string.Empty;
string fileName = System.IO.Path.Combine(Server.MapPath("~/APIUploaded"), Request.Params["filename"].ToString());
newFilename = Guid.NewGuid().ToString();
System.IO.FileInfo fInfo = new System.IO.FileInfo(fileName);
newFilename = string.Format("{0}{1}", newFilename, fInfo.Extension);
strFileName = System.IO.Path.Combine(Server.MapPath("~/APIUploaded"), newFilename);
using (System.IO.FileStream fileStream = System.IO.File.Create(strFileName))
{
/*Getting stream from the Request object.*/
using (System.IO.Stream stream = Request.InputStream)
{
int byteStreamLength = (int)stream.Length;
byte[] byteStream = new byte[byteStreamLength];
/*Reading the stream to a byte array.*/
stream.Read(byteStream, 0, byteStreamLength);
/*Writing the byte array to the harddisk.*/
fileStream.Write(byteStream, 0, byteStreamLength);
}
}
Through the second page I am getting form values with uploaded file name. When I am going to save to my Online server folder, the file contents are empty. Is this possible to get uploaded file from one page to another page by using file upload control in asp.net?
You need to add the enctype to the form:
<form action="http://localhost:3132/GoLeadsUpdate/api/Entries.aspx?frm=31"
method="post" target="_blank" enctype="multipart/form-data">
.
.
.
</form>
And I think you have to look at Request.Files: http://msdn.microsoft.com/en-us/library/system.web.httprequest.files(v=vs.110).aspx

ASP form action file (FileSystemObject)

I've got my code to post a javascript array in a form:
<form id="my_form" action="file:///C:/Users/John/Desktop/jquery/savetext.aspx" method="post" onsubmit="return prepare()">
<input type="text" id="file_name" name="file_name" rows="1" cols="20" />
<input type="hidden" name="seatsArray" />
<input type="submit" value="Save" />
</form>
<script type="text/javascript">
function prepare();
{
document.getElementById('seatsArray').value = seatsArray.join();
return true;
}
</script>
Can anyone help me out with the savetext.aspx action file that I need, as my knowledge of ASP.NET is minimal (I'm used to PHP, but this one needs to be ASP.NET).
I guess I can have a crack at getting somewhere near:
<%# Page Language="C#" %>
<script runat="server">
using System;
using System.IO;
class Test
{
public static void Main()
{
string path = "file:///C:/Users/John/Desktop/jquery/txtfiles/" + request.form("file_name");
if (!File.Exists(path))
{
using (StreamWriter sw = File.CreateText(path))
{
sw.WriteLine(request.form("seatsArray"));
sw.WriteLine("");
}
}
using (StreamReader sr = File.OpenText(path))
{
string s = "";
while ((s = sr.ReadLine()) != null)
{
Console.WriteLine(s);
}
}
}
}
</script>
Am I on the right track?
Many Thanks!
I think you should just use the form as intended, and just add the array data to a hidden element..
<form id="my_form" action="http://my_site/savetext.aspx" method="post" onsubmit="return prepare()">
<input type="text" id="file_name" name="file_name" rows="1" cols="20" />
<input type="hidden" name="seatsArray" />
<input type="submit" value="Save" />
</form>
<script type="text/javascript">
function prepare();
{
document.getElementById('seatsArray').value = seatsArray.join();
return true;
}
</script>
and on the server side use request.form("file_name") and request.form("seatsArray")
you need use the Stream Class. This is a short code for write / create text files in ASP.NET using VB.NET.
Dim strStreamW As Stream
Dim strStreamWriter As StreamWriter
Try
Dim ds As New DataSet
Dim FilePath As String = "C:\nombreArchivo.txt"
'Open the file, if not exists create it
strStreamW = File.OpenWrite(FilePath)
strStreamWriter = New StreamWriter(strStreamW, _
System.Text.Encoding.UTF8)
'Using a conection with the db
ds = Negocios.TraerDatosArchivo()
Dim dr As DataRow
Dim Nombre as String = ""
Dim Apellido as String = ""
Dim Email as String = ""
For Each dr In ds.Tables(0).Rows
'Get the recordset
Nombre = CStr(dr("Nombre"))
Apellido = CStr(dr("Apellido"))
Email = CStr(dr("Email"))
'Write the line in the file or "stream"
strStreamWriter.WriteLine(Nombre & " " & Apellido & " - " & Email)
Next
strStreamWriter.Close()
Catch ex As Exception
strStreamWriter.Close()
MsgBox(ex.Message)
End Try

Resources