MVC 5 - How to send an Excel file to the client? - javascript

I have a Bootstrap application that shows a list of data. I have a button at the bottom of the page that, when clicked, creates an Excel file and sends it back to the client.
The link (button) the user clicks to start the process is as follows:
<li>Export list to Excel</li>
The JavaScript function that gets called looks like this:
function ExportToExcel() {
var Url = "/UserLocation/ExportToExcel";
$.get(Url);
}
I know this probably isn't right, but it does correctly call my C# function that creates the Excel spreadsheet.
My C# function looks like this:
public ActionResult ExportToExcel()
{
var locationList = this.UserLocationData.GetList(this.AccountRowId).AsEnumerable();
ExcelPackage package = Common.Excel.CreateExcelFile(locationList);
var cd = new System.Net.Mime.ContentDisposition
{
// for example foo.bak
FileName = "ExcelTest.xlsx",
// Always prompt the user for downloading, set to true if you want the browser to try to show the file inline
Inline = false,
};
Response.AppendHeader("Content-Disposition", cd.ToString());
return File(package.GetAsByteArray(), "application/force-download");
}
At the moment, when the user clicks the button, my C# function is called, but nothing is returned to the client. I suspect my JS function is not correct, but I don't really know what to do to make it correct. I also don't know what MIME type to use in my C# method (the last line in my C# method). Is there a better way to do all this? I am fairly new to JavaScript.

With $.get() you're getting the data through ajax. The browser will get the file content in the ajax response, but there is no way to offer the user to save this data as a file. (Well, technically is possible in most browsers, but not in all of them, although some more are supported with this js. But obviously it's overkill for this case. Thanks to zerkms for his comment).
The solution is much simpler, use the old good window.open(url), so the file is opened in a new browser window, and the user will be invited to open or save it (that depends on the browser configuration).
Or use directly a link like this:
<li><a href ="/UserLocation/ExportToExcel" class="btn btn-info btn-sm">
Export list to Excel</a></li>
(unless your js function does some extra processing).

Related

Sending data from javascript to php to generate a pdf but doesn't work

I am using JavaScript to take the info from a form completed by the user, then sending this data to PHP and generate a PDF with FPDF. The problem is I want the browser to ask the user to save the PDF or view it online but
I cannot figure out how. The PDF generates correctly but only when I save it directly to a certain path specified by me.
The question is how do you guys send data from JavaScript to PHP to generate a PDF file then the browser asks the user to open or download, Or how can I make a function where the user can retrieve this PDF.
The JavaScript:
function senddata() {//this activates when i push a button not a submit
var peticion = new XMLHttpRequest();
peticion.open('POST', 'generatepdf.php');
var nueva2 = {};
var key;
for (i = 0; i < 6; i++) {
key = document.forms[0].elements[i].id;
nueva2[key] = document.forms[0].elements[i].value;
}//here i take my data from the form and make an object
var json = JSON.stringify(nueva2);//here i tranform my object to json string so i can send it to my php
var parametros = "json_string=" + json;//here I do this so later I can easily transform the $_POST to an array in the form json_decode($_POST["json_string"],true);
peticion.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
peticion.send(parametros);//it sends ok
}
The PHP with the FPDF class and things
<?php
require('fpdf/fpdf.php');
require('functions.php');
if($_SERVER['REQUEST_METHOD']=='POST'){
$datos=json_decode($_POST["json_string"],true); //here i have my data in an array format so i can use the parameters to fill my pdf fields
//...lots of pdf things here...//
$pdf->Output('F',"pdfs/Cotizacion ".$datos["nombres"]." ".$datos["apellidos"].".pdf");//this works but never ask the user
//$pdf->Output('D',"pdfs/Cotizacion ".$datos["nombres"]." ".$datos["apellidos"].".pdf");//this should force a dowload or send to the browser but doesnt work
//$pdf->Output();//this should send to the browser but doesnt work
}
To view your PDF inline to the browser, you should use the I variable instead. View full documentation here.
Also I don't think outputting the file in two methods at the same time works. It might conflict each other. The best way to do that is to test each method and if it does conflict each other just simply add a condition for the user to decide whether he/she wants to download or view it in the browser. Hope this helps.

DotNetBrowser calling a JS function and returning a value from C#

