C# Razor Upload File - c#

I am using cshtml as view
this is my input:
#Html.TextArea("DESCRIPTION", null, new { #class = "field-longtext", #cols = 100, #rows = 5, maxlength = 255 })
#Html.TextBox("DOC_TYPE", null, new { #class = "field-longtext", maxlength = 10 })
#Html.TextBox("DOC_FILE", null, new { #class = "field-longtext", #type = "file" })
and using ajax post
function UploadFile() {
var url = '#Url.Action("CreateUploadFile")';
var data = {};
var result = false;
$('##ViewBag.FormName').find('input, textarea').each(function () {
data[$(this).attr('name')] = $(this).val();
});
data.PROBLEM_CALL_ID = #Model.Model.PROBLEM_CALL_ID;
$.ajax({
type: 'POST',
url: url,
data: data,
async: false,
success: function (data) {
if (data.result) {
var selectedRow = SubFormService.tableList['##ViewBag.TableName'].selectedRow;
result = true;
} else {
alert(data.errorMsg);
result = false;
}
}
});
return result;
}
My Controller:
[HttpPost]
public ActionResult CreateUploadFile(Models.Shared.DocumentModel vm)
{
var id = -1;
var result = string.Empty;
var json = new BasicJsonResult();
var file = vm.DOC_FILE;
LogUtility.Debug(file.ContentLength.ToString());
if (file != null && file.ContentLength > 0)
{
var fileName = Path.GetFileName(file.FileName);
LogUtility.Debug(fileName);
LogUtility.Debug(Server.MapPath("~/Images/"));
var path = Path.Combine(Server.MapPath("~/Images/"), fileName);
file.SaveAs(path);
}
return Json(json, JsonRequestBehavior.AllowGet);
}
the code var file = vm.DOC_FILE; warns me (Object reference not set to an instance of an object.), but I can get another control value (vm.DESCRIPTION, vm.DOC_TYPE).
Please help.
Also, I want to download file when that file is uploaded.

With the introduction of XHR2 it is now possible to upload files using AJAX. You could use FormData to achieve this. Assuming that your input elements are inside a <form> you may try this (also include in this form a hidden input for the PROBLEM_CALL_ID field so that it gets sent to the server):
function UploadFile() {
var url = '#Url.Action("CreateUploadFile")';
var formData = new FormData($('form')[0]);
var result = false;
$.ajax({
type: 'POST',
url: url,
data: formData,
async: false,
success: function (data) {
...
}
});
return result;
}
So just make sure that you have wrapped your input elements inside a form tag (preferably with an id so that you can more specifically select it):
<form id="myForm">
#Html.TextArea("DESCRIPTION", null, new { #class = "field-longtext", #cols = 100, #rows = 5, maxlength = 255 })
#Html.TextBox("DOC_TYPE", null, new { #class = "field-longtext", maxlength = 10 })
#Html.TextBox("DOC_FILE", null, new { #class = "field-longtext", #type = "file" })
#Html.HiddenFor(x => x.PROBLEM_CALL_ID)
</form>
and then select the form like this:
var formData = new FormData($('#myForm')[0]);
Also please, please, please don't do that:
async: false
By doing this you are defeating the whole purpose of an asynchronous call to the server. If you set this flag the browser will freeze during the file upload which is an absolutely horrible user experience. If you do this, then you'd better use a normal HTML form submit to upload the file - you are loosing all the benefits of AJAX and there's no point to be making an AJAX request with this flag set to true.

If you want to able upload a file using ajax, you should use iframe.
<iframe name="upload-data" id="upload-data" frameborder="0" width="0" height="0"></iframe>
<form id="frm-add-update" enctype="multipart/form-data" method="post" target="upload-data">
// HTML Code
</form>
In my case, my Controller would return a code, "0x001" if the upload process successful, otherwise it will return "0x00".
When document is ready
$("#upload-data").hide();
$("#upload-data").load(function () {
var data = $.parseJSON($("#upload-data").contents().text());
if (data != null) {
if (data.code != "0x001") {
// you got a problem
}
else {
// you got no problem
}
}
});
In Controller
[Authorize, HttpPost]
private JsonResult ActionNAme(ModelClass modelObj, HttpPostedFileBase htmlFileTagName)
{
string code = "0x001";
string message = "";
try
{
// your process here
}
catch(Exception)
{
code = "0x000";
message = ex.Message;
}
return new JsonResult()
{
Data = new
{
code = code,
message = message
}
};
}
For downloading the uploaded file, i think you should change the Action return type. You will get the information from this link.
Hope it can solve your problem :)

Related

How to access viewbag value in AJAX success?

