Using Angular to Download a File via Ajax - c#

I have a service that generates a CSV file and returns it to the page via an http/ajax get. I'd like a user to click a button, have the service get called, and then have the file get downloaded to the user's browser.
I would like to do this The Angular Way, although I recognize this may have more to do with Ajax or the browser than Anguler per se.
The service is in C#, and this is what it returns:
return File(Encoding.UTF8.GetBytes(WriteCSV(assetList)), "text/csv", "results.csv");
The controller code that calls the service looks like the following. It works, but I don't know what to do on success:
$scope.exportCSV = function () {
$http({
method: "get",
url: "ExportCSV"
}).
error(function (data, status, headers, config) {
alert("Error exporting data to CSV.");
});
};

You can't initiate a download from a normal ajax GET or POST, you have to do the traditional way, eg window.location='url' and set the correct http header with the correct content-type which will prompt the download dialog in the users browser

Possibly a more 'angulary' way is to have your controller set a flag to trigger the download, but put the core functionality in a directive that builds an element with a "download" attribute, and on display, a callback/watch calls the ng-click.
For example:
// put this in a template related to a given controller
<downloader ng-if="downloadready"></downloader>
// controller just needs to trigger the directive into action
module.controller(..., function($scope){
$scope.downloadready = true; // trigger the directive to be created
});
// and the directive code will build the element and click the button
module.directive('downloader', function ($compile) {
return {
restrict: 'E',
replace: true,
// values here can be placed in the template as variables and accessed in link()
// but this is shortest to get the idea across
template: '<a id="downloadbtn" class="btn" download="backup.json"></a>',
link:function (scope, elm, attrs) {
// this clicks the button outside the digest loop which the scope was updated in
$timeout(function() {
angular.element($('#downloadbtn')).triggerHandler('click');
}, 0);
}
}
});
Though I admit, it's more mind-bending than changing redirect on window.location.

Related

MVC 5 + $Post() function not working after hosted on server

