I am trying to do this for the first time based on modifying a code snippet I found online. I am building an html data table in my code behind embedding sql data from a c# datatable. I am then trying to pass it to an .aspx page using an AJAX call and passing the html table string to a tag. The problem I am having is that when I breakpoint on the htmlTable string it looks good but the page is coming up with a javascript alert box saying 'error', not sure how to troubleshoot from this point or what is wrong with the code, I have pasted below, any assistance is appreciated!!!
Code Behind:
namespace WebApplication3
{
public partial class Page_MF : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
private static string connTotalOrdersCalls = ConfigurationManager.ConnectionStrings["connTotalOrdersCalls"].ConnectionString;
public static DataTable reportDT()
{
try
{
String sp_Name = "USP_TOTAL_ORDERCALLS";
using (DataTable OrdersCalls = new DataTable())
{
OrdersCalls.Columns.Add("Week_Ending");
OrdersCalls.Columns.Add("Mth");
OrdersCalls.Columns.Add("Product_Suite");
OrdersCalls.Columns.Add("Site");
OrdersCalls.Columns.Add("SalesAction");
OrdersCalls.Columns.Add("Orders");
OrdersCalls.Columns.Add("TotalCalls");
using (SqlConnection SQLConn = new SqlConnection(connTotalOrdersCalls))
{
using(SqlCommand SQLComm = new SqlCommand(sp_Name, SQLConn))
{
SQLComm.CommandType = CommandType.StoredProcedure;
//SQLComm.Parameters.Add(new SqlParameter("#Site", null);
SQLConn.Open();
SqlDataReader sql_Reader = SQLComm.ExecuteReader();
while (sql_Reader.Read())
{
Object[] row = {
sql_Reader["Week_Ending"].ToString(),
sql_Reader["MTH"].ToString(),
sql_Reader["PRODUCT_SUITE"].ToString(),
sql_Reader["SITE"].ToString(),
sql_Reader["Orders"].ToString(),
};
OrdersCalls.Rows.Add(row);
}
}
return OrdersCalls;
}
}
}
catch (Exception)
{
throw;
}
}
[WebMethod]
public static String SendToDiv()
{
String htmlTable = "<table>";
DataTable newTable = reportDT();
for (int i = 0; i < newTable.Rows.Count; i++)
{
htmlTable += "<tr>";
for (int x = 0; x < newTable.Columns.Count; x++)
{
htmlTable += "<td>" + newTable.Rows[i][x] + "</td>";
}
htmlTable += "</tr>";
}
return htmlTable;
}
}
}
.ASPX Page:
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
//on document ready event (when the dom is ready)
$(document).ready(function () {
appendToDiv();
});
function appendToDiv() {
$.ajax({
type: "POST",
async: false,
contentType: "application/json; charset=utf-8",
url: "Page_MF.aspx/SendToDiv",
data: JSON.stringify({}),
dataType: "json",
success: function (data) {
$('#div-for-upload').append(data.d)
},
error: function (result) {
alert("Error");
}
});
}
</script>
</head>
<body>
<form id="form1" runat="server">
<div id="div-for-upload">
</div>
</form>
</body>
</html>
according to the description you provided, below are possibilities.
1) Copy the value from htmlTable string variable. Create a HTML page and paste these content in the body section. If page displays the info, be sure, nothing wrong with the table creation.
In the provided solution, you must close the table node.
2) Check the response from developer tool like Firebug, Chrome developer tool by pressing F12 function key. It should show you the contents are being passed from server to client.
If you can see the response, your data is on the client side.
3) This condition limits us to the final option i.e you're accessing / trying to access wrong field for the data from the response.
Hope this helps.
Related
I have the following button in an Aspx page
<button type="button" style="margin: 10px;" class='btn btn-xs btn-warning' onclick="RunIntegrationTest('<%=obj.Tab.Replace(" ", "")%>')">TestRun</button>
and here's the function from the JS
function RunIntegrationTest(tableNames) {
c = confirm("Are you sure you want to Run Test?");
if (c) {
$('#LoadingModal').modal('show');
$.ajax({
url: 'Shared/_RunIntegrationTestMainPage?tableNames=' + tableNames,
type: 'GET',
success: function (res) {
$('#LoadingModal').modal('hide');
$('#GeneralModal').find('div.modal-title').text('Successfull');
$('#GeneralModal').find('div.modal-body').html('<p>Run Worked, please refresh the page to see updates</p>');
$('#GeneralModal').modal('show');
},
error: function () {
$('#LoadingModal').modal('hide');
$('#ErrorModal').modal('show');
}
});
}
}
here's the class for the button
protected void Page_Load(object sender, EventArgs e)
{
string tableNames = Request.QueryString["tableNames"].ToString();
if (!string.IsNullOrEmpty(tableNames))
{
string sql = "";
foreach (string table in tableNames.Split(','))
{
sql += " EXEC Run_"+table
}
SqlCmd cmd = new SqlCmd(sql);
cmd.ExecuteNonQuery();
}
Response.Write("OK");
}
}
the button is a dynamic button that will be added to any table that I add in the default, it's work is that it run any stored procedure that i added with the table name.
the stored procedure is a trigger type that will update the database
what I'm trying to do is when one button is pressed the other buttons on the other tables get disabled till the update of the database finish.
How can I achieve that? I don't want a timer because that won't achieve the purpose of the function
Thank you in advance
I am developing a spring+hibernate webapp for practicing translation skill from Russian to English.
In one of my jsp pages I am retrieving all the questions from database and placing them into a table with the following columns: text in Russian, field for user's translation, button for checking the result. The goal is to save user's input into database without refreshing the page. How can I do it?
I tried several options, but none of them worked for me.
I used the solution from Send javascript variables to spring controller in my project, but nothing happened at all.
Part of "firstPage.jsp" ("/first" path in the controller):
<head>
<title>Title</title>
<script>
function searchViaAjax(id) {
var tempId = id;
alert("Start");
$.ajax({
type : "POST",
url : "./search/api/getSearchResult",
data : {id:tempId},
timeout : 100000,
success : function(id) {
alert("success");
console.log("SUCCESS: ", id);
display(id);
alert(response);
},
error : function(e) {
alert("error");
console.log("ERROR: ", e);
display(e);
},
done : function(e) {
alert("done");
console.log("DONE");
}
});
}
</script>
</head>
<body>
<button onclick="searchViaAjax(1)">Simple button</button>
</body>
Controller class:
#Controller
public class DemoController {
#RequestMapping("/first")
public String getFirst(){
return "firstPage";
}
#ResponseBody
#RequestMapping(value = "/search/api/getSearchResult", method=RequestMethod.POST)
public String getSearchResultViaAjax(#RequestParam("id") Integer id) {
System.out.println("come to ajax"+ id);
return "hello";
}
}
The "Start" message gets printed, but other messages from searchViaAjax() don't. And controller method doesn't start.
You can pass id in controller as it is no issue in your 'id', and also you can skip value attribute in #RequestParam.
#ResponseBody
#RequestMapping(value = "/search/api/getSearchResult")
public String getSearchResultViaAjax(#RequestParam("id") integer id) {
System.out.println("come to ajax"+ id);
return "hello";
}
Specify the methodType
#RequestMapping(value = "/search/api/getSearchResult", methodType=RequestMethod.POST)
It is also a good practice to use wrapper instead of primitive
#RequestParam("tempId") Integer id
the problem is in your ajax url attribute.
It should be url : "./search/api/getSearchResult",
Root Cause:
When you are about to hit your controller, it construct the url like this
http://localhost:8080/search/api/getSearchResult
and hence such resource is not available and it causes 404 not found error.
In actual the url should be
http://localhost:8080/contextroot/search/api/getSearchResult
here contextroot refers your project name.
Now if you hit url ./search/api/getSearchResult then ./ refers the base url i,e localhost:8080/contextroot and the entire url will be constructed properly.
I would like to recommend you to create global variable in JavaScript say baseUri and assign./ into it.
<script>
var baseUri="./";
</script>
In your AJAX it becomes
url : baseUri+"search/api/getSearchResult",
Hope this will help
The code from user9634982 was fine, thanks to him. The problem was because I was using slim jQuery version so my browser was giving me "$.ajax is not a function" error. And I didn't see it for hours because I didn't know where to look :facepalm: Thanks again to user9634982 for discovering browser inspector to me :D After replacing slim version to usual it still didn't work because of spring security. I added _csrf token and all worked fine.
.jsp:
<meta name="_csrf" content="${_csrf.token}"/>
<meta name="_csrf_header" content="${_csrf.headerName}"/>
<script>
function searchViaAjax(id) {
var csrfHeaderName = "X-CSRF-TOKEN";
var csrfTokenValue;
var metaTags = document.getElementsByTagName('meta');
for(var i = 0; i < metaTags.length; i++) {
var metaTagName = metaTags[i].getAttribute("name");
if(metaTagName === "_csrf_header")
csrfHeaderName = metaTags[i].getAttribute("content");
if(metaTagName === "_csrf")
csrfTokenValue = metaTags[i].getAttribute("content");
}
$.ajax({
type : "POST",
url : "./addAnsweredQuestion",
data : {id:id},
timeout : 100000,
beforeSend:function(xhr){xhr.setRequestHeader(csrfHeaderName, csrfTokenValue);},
success : function(id) {
alert("success");
console.log("SUCCESS: ", id);
display(id);
alert(response);
},
error : function(e) {
alert("error");
console.log("ERROR: ", e);
display(e);
},
done : function(e) {
alert("done");
console.log("DONE");
}
});
}
</script>
Controller:
#PostMapping(value = "/addAnsweredQuestion")
public void getSearchResultViaAjax(#RequestParam("id") Long id) {
System.out.println("come to ajax"+ id);
}
Can someone help me solve this problem. I just want to add an Items in element in html with database field using c# and javascript, but my code has no output. Also, I tried to input a button and Called the Function "loadGrp" on onClick property of the button. eg: input type="submit" value="Add Item" onClick ="loadGrp();" but also it does not work. how to fix this problem, i know someone out there has a capability to solve this, so please help me guys Guys..
JS
function loadGrp()
{
$.ajax({
type: 'POST',
url: '../WebService/wsLeaveRequest.asmx/LoadGroup',
dataType: 'json',
//data: '',
contentType: 'application/json; charset=utf-8',
success: function (response){
$('#cboGroup').empty();
var cell = eval("(" + response.d + ")");
for (var i = 0; i < cell.length; i++)
{
$('#cboGroup').append('<option value="' + cell[i].grpID + '">"' + cell[i].grpShortName + '</option>');
}
},
error: function (error) {
console.log(error);
},
complete: function () {
}
});
}
C#
[WebMethod]
public string LoadGroup()
{
List<GroupInfo> mylist = new List<GroupInfo>();
using (SqlConnection conn = new SqlConnection(connectionString()))
{
conn.Open();
SqlCommand cmd = new SqlCommand("spLoadGroup", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandTimeout = 0;
SqlDataReader dr = cmd.ExecuteReader();
while(dr.Read())
{
mylist.Add(new GroupInfo
{
grpID = dr["groupID"].ToString(),
grpShortName = dr["groupShortName"].ToString()
});
}
dr.Close();
conn.Close();
}
JavaScriptSerializer js = new JavaScriptSerializer();
string jsn = js.Serialize(mylist);
return jsn;
}
HTML
<!DOCTYPE html>
<html>
<script src="Script/jsSetting.js"></script>
<script src="Script/jsleaverequest.js"></script>
<div class="row cells12">
<div class="cell colspan3">
<div class="input-control select full-size">
<h5>Filter Group:</h5>
<select id="cboGroup"></select>
</div>
</div>
</div>
</div>
<body>
<head>
</head>
</body>
</html>
Here are couple of observations
url: '../WebService/wsLeaveRequest.asmx/LoadGroup',
The .. may not be making any sense here
If there is no form in the page then replace input type = "submit" with input type = "button"
var cell = eval("(" + response.d + ")"); seems fishy. Using eval is not a good idea and specifically here it dont seems to make any sense.
Put a debugger or a log statement at the first line of function loadGrp and see if the function is getting executed on button click. Then check from developer's window(For Chrome press f12 -> Click on network -> Hit the input type = button) and validate if it is making any network call and validate the response of it
I am not that good at either .net or sql.
The thing is I have a web form and a database. The form would let the user enter information in textbox and dropdownlist.
the data in the dropdownlist is saved in a table.
So, I am reading values from the table, when the users fill the form and choose from the dropdownlist the options they want, the data in the textbox and selected dropdownlist should be sent back to be saved in the database.
I have successfully read the value from the database and show them in the dropdownlist like in the following code:
public class state
{
public string stateID { get; set; }
public string stateName { get; set; }
}
[WebMethod]
public static List<state> PopulateDropDownList()
{
DataTable dt = new DataTable();
List<state> objDept = new List<state>();
SqlConnection con = new SqlConnection("Data Source = ****; Initial Catalog = LCF2016; Integrated Security = true");
{
using (SqlCommand cmd = new SqlCommand("SELECT STATE_ID, STATE_Name FROM state", con))
{
con.Open();
SqlDataAdapter da = new SqlDataAdapter(cmd);
da.Fill(dt);
if (dt.Rows.Count > 0)
{
for (int i = 0; i < dt.Rows.Count; i++)
{
objDept.Add(new state
{
stateID = dt.Rows[i]["STATE_ID"].ToString(),
stateName = dt.Rows[i]["STATE_Name"].ToString()
});
}
}
return objDept;
}
}
}
<script src="
http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function () {
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
//url is the path of our web method (Page name/functionname)
url: "Default.aspx/PopulateDropDownList",
data: "{}",
dataType: "json",
//called on jquery ajax call success
success: function (result) {
$('#ddlstate').empty();
$('#ddlstate').append("<option value='0'>-Select-</option>");
$.each(result.d, function (key, value) {
$("#ddlstate").append($("<option></option>").val(value.stateID).html(value.stateName));
});
},
//called on jquery ajax call failure
error: function ajaxError(result) {
alert(result.status + ' : ' + result.statusText);
}
});
});
</script>
<p>State</p>
<asp:DropDownList ID="ddlstate" runat="server" Width="160px" />
However, even if I am successfully calling the data to be shown into the dropdownlist, I am not able to insert the selected data along with the data in the textbox back into the database. In other word, the data is not saved into the database.
Here is my code for inserting the data "when click submit":
public partial class Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (Page.IsPostBack == true)
{
Label1.Text = ("**Thanks for entering your information");
}
}
protected void Button1_Click(object sender, EventArgs e)
{
using (SqlConnection vid = new SqlConnection("Data Source = ****; Initial Catalog = LCF2016; Integrated Security = true"))
{
vid.Open();
using (SqlCommand xp = new SqlCommand("insert into LCF2016 (Fname, Lname, Email, Birthdate, Phone, Address, City, STATE_ID, Zip, Country_ID, Days_Per_Month, Primary_Language, Secondary_Language, Occupation_ID, HearAbout_ID, Other_Skills) Values(#Fname, #Lname, #Email, #Birthdate, #Phone, #Address, #City, #STATE_ID, #Zip, #Country_ID, #Days_Per_Month, #Primary_Language, #Secondary_Language, #Occupation_ID, #HearAbout_ID #Other_Skills)", vid))
{
xp.Parameters.AddWithValue("#Fname", TextBox1.Text);
xp.Parameters.AddWithValue("#Lname", TextBox2.Text);
xp.Parameters.AddWithValue("#Email", TextBox3.Text);
xp.Parameters.AddWithValue("#Birthdate", TextBox4.Text);
xp.Parameters.AddWithValue("#Phone", TextBox5.Text);
xp.Parameters.AddWithValue("#Address", TextBox6.Text);
xp.Parameters.AddWithValue("#City", TextBox7.Text);
xp.Parameters.AddWithValue("#STATE_ID", ddlstate.SelectedValue);
xp.Parameters.AddWithValue("#Zip", TextBox8.Text);
xp.Parameters.AddWithValue("#country_ID", ddlcountry.SelectedValue);
xp.Parameters.AddWithValue("#Days_Per_Month", TextBox10.Text);
xp.Parameters.AddWithValue("#Primary_Language", ddllangp.SelectedValue);
xp.Parameters.AddWithValue("#Secondary_Language", ddllangs.SelectedValue);
xp.Parameters.AddWithValue("#Occupation_ID", ddloccup.SelectedValue);
xp.Parameters.AddWithValue("#HearAbout_ID", ddlhearabout.SelectedValue);
xp.Parameters.AddWithValue("#Other_Skills", TextBox15.Text);
xp.ExecuteNonQuery();
}
}
The error I get is
Invalid postback or callback argument. Event validation is enabled using in configuration or <%# Page EnableEventValidation="true" %> in a page. For security purposes, this feature verifies that arguments to postback or callback events originate from the server control that originally rendered them. If the data is valid and expected, use the ClientScriptManager.RegisterForEventValidation method in order to register the postback or callback data for validation.
try,
by jquery
$( "#ddlstate" ).change(function() {
$('[id*=Hiddenfield1]').attr('value', $( "#ddlstate" ).val());
});
body
<asp:HiddenField ID="Hiddenfield1" runat="server">
code
xp.Parameters.AddWithValue("#STATE_ID", Hiddenfield1.vlue);
Never having tried exactly what you are doing here, my best approximation is that the ViewState is invalid when you do your PostBack because you're using Ajax to populate the drop down list. It appears you are populating your drop down list using an Ajax call, then trying to use a full page post to send that data back to the server.You have several things going on here I don't quite understand, but what I would suggest is this.
I think you need to do a server side Request / Post, i.e. bind your drop down list and text box controls server side on the request, and then use the normal postback to send the data back to the server. OR, use AJAX both ways -receive AND send your data, but not try to mix them as you are.
I'm a novice with webservices, so this one has me stumped. I have created a webservice that will (eventually) accept a block of html and create a pdf file from it. To keep it simple, currently I'm not passing any parameters into the service; I'm just creating a pdf document with "hello world" in it. In debug mode, when I call the service directly (i.e. start debugging from that asmx page), I can invoke the exportPDF() method and the results are perfect -- it creates the pdf just as I'd hoped.
The problem is when I call the webservice from a javascript, nothing happens. I've set up a breakpoint inside the service, so I know it's getting called, and as I mentioned there are no parameters being passed in, so I don't understand why it works when it's invoked directly, but not when it's invoked from a javascript call.
My javascript and webservice code is below...any help would be greatly, greatly appreciated!!
Javascript:
function getPDF(elem) {
var param = { html: elem.innerHTML };
$.ajax({
type: "POST",
contentType: "application/json; charset=UTF-8",
url: "../WebServices/exporting.asmx/exportPDF",
data: "{ }",
dataType: "json",
success: function (response) {
}
})
}
WebService:
using DMC.Classes;
using NReco.PdfGenerator;
using System;
using System.IO;
using System.Web;
using System.Web.Services;
using System.Web.UI;
namespace DMC.WebServices
{
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
[System.Web.Script.Services.ScriptService]
public class exporting : System.Web.Services.WebService
{
[WebMethod]
public void exportPDF()
{
WriteDocument("htmlToPDF.pdf", "application/pdf", ConvertHtmlToPDF());
}
public byte[] ConvertHtmlToPDF()
{
HtmlToPdfConverter nRecohtmltoPdfObj = new HtmlToPdfConverter();
nRecohtmltoPdfObj.Orientation = PageOrientation.Portrait;
nRecohtmltoPdfObj.PageFooterHtml = CreatePDFFooter();
nRecohtmltoPdfObj.CustomWkHtmlArgs = "--margin-top 35 --header-spacing 0 --margin-left 0 --margin-right 0";
return nRecohtmltoPdfObj.GeneratePdf(CreatePDFScript() + "Hello world" + "</body></html>");
}
public string CreatePDFScript()
{
return "<html><head><style>td,th{line-height:20px;} tr { page-break-inside: avoid }</style><script>function subst() {var vars={};var x=document.location.search.substring(1).split('&');for(var i in x) {var z=x[i].split('=',2);vars[z[0]] = unescape(z[1]);}" +
"var x=['frompage','topage','page','webpage','section','subsection','subsubsection'];for(var i in x) {var y = document.getElementsByClassName(x[i]);" +
"for(var j=0; j<y.length; ++j) y[j].textContent = vars[x[i]];}}</script></head><body onload=\"subst()\">";
}
public string CreatePDFFooter()
{
return "<div style='text-align:center;font-family:Tahoma; font-size:9px;'>Page <span class=\"page\"></span> of <span class=\"topage\"></span></div>";
}
public void WriteDocument(string fileName, string contentType, byte[] content)
{
HttpContext.Current.Response.Clear();
HttpContext.Current.Response.ContentType = contentType;
HttpContext.Current.Response.AddHeader("content-disposition", "attachment; filename=" + fileName);
HttpContext.Current.Response.CacheControl = "No-cache";
HttpContext.Current.Response.BinaryWrite(content);
HttpContext.Current.Response.Flush();
}
}
}
Thanks for the response, Mason! I've been working on this and found a solution; and while I admit it's not perfect, I don't think it's too bad. From all the different material I read, I started to get the feeling that a web service is more of a "go between" for passing data and not really meant to handle functionality like posting PDF documents. It would let you get away with it when debugging and invoking it directly, but that's about it.
So instead of using a web service, I created a class object. I also created a hidden field in my html. This field gets populated with the desired div.innerHtml content via JavaScript when somebody clicks the "Export to PDF" button. Upon postback, my codebehind checks to see if the hidden field is empty and if it isn't, it calls the exportPDF function, which in turn instantiates the class object that creates/downloads the PDF. The biggest pitfall to doing it this way, and some may consider this a big pitfall, is that to read in a field in the codebehind that has html markup in it you have to turn off validation for the web page, which obviously opens up your code for malicious attacks.
Below are the highlights of my code:
Web.Config
Add requestValidationMode = "2.0" to the web.config file
<system.web>
<httpRuntime
requestValidationMode="2.0"
targetFramework="4.5"
/>
</system.web>
.aspx Page:
Set ValidateRequest="false" in Page reference
<%# Page Title="Referrals" Language="C#" MasterPageFile="~/Behavior/Behavior.master" AutoEventWireup="true" CodeBehind="Referrals.aspx.cs"
Inherits="DMC.Behavior.Referrals" ClientIDMode="Static" EnableEventValidation="false" ValidateRequest="false" %>
.
.
.
<asp:LinkButton ID="LinkButton2" runat="server" OnClientClick="createPDF();">
<img src='../Images/icons/pdf.png'>PDF</asp:LinkButton>
.
.
.
<div id="export_pdf" class="pdfWidth_Portrait pdfSection" style="margin-top: 10px;" runat="server">
<div class="alert-info text-center" style="margin: 0; padding: 0;">
<table class="table table-condensed" style="margin-top: 0; padding: 30px; width: 100%;">
.
.
.
</table>
</div>
</div>
.
.
.
<asp:HiddenField ID="pdfData" runat="server" />
.
.
.
<script type="text/javascript">
function createPDF() {
document.getElementById("pdfData").value = document.getElementById("export_pdf").innerHTML;
}
</script>
Code Behind:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
//Set the hidden pdf field to null initially
pdfData.Value = "";
}
//If this field is no longer null, it means somebody is wanting to export into PDF
if (pdfData.Value != "")
{
exportPDF();
}
}
public void exportPDF()
{
string fileName = null;
export dmc = new export();
fileName = lblLocation.Text + " Behavior Statistics YTD " + lblDate.Text;
dmc.exportPDF(fileName, "Portrait", pdfData.Value);
//PDF downloaded, reset value to ""
pdfData.Value = "";
}
Export Class
using NReco.PdfGenerator;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.IO;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
namespace DMC.Classes
{
public class export
{
public void exportPDF(string fileName, string Orientation, string html)
{
HtmlToPdfConverter pdf = new HtmlToPdfConverter();
//Remove these control characters, they interfere with the formatting of the pdf document
html = html.Replace("\n", "");
html = html.Replace("\t", "");
html = html.Replace("\r", "");
switch (Orientation)
{
case "Portrait":
pdf.Orientation = PageOrientation.Portrait;
break;
case "Landscape":
pdf.Orientation = PageOrientation.Landscape;
break;
default:
pdf.Orientation = PageOrientation.Default;
break;
}
//In case needed for future
//pdf.CustomWkHtmlArgs = "--margin-top 35 --header-spacing 0 --margin-left 0 --margin-right 0";
pdf.Margins.Top = 25;
pdf.PageFooterHtml = createPDFFooter();
var pdfBytes = pdf.GeneratePdf(createPDFScript() + html + "</body></html>");
HttpContext.Current.Response.ContentType = "application/pdf";
HttpContext.Current.Response.ContentEncoding = System.Text.Encoding.UTF8;
HttpContext.Current.Response.AddHeader("content-disposition", "attachment; filename=" + fileName + ".pdf");
HttpContext.Current.Response.BinaryWrite(pdfBytes);
HttpContext.Current.Response.Flush();
HttpContext.Current.Response.End();
}
private string createPDFScript()
{
return "<html><head><style>td,th{line-height:20px;} tr { page-break-inside: avoid }</style><script>function subst() {var vars={};var x=document.location.search.substring(1).split('&');for(var i in x) {var z=x[i].split('=',2);vars[z[0]] = unescape(z[1]);}" +
"var x=['frompage','topage','page','webpage','section','subsection','subsubsection'];for(var i in x) {var y = document.getElementsByClassName(x[i]);" +
"for(var j=0; j<y.length; ++j) y[j].textContent = vars[x[i]];}}</script></head><body onload=\"subst()\">";
}
private string createPDFFooter()
{
return "<div><table style='font-family:Tahoma; font-size:9px; width:100%'><tr><td style='text-align:left'>Research Dept|RR:mm:jpg</td><td style='text-align:right'>Page <span class=\"page\"></span> of <span class=\"topage\"></span></td></div>";
}
}
}