Here I EditMyProfile method which is used to edit the customer detail.
In this method I am trying to set ViewBag.msg = 1 and return return PartialView("MyProfile", getCusomerDetail);, set ViewBag.msg = 0; and return return PartialView("EditMyProfile", customer); and using that ViewBag.msg value want put condition on AJAX success whether to show success message or not.
Now, the problem is that even though the ViewBag.msg has value in EditMyProfile view, the var message = '#ViewBag.msg' gives var message = "" in AJAX success.Any help with my code will be a great help
Thank you
Below is my AJAX
<script>
$(document).ready(function () {
$("#EditMyProfileCreate").submit(function (ev) {
debugger;
ev.stopImmediatePropagation();
var Action = $(this).attr('action');
var formData = new FormData($(this)[0]);
$.ajax({
url: Action,
type: 'POST',
data: formData,
async: false,
success: function (data) {
debugger
var message = '#ViewBag.msg'; // Here the var message = "" even though #ViewBag.msg' has value
if (message == "1") {
swal("Congratulations!", "Chages saved successfully", "success");
$("section#myAccountMainDiv").html(data);
}
else {
$("section#myAccountMainDiv").html(data);
}
},
cache: false,
contentType: false,
processData: false
});
return false;
});
})
Below is my
[HttpPost]
public ActionResult EditMyProfile(CustomerVM customer)
{
if (ModelState.IsValid)
{
using (emedicineEntities _db = new emedicineEntities())
{
var getCustomer = _db.Customers.Where(x => x.CustomerId == customer.CustomerId).FirstOrDefault();
getCustomer.CustomerName = customer.CustomerName;
getCustomer.CustomerPhoneNumber = customer.CustomerPhoneNumber;
getCustomer.CustomerEmail = customer.CustomerEmail;
getCustomer.CustomerAddress = customer.CustomerAddress;
getCustomer.ConfirmPassword = getCustomer.PasswordHash;
_db.Entry(getCustomer).State = EntityState.Modified;
_db.SaveChanges();
ViewBag.msg = 1; // here ViewBag.msg is set 1 on successfull edit
var getId = Global.CustomerId;
var getCusomerDetail = _db.Customers.Where(x => x.CustomerId == getId).FirstOrDefault();
return PartialView("MyProfile", getCusomerDetail);
}
}
else
{
ViewBag.msg = 0; // here ViewBag.msg is set 0 when model is invalid
return PartialView("EditMyProfile", customer);
}
}
To Access ViewBag dictionary in javascript, your Javascript code block must be on the cshtml file and not in the external javascript file.
In Controlller
public ActionResult Index()
{
ViewBag.Data = "haha";
return View();
}
In cshtml file
<script>
$(document).ready(function () {
alert('#ViewBag.Data');
});
</script>
As you are calling your controller through an Ajax call, you need to return the data as a variable inside your partial view. What i would suggest is to create a hidden field inside your partial view's cshtml file and assign that the value of ViewBag property at compile time. Then inside success function get the value of hidden field and compare.

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

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

C# Razor WebAPI Upload File with AJAX 400 Error

