Read Excel Content After Uploading File in MVC And Fill Some Textboxes - c#

I'm uploading an excel file and want to read file content and with jquery ajax fill some textboxes with excel content after uploading.
the file uploading correctly but I have Problem when I want read excel content.
can anybody help me?
public JsonResult ImportExcelToTextBoxes()
{
try
{
var ExcelFile = Request.Files[0];
if (ExcelFile != null && ExcelFile.ContentLength > 0)
{
//// .xlsx
//IExcelDataReader reader = ExcelReaderFactory.CreateOpenXmlReader(ExcelFile.InputStream);
// .xls
IExcelDataReader reader = ExcelReaderFactory.CreateBinaryReader(ExcelFile.InputStream);
var result = reader.AsDataSet(new ExcelDataSetConfiguration() {
ConfigureDataTable = (_) => new ExcelDataTableConfiguration() {
UseHeaderRow = true
}
});
}
//foreach (var item in ExcelFile)
{
IList lst = new List<ET.Reservation.Classes.PassengerSaleSeat>();
ET.Reservation.Classes.PassengerSaleSeat pass = new ET.Reservation.Classes.PassengerSaleSeat();
pass.FirstName = "testtt";//this section is for test
pass.LastName = "tttttt";//this section is for test
pass.Gender = ET.Public.Enumerations.GENDER.Female;//this section is for test
lst.Add(pass);//this section is for test
}
return Json(lst);
}
catch (Exception ex)
{
Console.WriteLine(ex);
throw ex;
}
return null;
}
and js section:
$('#btnUploadExcel').click(function () {
var formData = new FormData();
formData.append('file', fileInput.files[0]);
$.ajax({
type: "POST",
url: "/PassengerSaleSeat/ImportExcelToDatabase",
data: formData,
processData: false,
contentType: false,
success: function (data) {
for (var i = 0; i < data.length; i++) {
alert(data[i].FirstName);
}
},
error: function(err) {
alert('error');
}
});
});
and input is:
<input id="fileInput" type="file">
<button type="button" id="btnUploadExcel" class="btn btn-labeled btn btn-success">Send</button>
JSON Return:
image

Related

C# Return File not working to download an Excel file

I'm trying to download a file like this with an MVC project:
Controller:
[HttpPost]
[ActionName("ExportList")]
public async Task<IActionResult> ExportList(List<object> objectList)
{
var fileName = "fileName" ".xlsx";
try
{
var fileContent = await _serviceLayer.ExportListToExcel(objectList);
return File(fileContent, "application/vnd.ms-excel", fileName);
// return new JsonResult("ok");
}
catch(Exception ex)
{
return BadRequest(ex.Message);
}
}
then my service layer:
public Task<byte[]> ExportListToExcel(List<object> objectList)
{
try
{
using(var workbook = new XLWorkbook())
{
var worksheet = workbook.Worksheets.Add("Report");
var currentRow = 1;
#region Header
worksheet.Cell(currentRow, 1).Value = "val1";
worksheet.Cell(currentRow, 2).Value = "val2";
worksheet.Cell(currentRow, 3).Value = "val3";
#endregion
#region Body
foreach(var obj in objectList)
{
currentRow++;
worksheet.Cell(currentRow, 1).Value = obj.val1;
worksheet.Cell(currentRow, 2).Value = obj.val2;
worksheet.Cell(currentRow, 3).Value = obj.val3;
}
#endregion
using(var stream = new MemoryStream())
{
workbook.SaveAs(stream);
var content = stream.ToArray();
return Task.FromResult(content);
}
}
}
catch (Exception ex)
{
throw new Exception("Error");
}
}
I call the controller method with ajax:
function exportList() {
$.ajax({
type: "POST",
url: "#Url.Action("ExportList")",
data: { objectList: objectList},
dataType: "json",
success: function (data) {
//show success message
}, error: function (req, status, error) {
//show error message
}
});
}
I read a lot of posts and this is bassically what they suggest to download the file, but instead I'm returning to the view with the following error Message and the file is not being downloaded but the controller is not throwing any kind of exception message:
Any ideas to download the file?
Try Blob responseType,
$.ajax({
type: "POST",
url: "#Url.Action("ExportList")",
data: { objectList: objectList},
xhrFields: {
responseType: 'blob' // FileContentResult will return as blob
},
success: function (data) {
const url = window.URL.createObjectURL(data); // create url from blob
const link = document.createElement('a'); // create anchor at DOM
link.href = url;
link.setAttribute('download', 'file.xlsx'); // download attribute
document.body.appendChild(link);
link.click(); // trigger click for download
},
error: function (req, status, error) {
//show error message
}
});
Hi your problem is your javascript function exportList()
it's better create a redirect on where the file is and then download it.
In your export method
That will be part of your ExportList controller method:
// Generate a new unique identifier against which the file can be stored
string handle = Guid.NewGuid().ToString();
using (MemoryStream memoryStream = new MemoryStream())
{
//save your file to memory stream
workbook.SaveAs(memoryStream);
memoryStream.Position = 0;
TempData[handle] = memoryStream.ToArray();
}
// Note we are returning a filename as well as the handle
return new JsonResult()
{
Data = new { FileGuid = handle, FileName = "exporfile.xlsx" , FileType="xlsx"}
};
your download file should look like this:
public virtual ActionResult Download(string fileGuid, string fileName, string fileType)
{
if (TempData[fileGuid] != null)
{
byte[] data = TempData[fileGuid] as byte[];
if (fileType == "xlsx" || fileType == "xls")
{
return File(data, "application/vnd.ms-excel", fileName);
}
else if (fileType == "pdf")
{
return File(data, "application/pdf", fileName);
}
else
{
//sin especificar...
return File(data, "application/octet-stream", fileName);
}
}
else
{
return new EmptyResult();
}
}
then change your exportlist method:
function exportList() {
$.ajax({
type: "POST",
url: "#Url.Action("ExportList")",
data: { objectList: objectList},
dataType: "json",
success: function (data) {
var response = JSON.parse(data);
window.location = '/YourController/Download?fileGuid=' + response.FileGuid + '&filename=' + response.FileName +'&fileType=' + response.FileType;
}, error: function (req, status, error) {
//show error message
}
});
}

