Download a file through ajax request in asp.net MVC - javascript

I am trying to download file through ajax call in asp.net
my javascript:
var allData = dataSource.data();
var query = new kendo.data.Query(allData);
var data = query.filter(filters).data;
var strAccountCodes = '';
for (var i = 0; i < data.length; i++) {
strAccountCodes += data[i].AccountCode + ",";
}
$.ajax({
url: '#Url.Action("GetHistoricalUsageApplicationFile", "HUProducts")',
type: 'GET',
data: { "accountCodes": strAccountCodes }
});
my action method:
public ActionResult GetHistoricalUsageApplicationFile([DataSourceRequest]DataSourceRequest request, [FromBody] string accountCodes)
{
var HistoricalUsagesData = _enrollmentManagementRepository.GetHistoricalUsageApplicationFile(accountCodes);
List<HistoricalUsageApplicationFileModel> HUApplications = _mapper.MapToNew<List<HistoricalUsageApplicationFileModel>>(HistoricalUsagesData);
//var HistoricalUsageApplication = HUReport.ToDataSourceResult(request).Data;
var output = new MemoryStream();
var writer = new StreamWriter(output, Encoding.UTF8);
writer.Write("CommodityCode,");
writer.Write("CustomerTypeCode,");
writer.Write("EnrollmentRequestId");
writer.WriteLine();
var list = HUApplications.ConvertToString();
var single = list.Aggregate((x, y) => { return string.Concat(x, y); });
writer.WriteAsync(single);
writer.Flush();
output.Position = 0;
return File(output, System.Net.Mime.MediaTypeNames.Application.Octet, "Products.csv");
}
code is executing without any errors but it's not downloading any file.
is that anything i am missing?

You should know that AJAX call is not intended to download CSV file directly. Therefore, you can create a byte array from MemoryStream instance and store it inside Session or TempData variable, then return 'successful' state to enable redirect on AJAX success response:
public ActionResult GetHistoricalUsageApplicationFile([DataSourceRequest]DataSourceRequest request, [FromBody] string accountCodes)
{
var HistoricalUsagesData = _enrollmentManagementRepository.GetHistoricalUsageApplicationFile(accountCodes);
List<HistoricalUsageApplicationFileModel> HUApplications = _mapper.MapToNew<List<HistoricalUsageApplicationFileModel>>(HistoricalUsagesData);
//var HistoricalUsageApplication = HUReport.ToDataSourceResult(request).Data;
var output = new MemoryStream();
var writer = new StreamWriter(output, Encoding.UTF8);
writer.Write("CommodityCode,");
writer.Write("CustomerTypeCode,");
writer.Write("EnrollmentRequestId");
writer.WriteLine();
var list = HUApplications.ConvertToString();
var single = list.Aggregate((x, y) => { return string.Concat(x, y); });
writer.WriteAsync(single);
writer.Flush();
output.Position = 0;
// creates byte array from stream
TempData["Output"] = output.ToArray();
// returns successful state
return Json("Success", JsonRequestBehavior.AllowGet);
}
Second, create a controller action with GET method and pass stored byte array from Session or TempData into FileResult:
public ActionResult DownloadCSV()
{
// retrieve byte array here
var array = TempData["Output"] as byte[];
if (array != null)
{
return File(array, System.Net.Mime.MediaTypeNames.Application.Octet, "Products.csv");
}
else
{
return new EmptyResult();
}
}
Finally, handle success response to include location.href which will redirect to controller returning FileResult to download CSV file:
$.ajax({
url: '#Url.Action("GetHistoricalUsageApplicationFile", "HUProducts")',
type: 'GET',
data: { "accountCodes": strAccountCodes },
success: function (result) {
if (result == "Success") {
location.href = '#Url.Action("DownloadCSV", "ControllerName")';
}
}
});
As an option, you could pass CSV file name as parameter from AJAX response using query string.
Related issue:
Creating a byte array from a stream

Related

