I have the need to include a highcharts chart in a PDF report. But how can I get the image/png generated by the export.highcharts.com ?
That's what I have done so far:
At a button click, this ajax request is fired:
$.ajax({
url: "Home/Teste",
type: "POST",
dataType: "html",
data: { svgParam: myChart.getSVG() },
success: function (data) {
doStuff(data);
}});
At the server, I get the request and handle as follow:
[HttpPost]
[ValidateInput(false)]
public void Teste(string svgParam)
{
// Create a request using a URL that can receive a post.
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://export.highcharts.com/");
// Set the Method property of the request to POST.
request.Method = "POST";
// Create POST data and convert it to a byte array.
string postData = string.Format("filename={0}&type={1}&width={2}&sgv={3}", "chart", "image/png", 1270, Server.UrlEncode(svgParam));
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
// Set the ContentType property of the WebRequest.
request.ContentType = "application/x-www-form-urlencoded; multipart/form-data";
//User agent is based in a normal export.js request
request.UserAgent = #"Mozilla/5.0 (Windows NT 6.1; WOW64; rv:19.0) Gecko/20100101 Firefox/19.0";
// Set the ContentLength property of the WebRequest.
request.ContentLength = byteArray.Length;
// Get the request stream.
Stream dataStream = request.GetRequestStream();
// Write the data to the request stream.
dataStream.Write(byteArray, 0, byteArray.Length);
// Close the Stream object.
dataStream.Close();
// Get the response.
WebResponse response = request.GetResponse();
HttpWebResponse webResponse = (HttpWebResponse)request.GetResponse();
//This is here just to read the response.
string msg;
using (StreamReader sReader = new StreamReader(webResponse.GetResponseStream()))
{
msg = sReader.ReadToEnd();
}
}
The svgParam is an html string with content like this: "
I get this svgParam in the asp.net with no problems. But the response from the export.highcharts.com is always the same, as if te svg was not sent:
<body>
<div id="top">
<a href="http://www.highcharts.com" title="Highcharts Home Page"
id="logo"><img alt="Highcharts Home Page"
src="resources/Highcharts-icon-160px.png" border="0"></a>
<h1>Highcharts Export Server</h1>
</div>
<div id="wrap">
<h3>Oops..,</h3>
<p>The manadatory svg POST parameter is undefined.</p>
</div>
</body>
For the sake of testing, I created another method in my application, to receive this WebRequest as follow:
[HttpPost]
[ValidateInput(false)]
public void Teste2(string filename, string type, string width, string svg)
{
string whereIsMySvg = svg;
}
The filenam, type and width parameters are received. But the svg one is null. I tried to encode, to not encode, serialize as json string, change the content-type...and nothing, the svg parameter never get to the destination.
Any ideas?
If you copied and pasted your code and this is not a typographical error you mispelled "svg" in the request parameters being sent to the exporting server. You have "sgv".
Related
I have an MVC .cshtml page with a button. It's in a grid and I am passing the row ids to the controller using the jquery
<button type="submit" id="btn_View" name="view"
class="btn_View">
$(".btn_View_Question").click(function () {
var json = [];
var obj = {};
var rowID = $(this).closest('tr').attr('id');
obj.RowId= rowID ;
console.log(obj);
json.push(obj)
var responseDetails = JSON.stringify(json);
$.ajax({
url: "/Home/View",
type: "POST",
data: responseDetails,
dataType: "json",
traditional: true,
contentType: "application/json; charset=utf-8",
});
});
In the controller class I am redirecting to a aspx report page as follows
public RedirectResult ViewQuestionnaire(string[] id)
{
var reportParameters = new Dictionary<string, string>();
reportParameters.Add("ID", id[0]);
Session["reportParameters"] = reportParameters;
return Redirect("../Reports/ViewQuestionarie.aspx");
}
The aspx page is not loading. When I debug it the page_load of the aspx page also executing. What might the wrong thing I am doing here
Redirect is going to return a 302 response with the new url as the location header value.You should not be making the call to an action method which returns a 302 response from an ajax call.
Looks like you want to set some data to Session. You may use your ajax call to still do that part. Instead of returning a 302 response,return a json data structure with the url you want the browser to be redirected.
public ActionResult ViewQuestionnaire(string[] id)
{
var reportParameters = new Dictionary<string, string>();
reportParameters.Add("ID", id[0]);
Session["reportParameters"] = reportParameters;
return Json(new {status = "success", url="../Reports/ViewQuestionarie.aspx"});
}
And in the success / done event of the ajax call, you can read the url property of the json response coming back and use that to do the redirection.
$.ajax({
//Omitted some parameters
success: function(res) {
if (res.status === "success") {
window.location.href = res.url;
}
}
});
I have integrated tinymice rich text in my project,
When user enters a rich text ( which contains Image and other rich content ), I am passing the content to struts action methods through ajax calls and then sending it to server .
tinymce.activeEditor.getContent();
the above line returns me the content as follows
<p>Test tinymice text content</p>
<p> </p>
<p>with multi line text</p>
<p> </p>
<p>And <strong>Bold text</strong></p>
The same content I am sending it to server .
but the problem is due to some special symbols may be
at struts side I am not getting the exact data .
In struts I am getting data as follows
<p>Test tinymice text content</p>
<p>
Facing issue with image as well. When I fetch data from server I am getting valid data but facing issue with "" characters . example image data looks like below , and it shows an error in jsp as - Uncaught SyntaxError: Unexpected identifier
the error is mainly due to improper "" characters used . How exactly I should send rich text to struts and the to server? and in DB I am storing it as blob
"<p><img src="data:<;base64,<;base64,image/png;base64,
Update -
My ajax Code
var postTitle = document.getElementById("title").value;
var postDescription = tinymce.activeEditor.getContent();
var formdata = "title="+postTitle+"&"+"description="+postDescription;
// call function for handling Ajax part
$.ajax({
type: "POST",
url : "postDetails" ,
contentType: "application/x-www-form-urlencoded",
async: true,
data : formdata,
cache: false,
processData: false,
datatype: json,
success: successBlock,
error: failureBlock
});
The form data in above code looks like this when I put an alert
title=test&description=<p>Test tinymice text content</p>
<p> </p>
<p>with multi line text</p>
<p> </p>
<p>And Bold text</p>
Struts code
public class DescriptionAction {
String title;
String description;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
//Action method
public String postDescription(){
//Here my server request goes
}
}
I have found answer for my question.
I have to use encodeURI before posting data
updated ajax code
//Remove form data
//var formdata = "title="+postTitle+"&"+"description="+postDescription;
// call function for handling Ajax part
$.ajax({
type: "POST",
url : "postDetails" ,
//Remove contentType , it should not be form urlencoded
// contentType: "application/x-www-form-urlencoded",
// async: true,
//Use encodeURI to get rid of special characters within richText
data :{title:postTitle,description:encodeURI(postDescription)},
// cache: false,
// processData: false,
datatype: json,
success: successBlock,
error: failureBlock
});
I've got a controller action that downloads a dynamically generated file:
public ActionResult DownloadFile()
{
var obj = new MyClass { MyString = "Hello", MyBool = true };
var ser = new XmlSerializer(typeof(MyClass));
var stream = new MemoryStream();
ser.Serialize(stream, obj);
stream.Position = 0;
Response.Clear();
Response.AddHeader("Content-Disposition", "attachment; filename=myfile.xml");
Response.ContentType = "application/xml";
// Write all my data
stream.WriteTo(Response.OutputStream);
Response.End();
return Content("Downloaded");
}
Just for reference:
public class MyClass
{
public string MyString { get; set; }
public int MyInt { get; set; }
}
This is working, and the file (myfile.xml) is downloaded.
However, the message "Downloaded" is not sent to the browser.
Similarly, if I replace return Content("Downloaded");
for return Redirect("www.something.com");
then the browser is redirected before the file downloads.
As a bit of a pre-amble, the user journey is:
User fills out form on previous view
Form is submitted
XML is generated and downloaded
User is redirected / "Downloaded" view is shown (so hitting F5 won't re-post the form)
As Ross has said, you can only return one response to a HTTP request.
What i do in that case is:
Send the request to the server
The server generates the file and stores it in some server side data structure (Cache, Usersession, TempData)
The server returns a RedirectToAction() (POST, REDIRECT, GET pattern)
The redirected action returns a View with some javascript which
Triggers the download of the pregenerated file by setting window.location.href property to an special download action which sends the file back to the browser
Each HTTP request can only have one response - you're trying to sneak in two (the file, and a page).
Normally when you send a "Content-Disposition: attachment" HTTP header the browser will stay on the current page and pop a file save dialog (or automatically save the file in your downloads).
You're going to have to change your strategy if you want to prevent re-submission of the form. I'd suggest a bit of javascript to disable the form's submit button and show the "Completed" message in a div overlay?
Here is how I redirected after the file is downloaded.
The main logic is to wait the redirect until the file is downloaded.
To do that, a server side response is calculated and redirect is delayed using server side response time + some offset.
Server Side Controller Code:
[HttpPost]
public ActionResult GetTemplate()
{
return Json(new {Url = Url.Action("ReturnTemplate") });
}
[HttpGet]
public ActionResult ReturnTemplate()
{
FileResult fileResult = // your file path ;
return fileResult;
}
Client Side Code:
<div id="btnGen" align="right"><button class="main-button" id="generateTemplate" type="Submit"></div>
Javascript:
$("#generateTemplate").click(function () {
var startTime = (new Date()).getTime(), endTime;
$.ajax({
url: '#Url.Action("GetTemplate", "Controller")',
type: 'POST',
traditional: true,
dataType: "json",
contentType: "application/json",
cache: false,
data: JSON.stringify(),
success: function (result) {
endTime = (new Date()).getTime();
var serverResponseTime = endTime - startTime + 500;
setInterval(function () { Back() }, serverResponseTime);
window.location = result.Url;
}
});
});
function Back() {
window.location = '#Url.Action("Index","Controller")';
}
I have got an ajax request to my Server where i am creating an PDF File. Now i want to display this file in a new window/tab or just download it. how can i do that?
my request
$.ajax({
url: '/Document/CreatePDF',
type: 'POST',
data: {
docid: documentId,
dataId: array
},
traditional: true,
success: function (data) {
}
});
[HttpPost]
public FileStreamResult CreatePDF(long docid, List<long> dataId)
{
var document = _rep.LoadDocument(docid.ToString(), Server.MapPath("~/Documents/") + docid + ".xml");
var exporter = new PDFExporter(document);
MemoryStream fileStream = exporter.CreatePDF();
byte[] PdfByte = fileStream.GetBuffer();
fileStream.Flush();
fileStream.Close();
HttpContext.Response.AddHeader("content-disposition","attachment; filename=form.pdf");
return new FileStreamResult(fileStream, "application/pdf");
}
You cannot use AJAX to download files. The reason for that is because javascript doesn't allow you to save the downloaded content on the client computer, nor to prompt for a Save As dialog. You should use a simple HTML <form> or an anchor:
#using (Html.BeginForm("CreatePDF", "Document", FormMethod.Post, new { id = "myform" }))
{
<button type="submit">Download</button>
}
If you need to pass arguments to this controller action that are known only at the client you could subscribe to the .submit event of this form and then dynamically inject hidden fields into it with the corresponding values and then leave the default action execute. And if the values are known at the server side you should simply use HTML helpers to generate those hidden fields.
Question is really simple. What is Request.InputStream and when to use it. Is it always used to read entire html body sent in the post request or only some parameters sent in it? Why should i not send data as a parameter to my server side code by passing it in the Ajax request?
In the example i can either pass the parameter in the data: or i can read the parameter in the Request.InputStream. When should i use which one?
Example:
In controller:
public ActionResult GetSomeData(string someData)
{
Request.InputStream.Position = 0;
System.IO.StreamReader str = new System.IO.StreamReader(Request.InputStream);
string sBuf = str.ReadToEnd();
return Json("something");
}
Ajax Request:
$.ajax({
type: "POST",
url: "Home/GetSomeData",
data: "{someData:'Hello'}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (msg) {
alert(msg);
// Insert the returned HTML into the <div>.
$('#dvResult').html(msg);
}
});
Request.InputStream allows you to access the raw request data. If this data is formatted using some standard format such as application/x-www-form-urlencoded or multipart/form-data or some other format that the default model binder understands you do not need to use Request.InputStream. ASP.NET will parse the request values and you will be able to access them directly using Request[...]. Of course in ASP.NET MVC you don't even need to use Request[...] because you can define a view model which your controller action will take as parameter and leave the model binder assign its properties from the request.
There are cases though when you might want to access the raw request stream. For example you have invented some custom protocol and the client sends some custom formatted data in the request stream. Those cases are very rare since inventing custom protocols is not very common.
Now back to your question. In your case you could define a view model:
public class MyViewModel
{
public string SomeData { get; set; }
}
which your controller action will take as argument:
public ActionResult GetSomeData(MyViewModel model)
{
// model.SomeData will contain the Hello string that the client sent
return Json("something");
}
and on the client I would recommend you using the JSON.stringify method which is natively built into modern browsers to JSON serialize the request javascript literal into a JSON string instead of manually writing the JSON as you did:
$.ajax({
type: 'POST',
url: 'Home/GetSomeData',
data: JSON.stringify({ someData: 'Hello' }),
contentType: 'application/json; charset=utf-8',
success: function (msg) {
alert(msg);
// Insert the returned HTML into the <div>.
$('#dvResult').html(msg);
}
});