Ajax call to async method returning file successfully but success/complete part of an Ajax request is not getting executed

I am trying to export selected records in to a file and reload the page to update the records in a current view. I am calling web api asynchronously to get all the records. An AJAX call is executing an action in a controller successfully and returning expected data without any error but none of the 'success', 'complete' or 'error' part of ajax function is executing. There are no errors in a developer tool of the browser, no exception, nothing unusual so its getting trickier for me to investigate this issue further. Can I request your a suggestions on this please? Thanks
View :
#Html.ActionLink("Export records", "Index", null, new { Id = "myExportLinkId")
Script :
$("a#myExportLinkId").click(function (e) {
var selected = "";
$('input#myCheckBoxList').each(function () {
if (this.checked == true) {
selected += $(this).val() + ',';
}
});
if (selected != "") {
$.ajax({
url: '/MyController/MyAction',
type: 'GET',
contentType: "application/json; charset=utf-8",
dataType: "json",
data: {
'MyString': 'stringValue'
},
success: function (data) {
alert("success");
},
error: function () {
alert("error");
}
});
})
And the action/method looks like this :
[HttpGet]
public async Task<ActionResult> ExportNewOrders(string OrderIdString)
{
//code to create and store file
//actually want to send the file details as json/jsonResult but for testing only returning
//string here
return Json( "Success", "application/json", JsonRequestBehavior.AllowGet);
}
Finally I have resolved this with Promisify functionality of an AJAX call. Obviously the json response I was returning had an issue so I have replaced
return Json( "Success", "application/json", JsonRequestBehavior.AllowGet);
to
return new JsonResult(){
Data = new { success = true, guid = handle, fileName = exportFileName },
ContentType = "application/json",
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
which has fixed the bug and the success function of ajax call got executed.
But other than this there were issues to wait until the file download (which involved encryption decryption, server validations etc) completes and then refresh the page. This I have resolved by implementing an ajax call with Promisify fuctionality. You can find codepen example here and the original post here.
Here is the complete code.
View/HTML
#Html.ActionLink("Export", "yourActionName", null, new { Id = "exportRequest", #onclick = "letMeKnowMyFileIsDownloaded();" })
Script/Ajax
function letMeKnowMyFileIsDownloaded() {
return new Promise(function (resolve, reject) {
$("a#exportRequest").on("click", function () {
$.ajax({
url: this.href + "?param=whatever params you want to pass",
dataType: "json",
data: {
'param1': 'value'
},
success: function (data) {
var a = document.createElement("a");
var url = '/yourControllerName/Download?fileGuid=' + data.guid + '&filename=' + data.fileName;//window.URL.createObjectURL(data);
a.href = url;
a.download = data.fileName;
document.body.append(a);
a.click();
a.remove();
window.URL.revokeObjectURL(url);
resolve(true);
},
error: function (error) {
reject(error);
}
});
});
});
}
letMeKnowMyFileIsDownloaded()
.then(function (bool) {
if (bool) {
//alert("File downloaded 👇");
window.location.reload(1);
}
})
.catch(function (error) {
alert("error");
});
I have used nuget package ClosedXML to handle excel file functionality. Using the stream to create and download the data in excel file without storing the file physically on the server.
And in the controller
//can be async or sync action
public async Task<ActionResult> Index(YourModel model)
{
//do stuff you want
var exportOrders = your_object;
//using DataTable as datasource
var dataSource = new DataTable();
//write your own function to convert your_object to your_dataSource_type
dataSource = FormatTypeToDataTable(exportOrders);
if (dataSource != null && dataSource.Rows.Count > 0)
{
//install ClosedXML.Excel from nuget
using (XLWorkbook wb = new XLWorkbook())
{
try
{
var handle = Guid.NewGuid().ToString();
wb.Worksheets.Add(dataSource, "anyNameForSheet");
string exportFileName = "yourFileName" + ".xlsx";
MemoryStream stream = GetStream(wb);
TempData[handle] = stream; exportFileName);
return new JsonResult()
{
Data = new { success = true, guid = handle, fileName = exportFileName },
ContentType = "application/json",
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
}
catch (Exception ex)
{
//ModelState.AddModelError("", ex.Message);
}
}
}
}
public virtual ActionResult Download(string fileGuid, string fileName)
{
if (TempData[fileGuid] != null)
{
var stream = TempData[fileGuid] as MemoryStream;
var data = stream.ToArray();
return File(data, "application/vnd.ms-excel", fileName);
}
else
{
return new EmptyResult();
}
}

Send a binary excel file data from memory stream and generic handler to client side and prompt save

Currently I am using JQuery AJAX and connect it to the Generic Handler (.ashx), inside the Generic Handler, I am doing the template for the Excel File that is going to save the computer (prompt save). i can achieve that while using the .aspx.cs , the reason I am doing from Generic Handler (.ashx), is because I don't know any way to hide the loading overlay after the dialog box for us to save to the computer is appear. (means the loading overlay just stick there). $(element).show() or $(element).hide() is to show or hide the loading overlay.
I am using EPPlus Library to generate the template for Excel File, however I don't know how to pass the object into client side and then prompt to save, it keeps gives me an error.
The problem I was encountered while using the Generic Handler is always gives me the parsererror message.
Here is the code that I am using:
JQuery AJAX:
var loading = $("#loading");
$("#template").click(function () {
loading.show();
$.ajax({
type: "POST",
url: "TemplateService.ashx?Month=" + $("#Month").val() + "&Year=" + $("#Year").val(),
data: {},
contentType: "application/json",
dataType: "json",
success: function (data) {
loading.hide();
console.log(data);
alert("Success");
},
error: function (xhr, text) {
loading.hide();
console.log(JSON.stringify(xhr.responseText));
console.log(JSON.stringify(text));
alert("There is a problem while processing your request");
}
});
});
Generic Handler (.ashx):
public class TemplateService : IHttpHandler, IRequiresSessionState
{
private int Month = 0;
private int Year = 0;
public void ProcessRequest(HttpContext context)
{
Month = Convert.ToInt32(context.Request.Params["Month"]);
Year = Convert.ToInt32(context.Request.Params["Year"]);
try
{
string MonthName = CultureInfo.CurrentCulture.DateTimeFormat.GetMonthName(Month);
string fileName = string.Format("{0} - {1} {2}.xlsx", "Excel Template", MonthName, Year);
using (var package = new ExcelPackage())
{
package.Export();
using (var stream = new MemoryStream())
{
context.Response.Clear();
context.Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
context.Response.AddHeader("Content-Disposition", string.Format("attachment; filename={0}", fileName));
package.SaveAs(stream);
stream.WriteTo(context.Response.OutputStream);
context.Response.Write(stream);
}
}
}
catch (Exception)
{
ProcessResponse(context, Response());
}
}
private string Response(bool isSuccess = false)
{
string status = (isSuccess) ? Constant.SUCCESS : Constant.FAILED;
return JsonConvert.SerializeObject(new
{
Status = status
});
}
private void ProcessResponse(HttpContext context, string response)
{
context.Response.Clear();
context.Response.ContentType = "application/json";
context.Response.Write(response);
}
public bool IsReusable
{
get
{
return false;
}
}
}
Export function:
public void Export(this ExcelPackage package)
{
try
{
package.Workbook.Worksheets.Add("Excel Template");
var workSheet = package.Workbook.Worksheets["Excel Template"];
var columnNames = new string[]
{
"First Column",
"Second Column",
"Third Column"
};
var headerRow = new List<string[]>()
{
columnNames
};
var cells = workSheet.Cells[1, 1, 1, 3];
cells.LoadFromArrays(headerRow);
cells.AutoFilter = true;
cells.AutoFitColumns();
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}
HTML:
<form>
<asp:Button ID="Submission" runat="server" OnClick="Submission_Click" Text="Upload" />
<input type="button" id="Template" value="Template" />
</form>
<script type="text/javascript">
var loading = $("#loading");
$("form").submit(function () {
loading.show();
});
$("#template").click(function () {
loading.show();
$.ajax({
type: "POST",
url: "TemplateService.ashx?Month=" + $("#Month").val() + "&Year=" + $("#Year").val(),
data: {},
contentType: "application/json",
dataType: "json",
success: function (data) {
loading.hide();
console.log(data);
alert("Success");
},
error: function (xhr, text) {
loading.hide();
console.log(JSON.stringify(xhr.responseText));
console.log(JSON.stringify(text));
alert("There is a problem while processing your request");
}
});
});
</script>
Your answer much appreciated.
Thank you.

ajax call (to send file) to call c# function not working(webmethod)

This form i want to send using ajax call with file, but it is not calling the c# function and not showing any error.
//form to submit
<form id="formfile" enctype="multipart/form-data">
<div class="modal-body">
<input type="file" id="fileupload1"/>
</div>
<div class="modal-footer">
<input type="submit" id="savefiles" class="buttonType" onclick="saveFile();return false" value="Save File" />
</div>
</form>
This ajax call is used to call c# code and also send file(.pdf)
//ajax call in .aspx file
function saveFile() {
debugger;
var file = $('input[type="file"]').val();
var exts = ['pdf', 'PDF'];
var formData = new FormData();
formData.append("imageFile", $('#fileupload1')[0].files[0]);
if (file) {
var extension = file.substring(file.lastIndexOf('.') + 1, file.length);
if ($.inArray(extension, exts) > -1)
{
//var formData = new FormData($('#form1')[0]);
var fileUpload = $('#fileupload1').get(0);
var files = fileUpload.files;
for (var i = 0; i < files.length; i++) {
formData.append(files[i].name, files[i]);
}
formData.append(fileUpload.name, fileUpload);
//alert('File Uploaded Successfully!');
}
else
{
alert('Invalid file, Only pdf files can be uploaded!!!');
}
}
//var str = "abc";
$.ajax({
url: "FileUploader.aspx/savepdfFiles",
type: "POST",
//cache: false,
contentType: false,
processData: false,
data: formData,
success: function (data) {
debugger;
},
error: function (data) {
debugger
}
});
}
It will come into success section also, but not calling following method.
//c# code
[webMethod]
public static void savepdfFiles()
{
//code
}
In ajax call it goes into success. but not calling savepdfFiles() method.
EDIT 24/08/2016
You can convert your blob data to base 64 and send it in JSON
var filesLength = 0;
function SaveFileToTemp() {
var file = $('input[type="file"]').val();
var exts = ['pdf', 'PDF'];
var pdfList = [];
// var pdfFile = { FileName: '', B64Data: '' };
if (file) {
var extension = file.substring(file.lastIndexOf('.') + 1, file.length);
if ($.inArray(extension, exts) > -1) {
var fileUpload = $('#fileupload1').get(0);
var files = fileUpload.files;
filesLength = files.length;
for (var i = 0; i < files.length; i++) {
var reader = new window.FileReader();
reader.myFileIndex = i;
reader.onloadend = function () {
base64data = reader.result;
pdfList.push({ FileName: files[this.myFileIndex].name, B64Data: base64data.substr(base64data.indexOf(',') + 1) });
console.log(base64data);
filesLength--;
if (filesLength === 0) {
$.ajax({
url: "/FileUploader.aspx/savepdfFiles",
type: "POST",
//cache: false,
contentType: "application/json; charset=utf-8",
dataType: "json",
data: JSON.stringify({ listPdf: pdfList }),
success: function (data) {
//alert('File Uploaded Successfully!');
debugger;
},
error: function (data) {
debugger
}
});
}
}
reader.readAsDataURL(files[i]);
}
}
else {
alert('Invalid file, Only pdf files can be uploaded!!!');
}
}
}
and in C#
[WebMethod]
public static void savepdfFiles(List<PdfFile> listPdf)
{
//code
foreach (var item in listPdf)
{
byte[] data = Convert.FromBase64String(item.B64Data);
System.IO.File.WriteAllBytes(string.Format("d:\\temp\\{0}",item.FileName), data) ;
}
}
this is my clas PdfFile for info
public class PdfFile
{
public string FileName { get; set; }
public string B64Data { get; set; }
}
Maybe you have to add this to your web.config to allow big json serialization :
<system.web.extensions>
<scripting>
<webServices>
<jsonSerialization maxJsonLength="10240000"/>
</webServices>
</scripting>
</system.web.extensions>
You have to set the appropiate value for maxJsonLength
Previous answer
I think I had this problem before from what i remember there is mechanism that doesn't allow you to this.
Maybe I'm wrong but I share you a link.
You will have to handle this with an ashx.
here is a built-in validation layer of protection that ASP.NET
enforces for both GET and POST based ASP.NET AJAX web methods, which
is that regardless of the HTTP verb being used, ASP.NET always
requires that the HTTP Content-Type header is set to the value
application/json. It this content type header is not sent, ASP.NET
AJAX will reject the request on the server.
I know this problem and it's easy to solve just you have to use Generic Handler.
Using generic handler with your AJAX call you can send any file to asp.net C# function.
In Generic Handler you have to write following c# code.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
namespace UploadFile
{
/// <summary>
/// Summary description for UploadFileHandler
/// </summary>
public class UploadFileHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
//context.Response.ContentType = "text/plain";
//context.Response.Write("Hello World");
if (context.Request.Files.Count > 0)
{
HttpFileCollection files = context.Request.Files;
for (int i = 0; i < files.Count; i++)
{
HttpPostedFile file = files[i];
string fname;
if (HttpContext.Current.Request.Browser.Browser.ToUpper() == "IE" || HttpContext.Current.Request.Browser.Browser.ToUpper() == "INTERNETEXPLORER")
{
string[] testfiles = file.FileName.Split(new char[] { '\\' });
fname = testfiles[testfiles.Length - 1];
}
else
{
fname = file.FileName;
}
fname = Path.Combine(context.Server.MapPath("~/Uploads/"), fname);
file.SaveAs(fname);
}
}
context.Response.ContentType = "text/plain";
context.Response.Write("File Uploaded Successfully!");
}
public bool IsReusable
{
get
{
return false;
}
}
}
}
Here is the example...
If you want Full Example Click here!

Web API to upload images with c# (code behind)

I need the c# code to upload images to my web api. (c# code that will do the same as my ajax call below)
Here is my working example that I use to upload images from my web project via ajax call.
HTML
<form>
<span>Select file(s) to upload :</span>
<input id="file1" name="file1" type="file" multiple="multiple" />
<input id="button1" type="button" value="Upload" />
</form>
ajax Call
$(document).ready(function () {
$("#button1").click(function (evt) {
var files = $("#file1").get(0).files;
if (files.length > 0) {
var data = new FormData();
for (i = 0; i < files.length; i++) {
data.append("file" + i, files[i]);
}
$.ajax({
type: "POST",
url: window.apiuri + "/api/book/UploadCover()",
contentType: false,
processData: false,
data: data,
success: function (messages) {
for (i = 0; i < messages.length; i++) {
$.smkAlert({ text: messages[i], type: 'success' });
}
},
error: function () {
$.smkAlert({ text: "Error while invoking the Web API", type: 'success' });
}
});
}
});
});
API Code in c#
public async Task<List<string>> UploadCover()
{
try
{
List<string> messages = new List<string>();
if (Request.Content.IsMimeMultipartContent())
{
string path = string.Format(#"C:\");
API.Classes.ImageUploads.MyStreamProvider streamProvider = new API.Classes.ImageUploads.MyStreamProvider(path);
await Request.Content.ReadAsMultipartAsync(streamProvider);
foreach (var file in streamProvider.FileData)
{
FileInfo fi = new FileInfo(file.LocalFileName);
try
{
messages.Add("<b>Book Cover Uploaded</b>");
}
catch (Exception ex)
{
messages.Add("<b>Upload Failed</b>");
}
}
return messages;
}
else
{
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.BadRequest, "Invalid Request!");
throw new HttpResponseException(response);
}
}
catch (Exception ex)
{
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.BadRequest, "Request Failed!");
throw new HttpResponseException(response);
}
}
Please help me with c# code to upload images to my web api. Thank you

Categories

Resources