How to fix Ajax call "The parameters dictionary contains a null entry........."

I'm trying to send my data via ajax call to the controller but I check all my code I debug it all values are filled but it continuously shows me this error. event its also show me ON MVC call As Well
The parameters dictionary contains a null entry for parameter 'BrandId' of non-nullable type 'System.Int32' for method 'System.Web.Mvc.ActionResult Forms(System.Collections.Generic.IEnumerable1[System.Web.HttpPostedFileBase], System.String, Int32, Int32, Boolean, Int32)'in'AdminDevVersion.Controllers.HomeController'`. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter.
Parameter name: parameters
i have already debugged the code and I have checked if all the values are filled.
My Ajax Code
function uploadSubmitHandler() {
var PName = $("#ProductName").val();
var Category = $("#CategoryDropDown").val();
var Brand = $("#BrandDropDown").val();
var SubCategory = $("#SubCategory").val();
var ProductDescription = $('textarea.textarea-editor').val();
var NewOROldRadio = $("input[name='ProductStatus']:checked").val();
if (state.fileBatch.length !== 0) {
var data = new FormData();
for (var i = 0; i < state.fileBatch.length; i++) {
data.append('files', state.fileBatch[i].file, state.fileBatch[i].fileName);
}
data.append('ProductName', PName);
data.append('CategoryId', Category);
data.append('BrandId', Brand);
data.append('IsNewStatus', NewOROldRadio);
data.append('SubCategoryId', SubCategory);
data.append('Description', ProductDescription);
$.ajax({
type: 'POST',
url: options.ajaxUrl,
data: data,
cache: false,
contentType: false,
processData: false
});
}
}
Controller Code
[HttpPost]
public ActionResult Forms(IEnumerable<HttpPostedFileBase> files, String ProductName, int CategoryId, int BrandId, bool IsNewStatus, int SubCategoryId)
{
List<string> FileNames = new List<string>();
string ImageName = null;
TblProduct InsertProduct = new TblProduct();
if (ModelState.IsValid == true)
{
InsertProduct.Name = ProductName;
InsertProduct.IsActive = IsNewStatus;
InsertProduct.BrdId = BrandId;
InsertProduct.CatId = SubCategoryId;
InsertProduct.Image = ImageName;
InsertProduct.Created = DateTime.Now;
InsertProduct.IsActive = true;
_RepoProduct.Insert(InsertProduct);
_RepoProduct.Save();
TblProRelImg RelatedImages = new TblProRelImg();
foreach (HttpPostedFileBase file in files)
{
string _path = System.IO.Path.Combine(Server.MapPath("~/Content/Images/"), file.FileName);
file.SaveAs(_path);
if (file == files.First())
{
ImageName = file.FileName.ToString();
}
else
{
RelatedImages.PrdID = InsertProduct.ID;
RelatedImages.Image = file.FileName;
_ReporRelatedImages.Insert(RelatedImages);
_ReporRelatedImages.Save();
}
FileNames.Add(file.FileName);
}
ViewBag.CategoryId = Logics.Category();
ViewBag.BrandInfo = new SelectList(DbContext.TblBrands, "Id", "Name");
}
return View();
}
I have expected to send data to the controller
parse your BrandId to int like blow and append to your data
parseInt(Brand)

How to iterate json string which holds array of object in controller

I have converted array of object into json string in jsp as follows
$("#submitButton").click(function(){
var sample = new Array();
var k = 1;
for(var i=0; i < JSONObj.length; i++){
var remarkString = $("#eduRemark"+k).val();
var scoreNum = $("#eduScore"+k).val();
var objectInfo = {"iqrQuestionRemark":remarkString, "iqrQuestionScore":scoreNum,"crtnByUmId":""};
sample.push(objectInfo);
k++;
}
var ArrayData = JSON.stringify(sample);
alert("Json Data:"+ArrayData);
$.ajax({
type: "POST",
contentType : 'application/json; charset=utf-8',
dataType : 'json',
url: "/Vidyasaarathi/ipusers/submitAssessmentform",
data: ArrayData,
success :function(result) {
}
});
});
The ajax call works fine. At controller side i'm getting list of object as String. in following format
[{"iqrQuestionRemark":"nitin","iqrQuestionScore":"10","crtnByUmId":""},{"iqrQuestionRemark":"akash","iqrQuestionScore":"12","crtnByUmId":""},{"iqrQuestionRemark":"sharad","iqrQuestionScore":"14","crtnByUmId":""}]
Now my question is how to iterate this array of object individually at controller side.
Here is my controller code
#RequestMapping(value={VspCommonConstants.INTERVIEW_PANEL_MANAGER_URL+"/submitAssessmentform"}, method = RequestMethod.POST)
public String submitAssessmentform(#RequestBody List<InterviewQuestionResult> ArrayData,HttpServletRequest request,Model model) throws JsonParseException, JsonMappingException, IOException
{
ObjectMapper mapper = new ObjectMapper();
//String [] actualData = mapper.readValue(ArrayData, String[].class);
//System.out.println("Json converted Data:"+actualData);
System.out.println("Result object:"+ArrayData);
String view = null;
try {
view = "ipsearchForm";
} catch (Exception e) {
model.addAttribute("errormsg", "System is busy...... Please try after some time.");
}
return view;
}
Please suggest some possible way. Here i'm trying to assign json string to 'InterviewQuestionResult' bean which has a getter setter. Thanks in advance.

Ajax call to webmethod gives ERROR 500

I'm a beginner and I want to use ajax to load some data from database to dropdownlist when another dropdownlist selected index in changed
but I'm getting nothing but 500 error
My jquery ajax code
function ddlGroups() {
var s = $("#Content_ddlGroups").find("option:selected").prop("value");
$.ajax({
method: "GET",
contentType: "application/json; charset=utf-8",
//url is the path of our web method (Page name/function name)
url: "../panels/admin/AddProject.aspx/getSubgroups",
data: { Id: s },
dataType: "json",
//called on jquery ajax call success
success: function (result) {
$('#Content_SubGroups').empty();
$.each(result.d, function (key, value) {
$("#Content_ddlGroups").append($("<option></option>").val(value.GroupID).html(value.Title));
});
},
//called on jquery ajax call failure
error: function ajaxError(result) {
alert(result.status + ' : ' + result.statusText);
}
});
};
and my c# code
[WebMethod]
[ScriptMethod(UseHttpGet = true)]
public static List<Group> getSubgroups(string Id)
{
DataTable dt = new DataTable();
List<Group> objDept = new List<Group>();
GroupsRepository jg = new GroupsRepository();
//Page page = (Page)HttpContext.Current.Handler;
//DropDownList DDLGroups = (DropDownList)page.FindControl("DDLGroups");
dt = jg.LoadSubGroup(Id.ToInt());
if (dt.Rows.Count > 0)
{
for (int i = 0; i < dt.Rows.Count; i++)
{
objDept.Add(new Group
{
GroupID = Convert.ToInt32(dt.Rows[i][0]),
Title = dt.Rows[i][1].ToString(),
});
}
}
return objDept;
}
What is the problem??
The jQuery is not the problem here. The 500 error is thrown by the server, so you should review the log of your c# code to find out the details about it and be able to narrow the causes.
In your AJAX Call actually 500 error caused beacuse you have passed
Id:s instead of Id having some digits. Ex. Id : 5.
I see your code if you passed string as a id so in your server side method
you are trying to convert that string to int.That actually causes the 500 error.
[WebMethod]
[ScriptMethod(UseHttpGet = true)]
public static List<Group> getSubgroups(string Id)
{
DataTable dt = new DataTable();
List<Group> objDept = new List<Group>();
GroupsRepository jg = new GroupsRepository();
//Page page = (Page)HttpContext.Current.Handler;
//DropDownList DDLGroups = (DropDownList)page.FindControl("DDLGroups");
dt = jg.LoadSubGroup(Id.ToInt()); // Here You have convert string to Int that's why you got 500 Error.
if (dt.Rows.Count > 0)
{
for (int i = 0; i < dt.Rows.Count; i++)
{
objDept.Add(new Group
{
GroupID = Convert.ToInt32(dt.Rows[i][0]),
Title = dt.Rows[i][1].ToString(),
});
}
}
return objDept;
}

AJAX call to async method is success, but data returned is undefined

I have a controller, and when I Debug.WriteLine the data which I'm returning it's exactly like it's supposed to be. I'm very new to async in .NET, but it seems something gets lost between the controller and the view, because the AJAX call is a success, but the data which I'm returning is undefined when I try to work with it.
Below is the method in the controller. Here the data is correct, and as far as I know this method works exactly as it should.
[HttpPost]
public async Task<JsonResult> getServerProcesses(string server)
{
HttpClient client = new HttpClient();
QueryPair<JToken, JToken> processes = new QueryPair<JToken, JToken>();
using (client)
{
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var processesRequest = ProcessURLAsync(baseUrl + "activityMonitor/" + server + "/processes", client);
HttpResponseMessage response = await processesRequest;
var jsonString = response.Content.ReadAsStringAsync().Result;
JObject json = JObject.Parse(jsonString);
var data = json.SelectToken("Processes" + ".Data");
var columns = json.SelectToken("Processes" + ".Columns");
processes.Data = data;
processes.Columns = columns;
Debug.WriteLine(data);
}
return Json(processes);
}
As you can see I use an alert to confirm the success, but when I try something such as getting the length it says it's undefined. Even when I just try to console.log the object it says it's undefined.
$.ajax({
type: 'POST',
url: '/Home/getServerProcesses',
data: {'server': server},
success: function(data) {
console.log("Length: " + data.length);
alert("oui");
$('#server-name').empty();
$('#server-name').append(server);
var dataTable = new google.visualization.DataTable();
for (var i = 0; i < pmdfields.length; i++) dataTable.addColumn('string', pmdfields[i]);
for (var i = 0; i < data.length; i++) dataTable.addRow(data[i]);
var table = new google.visualization.Table(document.getElementById('processTable'));
table.draw(dataTable, {showRowNumber: true, width: '100%', height: '100%'});
},
error: function(data) {
alert('ajax getServerProcesses POST request error');
}
});
From API. Under response it has an empty JSON object full of empty arrays. I suspect the error is in my controller class:

Open a PDF file in AJAX POST

I am doing ajax POST as:
$.ajax({
type: 'POST',
url: rootUrl("Home/PrintInvoice/12"),
success: function (result) {
$("#TestInvoicePrint").empty();
$("#TestInvoicePrint").html(result);
window.open(result);
}
});
Where I am getting PDF file in result from MVC action as,
public ActionResult PrintInvoice(long ID)
{
var data = db.Documents.Where(x => x.InvoiceNumber == ID);
ReportDocument rd = new ReportDocument();
rd.Load(Server.MapPath("~/Reports/InvoiceDocument.rpt"));
ConnectionInfo ConnInfo = new ConnectionInfo { ServerName = "10.0.0.154,1433\\sqlexpress", UserID = "CueReader", Password = "CueReader#123", DatabaseName = "Cue" };
ParameterFieldDefinitions parmFields = rd.DataDefinition.ParameterFields;
ParameterValues pvals = new ParameterValues();
rd.ParameterFields["DocumentID"].CurrentValues.IsNoValue = true;
Stream stream = rd.ExportToStream(CrystalDecisions.Shared.ExportFormatType.PortableDocFormat);
stream.Seek(0, SeekOrigin.Begin);
return new FileStreamResult(stream, "application/pdf");
}
How can I use the PDF file into my DOM Element from ajax POST?
it would be better if you could have the ajax give you a url (dynamic?) and then update an object data= attribute

Categories

Resources