I'm trying to make use of the answer provided here:
Upload File Using WebAPI Ajax
But I keep receiving a 400 (Bad Request) error.
I've been submitting a pdf file but I keep receiving this error...
What am I doing wrong?
(FYI I'm not using MVC)
My code:
CSHTML (using Razor Syntax)
#{
Layout = "~/_SiteLayout.cshtml";
}
<label>Enter File</label>
<input type="file" name="UploadFile" id="datasheet_uploadfile" class="" accept="application/pdf"/>
<script>
$(document).ready(function() {
$('#datasheet_uploadfile').change(function() {
var data = new FormData();
var file = this.files;
data.append('file', file);
$.ajax({
url: '/api/file',
processData: false,
contentType: false,
data: data,
type: 'POST'
}).done(function(result) {
alert(result);
}).fail(function(a, b, c) {
console.log(a, b, c);
});
});
});
</script>
My WebAPI Controller
FileController.cs
public class FileController : ApiController
{
// POST api/<controller>
public HttpResponseMessage Post()
{
HttpResponseMessage result = null;
var httpRequest = HttpContext.Current.Request;
if (httpRequest.Files.Count > 0)
{
var docfiles = new List<string>();
foreach (string file in httpRequest.Files)
{
var postedFile = httpRequest.Files[file];
int hasheddate = DateTime.Now.GetHashCode();
//Good to use an updated name always, since many can use the same file name to upload.
string changed_name = hasheddate.ToString() + "_" + postedFile.FileName;
var filePath = HttpContext.Current.Server.MapPath("~/Content/stuff/" + changed_name);
postedFile.SaveAs(filePath); // save the file to a folder "Images" in the root of your app
changed_name = #"~\Content\stuff\" + changed_name; //store this complete path to database
docfiles.Add(changed_name);
}
result = Request.CreateResponse(HttpStatusCode.Created, docfiles);
}
else
{
result = Request.CreateResponse(HttpStatusCode.BadRequest);
}
return result;
}
}
Use the below code to upload files
$(document).ready(function () {
$('#datasheet_uploadfile').change(function () {
var data = new FormData();
data.append("file", this.files[0]);

Passing in HttpPostedFileBase and FormCollection from Ajax

I'm currently working on a project where the previous contractor had an attachments area within our site. The piece works for the most part but has issues when redirecting back after uploading the file, plus I don't like the fact the page does a full page reload just to update a grid to show the uploaded file.
My goal is to instead do an Ajax call for the upload versus form submit. I have added this in, however, the return forces a download of the Json object (using IE 11). I have researched how to get around this and have yet to find any substantial ways around it.
Is it possible to upload a file using Ajax and not send back a download of the Json object?
Below is my code.
View (Upload.cshtml)
#using (Html.BeginForm("Upload", "PM", FormMethod.Post, new { enctype = "multipart/form-data", id = "frmUpload" }))
{
#Html.ValidationSummary(true)
<table>
...
<tr>
<td>#Html.Label("File: ")</td>
<td>
<input type="file" name="file" id="file"/>
#Html.ValidationMessage("file","File is required")
</td>
</tr>
...
<tr>
<td colspan="2">
<p>
<button type="submit" class="t-button" id="btnSubmit">
Attach</button>
<button type="button" class="t-button" onclick="CloseAttachmentWindow()">
Cancel</button>
</p>
</td>
</tr>
</table>
}
<script type="text/javascript">
$(document).ready(function () {
$("#btnSubmit").click(function (e) {
e.preventDefault();
if (!$('form').valid())
return false;
//Upload document
$.ajax({
type: "POST",
cache: false,
url: "/PM/Upload",
dataType: "json",
contentType: false,
processData: false,
data: $('form').serialize(),
success: function (result) {
if (result.success) {
var window = $("#error").data("tWindow");
window.content("<b>Attachment successfully added</b>").title("Success!");
window.center().open();
CloseAttachmentWindow();
}
else {
var window = $("#error").data("tWindow");
window.content("<b>Error: Unable to Upload Document. Please try again. "
+ "If this fails, contact the administrators with the below details.</b>"
+ '\n' + '\n' + result.Error).title("Error");
window.center().open();
}
},
error: function (xhtr, e, e2) {
var window = $("#error").data("tWindow");
window.content(e + '\n' + xhtr.responseText, 'error', '');
window.center().open();
}
});
});
});
</script>
PMController.cs
[HttpPost]
public ActionResult Upload(HttpPostedFileBase file, FormCollection formcollection)
{
if (file != null)
{
var cntPOC = int.Parse(Session["cntPOC"].ToString());
try
{
var cntFileType = _fileTypeRepo.GetCntFileTypeByMimeType(file.ContentType);
if (cntFileType == 0)
throw new Exception("This file type is not supported");
var strAttachmentName = formcollection["AttachmentName"];
var strAttachmentType = formcollection["AttachmentType"];
var length = file.ContentLength;
var tmpFile = new byte[length];
if (tmpFile.Count() > 0)
{
file.InputStream.Read(tmpFile, 0, length);
var intAttchmentId = _AttachRepo.GetNextAttachmentId() + 1;
var objAttachment = new TBLATTACHMENT
{
CNTATTACHMENT = intAttchmentId,
CNTPOC = cntPOC,
CNTFILETYPE = cntFileType,
CNTATTACHMENTTYPE = Convert.ToDecimal(strAttachmentType),
DTMCREATED = DateTime.Now,
STRATTACHMENTTITLE = strAttachmentName,
BLBATTACHMENT = tmpFile,
STRORIGINALFILENAME = file.FileName,
YSNDELETED = 0
};
_AttachRepo.Add(objAttachment);
_AttachRepo.Save();
return Json(new { success = true, Error = "" });
}
//File not real
else
return Json(new { success = false, Error = "Please select appropriate file" });
}
catch (Exception ex)
{
logger.LogError("File Upload", ex);
if (ex.InnerException != null)
ModelState.AddModelError("Error", ex.InnerException.ToString());
else
ModelState.AddModelError("Error", ex.Message.ToString());
TempData["ModelState"] = ModelState;
return Json(new { success = false, Error = ex.Message });
}
}
else
{
logger.LogError("File Upload Error. File was not selected");
ModelState.AddModelError("Error", "Please select file");
TempData["ModelState"] = ModelState;
return Json(new { success = false, Error = "File was not selected" });
}
}
As is, using this code, I can upload documents, however, I get the prompt to download the Json object upon return.
NOTE Long story short, you cannot do this. I had to learn the hard way and never did find a solution. I did find a way to do it for downloads, but not uploads.
Options:
Remove change the button type submit to button <input type="button"/>
<input type="submit" onclick="return false">
return false; or add event handlers
$("input[type='submit']").click(function() { return false; });
or
$("form").submit(function() { return false; });
<form onsubmit="return false"> ...</form>
in order to avoid refresh at all "buttons", even with onclick assigned.
changing the submit type to button is the optimal one.

Adding image to AngularJS model for upload

I am new to this wonderful framework AngularJS. I have a C# API controller where I would like to upload data from a form that includes an image. Normally (razor) I would upload a form as json and include the image as a HttpPostedFileBase:
public ArtWork SaveArtWork(ArtWork artWork, HttpPostedFileBase file)
{ // save in db and return object }
I have found a lot of different ways for uploading the file wrapped in a FormData object ([AngularJS Uploading An Image With ng-upload):
$scope.uploadFile = function(files) {
var fd = new FormData();
//Take the first selected file
fd.append("file", files[0]);
$http.post(uploadUrl, fd, {
withCredentials: true,
headers: {'Content-Type': undefined },
transformRequest: angular.identity
}).success( ...all right!... ).error( ..damn!... );
};
But I have some other properties I have parsed to a json object, and now I would like to upload it all in a bundle. Or is it possible to get the image data as a base64 and add it to my json object? I know that a base64 is 1/3 bigger than a byte stream, but it's so easy to work with :)
Here's my Angular Controller:
'use strict';
(function () {
// Factory
angular.module('umbraco').factory('artworkResource', function ($http) {
return {
getById: function (id) {
return $http.get("backoffice/Trapholt/ArtWorkApi/GetById/" + id);
},
save: function (artwork) {
return $http.post("backoffice/Trapholt/ArtWorkApi/SaveArtWork", angular.toJson(artwork));
},
save2: function (artwork, fd) {
return $http.post("backoffice/Trapholt/ArtWorkApi/SaveArtWork", angular.toJson(artwork), fd);
}
};
});
// Controller
function artworkController($scope, $routeParams, artworkResource, $http) {
$scope.categories = ['Keramik', 'Maleri', 'Møbel', 'Skulptur'];
artworkResource.getById($routeParams.id).then(function (response) {
$scope.curatorSubject = response.data;
});
var fd;
$scope.uploadFile = function(files) {
fd = new FormData();
fd.append("file", files[0]);
};
$scope.save = function (artwork) {
artworkResource.save(artwork, fd).then(function (response) {
$scope.artwork = response.data;
alert("Success", artwork.Title + " er gemt");
});
};
};
//register the controller
angular.module("umbraco").controller('ArtworkTree.EditController', artworkController);
})();
So how can I combine my image and the other properties in one json object or two arguments? Please leave a comment if I need to explain some more, any help would really be appreciated :)
I found a solution, where I added the file and the model to the form data. So it was actually pretty easy to expand solution from here. This is my Angular controller:
function artworkController($scope, $routeParams, artworkResource, $http) {
$scope.categories = ['Keramik', 'Maleri', 'Møbel', 'Skulptur'];
artworkResource.getById($routeParams.id).then(function (response) {
$scope.curatorSubject = response.data;
});
var fd;
$scope.uploadFile = function(files) {
fd = new FormData();
fd.append("file", files[0]);
};
$scope.save = function (artwork) {
fd.append("ArtWork", angular.toJson(artwork));
$http.post("backoffice/Trapholt/ArtWorkApi/Post", fd, {
transformRequest: angular.identity,
headers: { 'Content-Type': undefined }
});
};
};
And this i my C# mvc API controller:
public HttpResponseMessage Post()
{
HttpResponseMessage result = null;
var httpRequest = HttpContext.Current.Request;
if (httpRequest.Files.Count > 0)
{
var file = httpRequest.Files[0];
var artworkjson = httpRequest.Form[0];
var artwork = JsonConvert.DeserializeObject<ArtWork>(artworkjson);
if (artwork == null)
{
return Request.CreateResponse(HttpStatusCode.BadRequest, "No saved");
}
using (var binaryReader = new BinaryReader(file.InputStream))
{
artwork.Picture = binaryReader.ReadBytes(file.ContentLength);
}
result = Request.CreateResponse(HttpStatusCode.Created, "ok");
}
else
{
result = Request.CreateResponse(HttpStatusCode.BadRequest);
}
return result;
}
The html view is a normal form where all the inputs are bound with the model, expect the file input field:
<input type="file" id="file" name="picture" onchange="angular.element(this).scope().uploadFile(this.files)"/>

Categories

Resources