I have developed an application in MVC5. Onclick of a link on the View below code gets invoked -
// Code in View File
$.post('../ControllerName/FunctionName', //this is your url
{
id: image,
}, function (data) {
alert("Successfully published");
}
).error(function () {
alert("Failed to publish");
});
//Code in Controller
[HttpPost]
public void ISPPDF(string id)
{}
Issue that i am facing is the ISPPDF() function gets invoked when i run it through visual studio.However after i hosted my application on server it does not seem to call the function..
I feel there is some issue with the path i have specified -
i also tried specifying path the below ways but no luck!
/ControllerName/FunctionName
ControllerName/FunctionName
Any help would be appreciated.
Thanks,
You should never hard-code URLs in MVC.
Instead use #Url.Action.
$.post('#Url.Action("FunctionName", "ControllerName")', //this is your url
If you need to send parameters, you do it like this:
$.post('#Url.Action("FunctionName", "ControllerName", new { id = Model.ID })', //this is your url
And there are two important reasons why I recommend this:
1. The chances of mistyping the URL are huge. This Questions proves it, the OP mistyped the URL.
2. Url.Action takes into account your route. If your route changes, Url.Action will know how to build the correct URL. This way you will not have to go through multiple views to change all the hard-coded values.
Try this as your post method is in view file
$.post('../FunctionName',{ id: image,}, function (data) { alert("Successfully published");}).error(function () {alert("Failed to publish"); });

launch an excel file from a Controller using JavaScript

What do I need to do to open an excel file via controller action using javascript?
I tried the this way but it does not open the file.
JavaScript Function:
function ExcelExport() {
var link = '/Report/ExcelExportData';
$.ajax({
type: 'POST',
url: link,
success: function (result) {
},
error: function (result) {
}
});
};
Controller Action:
public ActionResult ExcelExportData()
{
return File("~/Reports/ExcelFile.xlsm", Server.UrlEncode("~/Reports/ExcelFile.xlsm"));
}
Actually, you can't open files directly from ajax callback responses. You could try two different approaches:
Use an anchor for opening the file and get rid of the ajax request. Something like <a href="/Report/ExcelExportData"> will do.
Call window.open(link) inside your success callback. The only advantage of this approach is that it allows you to handle unexpected errors (file not found or something like that). It will perform another roundtrip to the server, though.

Getting a downloadable file with an ajax request

Edit: Not sure why this was marked as a duplicate given that the original doesn't even really have an answer other than "use this third party tool that adds extra interface stuff that you probably don't want or need". The reason I was using ajax is because I need to send an array of ids and I'm not sure how to do it other than with ajax. I figured out what I need to do, so I don't really need any more help from this post, but this definitely isn't a duplicate question, and even if it were, there isn't a real answer to the original.
I've been trying to get a link that will download a file generated by my export script. However, I can't get it to get the returned file. This is the JS function I've been using...
function sendSelected(path) {
var ids;
ids = jQuery("#grid").jqGrid('getGridParam', 'selarrrow');
if (ids.length > 0) {
alert("");
$.ajax({
url: path,
data: { ids: ids },
type: "POST",
traditional: true,
});
} else {
alert("You have not selected any rows.");
return false;
}
}
and then here's the HTML portion...
<input type="submit" name="command" value="Export" />
<script type="text/javascript">
jQuery("#export").click(function () { sendSelected("/Forms/Export"); });
</script>
This all works fine, except my exporter ends with document.Save(response, "file.pdf"); and the page isn't getting this back. If I change it to document.Save(response, #"C:\some\location\to\save\at.pdf"); the file is created there, so I know it's not a problem creating the file. Also, if I just create a standard form that points to /Forms/Export and then manually enter the ids, I can download the file fine, but that doesn't work for my implementation.
$.ajax will not work, i was attempting something similar recently but ended up with different solution. Simply have a form with hidden input and then in your sendSelected set the field and action and then submit form.
$("#hiddenField").val(data);
$("#yourForm").attr("action", path)
$("#yourForm").submit();

How the form data is converted to a model in C# .Net MVC3 , entity framework?

I have a code like below
View:
$("form").live('submit', function () {
var formData = $(this).toObject();
$.ajax({
url: "../Home/Index",
type: "POST",
dataType: "json",
data: formData,
success: function (data) {<<Some handling>>
}
Controller:
public JsonResult Index(Task task)
{
//operations on the task object like getting data from task and setting to it.
}
Task is a model here.
Here when the form is submitted, the form object is directly sent to the controller and the controller is receiving it as a model.
How this conversion takes place? I have added a file component to the form now
<input type="file" name = "file" id="file"/>
and added the file attribute to model Task.
public HttpPostedFileBase file{ get; set; }
But I am getting null for the file in the controller. But all other values are coming well.
Please help me out. Please let me know if you need any additional info to understand my question correctly.
Normally it's the model binder that is responsible for converting the request values into a model.
But in your case you seem to be attempting to send a file using AJAX. This is not supported. The reason for that is because jQuery's ajax method doesn't support that. You could use HTML5 File API if the client browser supports it because the XHR2 object allows you to asynchronously upload files to the server. Here's an example:
$(document).on('submit', 'form', function () {
var xhr = new XMLHttpRequest();
xhr.open(this.method, this.action);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
alert(xhr.responseText); // handle response.
}
};
xhr.send(new FormData(this));
return false;
}
Also notice that I have used the .on() method to subscribe to the submit event instead of .live() which is obsolete and has been removed in jQuery 1.9.
If on the other hand you need to support legacy browsers you could use a plugin such as Fine Uploader or jQuery form to achieve this task. What those plugins do is detect the capabilities of your browser and if it supports XHR2 it will use it, and if it doesn't it will use a different technique (such as hidden iframes, flash, ...).
You can not file upload using jquery ajax post directly. You should you some plug-in for this.
May be you can use this plug-in
This question will show you a start point for using this plug in.
Also, I learned it from #DarinDimitov suggestions, too :)

Ajax post web service url error

I am trying posting a data to a web service. And this service in a different project in same solution.
This project name is WebServices and web service's name is HastaTahlilUyariService.asmx.
My code is here:
$.ajax(
{
type: "POST",
url: "WebServices/HastaTahlilUyariService.asmx/f_HastaninAktarilacakAlislabTestleri",
data: "{_sTcKimlikNo:" + Cell.innerHTML + ",_iKlinikKodu:18001,_bAy:12,_iYil:2009}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(msg) {
alert(msg);
},
error: function(msg) {
alert( 'hata'+ msg);
}
}
);
I think my url is wrong. How can i give correct url.
Thanks in advance...
You might want to change your url to something that isn't relative to where you are right now, such as url: '/WebServices/... (initial slash...)
Using the firebug addon for firefox, you can inspect the AJAX callback and see what exact URL is being requested. You can copy that URL, and you should be able to point your browser to the URL of the asmx (i.e. without the last parameter, which is the method name).
Other than that, you need to make sure you've uncommented the ScriptService attribute in the top few lines of the asmx code file. It is commented out by default, but it needs to be there to allow jQuery to access the webservice.
First of all: build your webservice, and configure it to run under something like http://localhost/services/myservice.asmx in IIS Configuration Manager. Open IIS Manager, rightclick on website -> New Virtual Directory; and navigate to the folder where your webservice is located. Name the virtual directory then services.
Then call the service with it's fully qualified url like http://localhost/myservice.asmx/function.
The most easy way to do what you are trying to do (well, I guess)
Create the method you want to call in your codebehind like
[WebMethod]
public static object MethodToCallFromAjax(string argument)
{
//do something
return result;
}
Then add a ScriptManager to your aspx page; and set enablePageMethods=true. Then call your method from JavaScript like:
PageMethods.MethodToCallFromAjax("argument value", function(msg) { alert(msg); });
edit: removed some stuff about json and asmx that wasn't true :-)
Another option to look into is the standard XMLHttpRequest object that is built into the browser (for IE 6 you have to use the ActiveX object with the same name). It makes calling XML services pretty easy, although you end up having to some of the SOAP formatting yourself.
Wikipedia entry for XMLHttpRequest

Categories

Resources