I see the option where you can initiate the function call in .NET and return a value, but I don't see an option where you are able to initiate a function call in javascript calling a .NET function and then return a value to javascript, similar to what would happen if I was using ASP.NET or hitting a Web API.
So basically here is what I am doing. I have a modal that pops up when the user clicks to save game. They enter the name of the Save Game file, click OK and it calls a .NET function to check the DB to see if it's a duplicate save game file or not. If it is, it should return "Error! Duplicate file name! Please choose a unique file name." If it is unique it saves the information to a DB and returns a "Successfully saved game!" message, waits 2 seconds and then redirects to the main dashboard page.
I have everything working fine up until the point .NET is supposed to return the value. Currently the modal window just sits there and nothing returns to JS.
I have it set up like I normally would through calling the .Net function and using .then(function (response) to get the response value, but it is coming back as undefined.
I'm sure there has to be a way to do this, I just don't see how in the documentation as that only shows how to do it when initiating the function call from .NET...
EDIT: OMG...I just realized this was such a dumb question...I'm already doing that returning lookups from the database...the answer was to set it equal to a variable instead of trying to chain the function onto the end.
THIS:
var value = window.CRUD.Save(fileName, model);
if(value === "Duplicate!") ....
INSTEAD OF:
window.CRUD.Save(fileName, model).then(function(response) {
});
The article by the following link explains how to call .NET from JavaScript:
https://dotnetbrowser.support.teamdev.com/support/solutions/articles/9000109869-calling-net-from-javascript
Thank you for adding your answer to the question as an update.

Store very small amount of data with javascript

I have one of those websites that basically gives you a yes or no response to a question posed by the url. An example being http://isnatesilverawitch.com.
My site is more of an in-joke and the answer changes frequently. What I would like to be able to do is store a short one or two word string and be able to change it without editing the source on my site if that is possible using only javascript. I don't want to set up an entire database just to hold a single string.
Is there a way to write to a file without too much trouble, or possibly a web service designed to retrieve and change a single string that I could use to power such a site? I know it's a strange question, but the people in my office will definitely get a kick out of it. I am even considering building a mobile app to manipulate the answer on the fly.
ADDITIONAL:
To be clear I just want to change the value of a single string but I can't just use a random answer. Without being specific, think of it as a site that states if the doctor is IN or OUT, but I don't want it to spit out a random answer, it needs to say IN when he is IN and OUT when he is out. I will change this value manually, but I would like to make the process simple and something I can do on a mobile device. I can't really edit source (nor do I want to) from a phone.
If I understand correctly you want a simple text file that you change a simple string value in and have it appear someplace on your site.
var string = "loading;"
$.get('filename.txt',function(result){
string = result;
// use string
})
Since you don't want to have server-side code or a database, one option is to have javascript retrieve values from a Google Spreadsheet. Tabletop (http://builtbybalance.com/Tabletop/) is one library designed to let you do this. You simply make a public Google Spreadsheet and enable "Publish to web", which gives you a public URL. Here's a simplified version of the code you'd then use on your site:
function init() {
Tabletop.init( { url: your_public_spreadshseet_url,
callback: function (data) {
console.log(data);
},
simpleSheet: true } )
}
Two ideas for you:
1) Using only JavaScript, generate the value randomly (or perhaps based on a schedule, which you can hard code ahead of time once and the script will take care of the changes over time).
2) Using Javascript and a server-side script, you can change the value on the fly.
Use JavaScript to make an AJAX request to a text file that contains the value. Shanimal's answer gives you the code to achieve that.
To change the value on the fly you'll need another server-side script that writes the value to some sort of data store (your text file in this case). I'm not sure what server-side scripting (e.g. PHP, Perl, ASP, Python) runtime you have on your web server, but I could help you out with the code for PHP where you could change the value by pointing to http://yoursite.com/changeValue.php?Probably in a browser. The PHP script would simply write Probably to the text file.
Though javascript solution is possible it is discouraged. PHP is designed to do such things like changing pieces of sites randomly. Assuming you know that, I will jump to javascript solution.
Because you want to store word variation in a text file, you will need to download this file using AJAX or store it in .js file using array or string.
Then you will want to change the words. Using AJAX will make it possible to change the words while page is loaded (so they may, but do not have to, change in front of viewers eyes).
Changing page HTML
Possible way of changing (words are in array):
wordlist.js
var status = "IN"; //Edit IN to OUT whenever you want
index.html
<script src="wordlist.js"></script>
<div>Doctor is <span id="changing">IN</span></div>
<script>
function changeWord(s) { //Change to anything
document.getElementById("changing").innerHTML = s;
}
changeWord(status); //Get the status defined in wordlist.js
</script>
Reloading from server
If you want to change answer dynamically and have the change effect visible on all open pages, you will need AJAX or you will have to make browser reload the word list, as following:
Reloading script
function reloadWords() {
var script = document.createElement("script"); //Create <script>
script.type="text/javascript";
script.src = "wordlist.js"; //Set the path
script.onload = function() {changeWord(status)}; //Change answer after loading
document.getElementsByTagName("head")[0].appendChild(script); //Append to <head> so it loads as script. Can be appended anywhere, but I like to use <head>
}
Using AJAX
Here we assume use of text file. Simplest solution I guess. With AJAX it looks much like this:
http = ActiveXObject==null?(new XMLHttpRequest()):(new ActiveXObject("Microsoft.XMLHTTP"));
http.onloadend = function() {
document.getElementById("changing").innerHTML = this.responseText; //Set the new response, "IN" or "OUT"
}
http.open("GET", "words.txt")
http.send();
Performance of AJAX call may be improved using long-poling. I will not introduce this feature more here, unless someone is interested.

ScriptManager.RegisterStartupScript Keeps adding script blocks multiple times

I have an update panel with a timer control set up to automatically check for some data updates every minute or so.
If it sees that the data updates, it is set to call a local script with the serialized JSON data.
ScriptManager.RegisterStartupScript(UpdateField, GetType(HiddenField), ACTION_CheckHistoryVersion, "updateData(" & data & ");", True)
where "data" might look something like
{
"someProperty":"foo",
"someOtherProperty":"bar",
"someList":[
{"prop1":"value"},
{"prop2":"value"}, ...
],
"someOtherList":[{},...,{}]
}
"data" can get quite large, and sometimes only a few items change.
The problem I am having is this. Every time I send this back to the client, it gets added as a brand new script block and the existing blocks do not get removed or replaced.
output looks something like this:
<script type="text/javascript">
updateData({
"someProperty":"foo",
"someOtherProperty":"bar",
"someList":[
{"prop1":"value"},
{"prop2":"value"}, ...
],
"someOtherList":[{},...,{}]
});
</script>
<script type="text/javascript">
updateData({
"someProperty":"foo",
"someOtherProperty":"bar",
"someList":[
{"prop1":"changed"},
{"prop2":"val"}, ...
],
"someOtherList":[{},...,{}]
});
</script>
<script type="text/javascript">
updateData({
"someProperty":"foos",
"someOtherProperty":"ball",
"someList":[
{"prop1":"changed"},
{"prop2":"val"}, ...
]
});
</script>
with a new script block being created every time there is a change in the data.
Over time the amount of data accumulating on the browser could get potentially huge if we just keep adding this and I can't imagine how most people's browser would take it, but I don't think it could be good.
Does anyone know if there is a way to just replace the code that has been sent back to the browser rather than continuously adding it like this?
I came up with a hack that seems to work in my situation.
I am using jQuery to find the script tag that I am creating and remove it after it has been called.
Here is an example:
First I generate a guid:
Dim guidText as string = GUID.NewGuid().ToString()
I create a function like the following:
function RemoveThisScript(guid){
$("script").each(function(){
var _this = $(this);
if(_this.html().indexOf(guid)>-1)
_this.remove();
});
}
Then I add the following code to my output string:
... & " RemoveThisScript('" & guidText & "');"
This causes jQuery to look through all the scripts on the page for one that has the GUID (essentially the one calling the function) and removes it from the DOM.
I would recommend to use web service with some webmethod which you will call inside window.setInterval. In success handler of your webmethod (on client side) you can just take response and do whatever you want with it. And it will not be saved in your page (well, if you will do everything wrong). Benefit is that you will minimize request size(updatepanel will pass all your viewstate data, which could be large enough) and will limit server resources usage (update panel is causing full page live cycle, suppose slightly modified, but anyway - all those page_load, page_init, etc...) and with web service you will only what you need.
Here is an article where you can see how it could be created and used on client side. Looks like good enough.

Managing Html text in popup

I'm using OpenLayer popup.
when initializing it, there a parameter required to contain the html displayed in the popup.
this parameter is javascript string.
I have a conflict, on the one hand the html text is long so I prefer to place it in html file and read the file to the variable.
On the other hand, the html depends on other local variables, so if I leave it on its place I can concatenate some strings and local variables to compose the final variable containing the html text. but it is very long and ugly code...
Maybe experienced javascript programmers can help me to find a design solution to this problem?
thanks
As you are using OpenLayers you can use the OpenLayers.loadURL function to retrieve HTML from your server.
http://dev.openlayers.org/releases/OpenLayers-2.10/doc/apidocs/files/OpenLayers/Ajax-js.html
If you want to pass in local variables to server side HTML you can set up a simple handler that accepts variables, and integrates these into some static HTML (using string formatting or a template).
If you are using .NET then a .ashx file can do this. See http://dotnetperls.com/ashx for an example.
Another solution is to use an Ajax request to load your file, and then print the content inside the popup.
Using JQuery:
$.get('myfile.php',function(content){
var popup = new OpenLayers.Popup("popupid",
new OpenLayers.LonLat(mouseX,mouseY),
new OpenLayers.Size(360,200),
content,
true);
map.addPopup(popup);
});
When the Ajax request is completed, you can create the popup and fill it with the file content previously loaded.
I would recommend geographikas solution, and also try to use different js-classes to improve maintainability and readability. Don't do everything in the same object, make your own popup object that inherits from or uses OpenLayers.Popup.Anchored or something, and make the Ajax server call from there. This way you won't clutter your other code with this. Also makes it easy to reuse and substitute when needed.
I would go for something like this (untested!):
mynamespace.mypopup = function(o) {
var size = new OpenLayer.Size(100, 70);
var icon = new OpenLayers.Icon(); // Fill it
var popup = new OpenLayers.Popup.Anchored(o.id, o.lonlat, size, getContent(), icon, false, null);
var getContent = function() {
// ajax call
// return a string
}
return popup;
}
in a file called "mypopup.js"
and call it with:
var popup = new mynamespace.mypopup({id: 'whatever', lonlat: myLonLat});

Categories

Resources