how to correctly delete file from server - c#

I have a photo which I can upload to sever in my project and info about my photo store in database. This is how record in my database looks like:
Id:1 , Path: ~/Upload/d8cd7f97-1da2-43f3-b43a-74e5c9f28731.JPG DispayName: 9.jpg , IsMainImage:True , FurnitureId:25 .
So here is my method which delete file from server and database:
[HttpPost]
public JsonResult DeleteFile(int Id)
{
try
{
FurnitureImages furnitureImages = db.FurnitureImages.Find(Id);
if (furnitureImages == null)
{
Response.StatusCode = (int)HttpStatusCode.NotFound;
return Json(new { Result = "Error" });
}
//Remove from database
db.FurnitureImages.Remove(furnitureImages);
db.SaveChanges();
//Delete file from the file system
var path = Server.MapPath(furnitureImages.Path);
if (System.IO.File.Exists(path))
{
System.IO.File.Delete(path);
}
return Json(new { Result = "OK" });
}
catch (Exception ex)
{
return Json(new { Result = "ERROR", Message = ex.Message });
}
}
In my view I pass parametr to ajax:
<script type="text/javascript">
$('.deleteItem').click(function (e) {
e.preventDefault();
var $ctrl = $(this);
if (confirm('Do you really want to delete this file?')) {
$.ajax({
url: '#Url.Action("DeleteFile")',
type: 'POST',
data: { Id: $(this).data('Id') }
}).done(function (data) {
if (data.Result == "OK") {
$ctrl.closest('li').remove();
}
else if (data.Result.Message) {
alert(data.Result.Message);
}
}).fail(function () {
alert("There is something wrong. Please try again.");
})
}
});
</script>
And finally call this function:
#for (int i = 0; i < Model.SecondaryImages.Count; i++)
{
#Html.HiddenFor(m => m.SecondaryImages[i].Id)
#Html.HiddenFor(m => m.SecondaryImages[i].Path)
#Html.HiddenFor(m => m.SecondaryImages[i].DisplayName)
<img src="#Url.Content(Model.SecondaryImages[i].Path)" />
X
}
Model in this example is ViewModel. But it doesn't work , It writes me "There is something wrong. Please try again" , first condition If doesn't work, what's wrong? Thanks

Okay , problem was solved , my Id was null , so error was in this line
data: { Id: $(this).data('Id') }
It must be
data: { Id: $(this).attr('data-Id') }
now we get right id and image will be delete from server and file system

Related

Jqgrid upload image not passing data object to database

This is a last attempt for me to get some insight on this issue before I scratch JqGrid all together. I have a col in my colModel to upload an Image. I am using ajaxfileupload. Although there are several of the same examples out there they seem to work for others but mine is not. When I select an Image from the enctype: "multipart/form-data" for some reason it is not putting anything in the record for the object. I have a few breakpoints and when I view the data everything is visible but the product Image. So all fields are there and ProductImage is null. It is like JqGrid is not holding the object and passing it. Since it is null, nothing gets uploaded either. Maybe I am missing something but I have looked through my code over and over again and it appears to be just like what I have read in examples that supposedly work.
Any help with would be fantastic as I am ready to scratch this and use something else.
Below is my code for the process. sections only. if you need to see other code let me know.
JqGrid:
{
name: "ProductImage",
index: "ProductImage",
mtype: "Post",
editable: true,
editrules: { required: true },
edittype: "file",
search: true,
resizable: false,
width: 210,
align: "left",
editoptions: {
enctype: "multipart/form-data"
}
},
.....
{
// edit option
zIndex: 100,
url: "/Admin/EditProducts",
closeOnEscape: true,
closeAfterEdit: true,
recreateForm: true,
afterSubmit: uploadImage,
afterComplete: function (response) {
if (response.responseText) {
alert(response.responseText);
}
}
},
....
function uploadImage(response, postdata) {
//debugger;
//var json = $.parseJSON(response.responseText);
//if (json) return [json.success, json.message, json.id];
//return [false, "Failed to get result from server.", null];
var data = $.parseJSON(response.responseText);
if (data.success == true) {
if ($("#ProductImage").val() != "") {
ajaxFileUpload(data.id);
}
}
return [data.success, data.message, data.id];
}
function ajaxFileUpload(id) {
$.ajaxFileUpload(
{
url: "/Admin/UploadImage",
secureuri: false,
fileElementId: "ProductImage",
dataType: "json",
data: { id: id },
success: function (data, status) {
if (typeof (data.isUploaded) != "undefined") {
if (data.isUploaded == true) {
return;
} else {
alert(data.message);
}
}
else {
return alert("Failed to upload image!");
}
},
error: function (data, status, e) {
return alert("Failed to upload image!");
}
}
)
return false;
}
Controller:
public string EditProducts(Product product)
{
string msg;
try
{
if (ModelState.IsValid)
{
using (StoreEntities db = new StoreEntities())
{
db.Entry(product).State = EntityState.Modified;
db.SaveChanges();
msg = "Saved Successfully";
}
}
else
{
msg = "Did not save! ";
}
}
catch (DbEntityValidationException ex)
//catch (Exception ex)
{
msg = "Error occured:" + ex.Message;
foreach (var validationErrors in ex.EntityValidationErrors)
{
foreach (var validationError in validationErrors.ValidationErrors)
{
System.Diagnostics.Debug.WriteLine("Property: {0} Error: {1}",
validationError.PropertyName, validationError.ErrorMessage);
}
}
}
return msg;
}
....
#region Upload Images
[HttpPost]
public JsonResult UploadImage(HttpPostedFileBase ProductImage)
{
string directory = "~/Images/";
if (ProductImage != null && ProductImage.ContentLength > 0)
{
var fileName = Path.GetFileName(ProductImage.FileName);
ProductImage.SaveAs(Server.MapPath(Path.Combine(directory, fileName)));
//ProductImage.SaveAs(Path.Combine(directory, fileName));
}
return Json(new { isUploaded = true, message = "Uploaded Successfully" }, "text/html");
}
#endregion

Display a confirmation message on Delete a record from a Grid

I want to display a confirmation message when the User delete a record from a grid this what I implement but I have the error message
With the code below the record is deleted but :
the record still in the Grid I have to refresh to see it disapear;
I Have the message Error! even if the record is deleted
3.
#Html.ActionLink("Delete Student", "Delete", new { #StudentID = StudentID }, new { #class="glyphicon glyphicon-pencil", #id=StudentID })
$(document).ready(function () {
$('a.delete').click(OnDeleteClick);
});
function OnDeleteClick(e)
{
var StudentId = e.target.id;
var flag = confirm('You are about to delete this record permanently. Are you sure you want to delete this record?');
if (flag) {
$.ajax({
url: '/Home/DeleteRecord',
type: 'POST',
data: { StudentID: StudentId },
dataType: 'json',
success: function (result) {
alert(result);
$("#" + StudentId).parent().parent().remove();
},
error: function () {
alert('Error!');
}
});
}
return false;
}
Controller :
public ActionResult DeleteRecord(string StudentID)
{
//Code to delete
}
return RedirectToAction("StudentGrid",
"Home");
}
Without seeing which grid you are using try the following:
Get the closest tr tag so you can remove it on success with:
var $tr = $(this).closest("tr");
$tr.remove();
jsFiddle
Set the content message from your controller, the Redirect won't work as it is an ajax call.
public ActionResult DeleteRecord(string StudentID)
{
var success = false;
//Code to delete
// then set success variable
if (success)
{
return Content("Deleted");
}
else
{
return Content("Failed");
}
}
Then from your success handler check the message and remove if needed, the client-side code would end up like this:
function OnDeleteClick(e)
{
e.preventDefault();
var $tr = $(this).closest("tr");
var StudentId = e.target.id;
var flag = confirm('You are about to delete this record permanently. Are you sure you want to delete this record?');
if (flag) {
$.ajax({
url: '/Home/DeleteRecord',
type: 'POST',
data: { StudentID: StudentId },
dataType: 'json',
success: function (result) {
if (result == "Deleted")
$tr.remove();
},
error: function () {
alert('Error!');
}
});
}
return false;
}
public ActionResult DeleteRecord(string StudentID)
{
//Code to delete
}
return Json("Record Is Delete", JsonRequestBehavior.AllowGet);
}
with is response from controller you can show this MSG in alert()
with update grid in project you can use below code is sufficient
$(e).closest("tr").remove();

MVC5 Controller: Check for duplicate in DB before saving?

On my View I have a button I use to submit a [description] value to my Controller via JSON, which is then used to create a new Table record. For example:
[HttpPost]
public JsonResult createNewStatus(string description)
{
INV_Statuses status = new INV_Statuses()
{
// ID auto-set during save
status_description = description,
created_date = DateTime.Now,
created_by = System.Environment.UserName
};
//var allErrors = ModelState.Values.SelectMany(x => x.Errors);
try
{
if (ModelState.IsValid)
{
db.INV_Statuses.Add(status);
db.SaveChanges();
}
}
catch (Exception ex)
{
Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
}
return Json(new { ID = status.Id, Text = status.status_description }, JsonRequestBehavior.AllowGet);
}
What I'd like to do now (before saving the Status to the DB) is run a check to see if any other records in the INV_Statuses table have a [description] value matching the one submitted to the function for new creation. If there is a match, I want to return an error/validation? message and alert the user the submitted value already exists and to choose it from the DropDownList on the View.
Can anyone provide an example of how to go about this with LINQ in my MVC Controller?
EDIT: Added my View JS code for submitting the new Status:
$('#createNewStatus').click(function () {
$('#createStatusFormContainer').show();
})
$('#cancelNewStatus').click(function () {
$('#createStatusFormContainer').hide();
})
$('#submitNewStatus').click(function () {
var form = $(this).closest('form');
var data = { description: document.getElementById('textNewStatus').value };
$.ajax({
type: "POST",
dataType: "JSON",
url: '#Url.Action("createNewStatus", "INV_Assets")',
data: data,
success: function (resp) {
$('#selectStatus').append($('<option></option>').val(resp.ID).text(resp.Text));
form[0].reset();
$('#createStatusFormContainer').hide();
var count = $('#selectStatus option').size();
$("#selectStatus").prop('selectedIndex', count - 1);
},
error: function () {
alert("ERROR!");
}
});
});
EDIT2:
Adricadar's suggestion:
INV_Statuses status = new INV_Statuses()
{
// ID auto-set during save
status_description = description,
created_date = DateTime.Now,
created_by = System.Environment.UserName
};
try
{
var existingStatus = db.INV_Statuses.FirstOrDefault(x => x.status_description.ToUpper() == status.status_description.ToUpper());
var isDuplicateDescription = existingStatus != null;
if (isDuplicateDescription)
{
ModelState.AddModelError("Error", "[" + status.status_description + "] already exists in the database. Please select from the DropDownList.");
}
else if (ModelState.IsValid)
{
db.INV_Statuses.Add(status);
db.SaveChanges();
}
}
catch (Exception ex)
{
Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
}
return Json(new { ID = status.Id, Text = status.status_description }, JsonRequestBehavior.AllowGet);
I added a .ToUpper() in my comparison in Controller, but even though the match with .ToUpper() gets identified, the ModelState.AddModelError() code fires, then the code returns and no error message is issued?
The value (though duplicate) still gets added to the dropdownlist (visually, not in DB) via my current JS code:
$('#createNewStatus').click(function () {
$('#createStatusFormContainer').show();
})
$('#cancelNewStatus').click(function () {
$('#createStatusFormContainer').hide();
})
$('#submitNewStatus').click(function () {
var form = $(this).closest('form');
var data = { description: document.getElementById('textNewStatus').value };
$.ajax({
type: "POST",
dataType: "JSON",
url: '#Url.Action("createNewStatus", "INV_Assets")',
data: data,
success: function (resp) {
$('#selectStatus').append($('<option></option>').val(resp.ID).text(resp.Text));
form[0].reset();
$('#createStatusFormContainer').hide();
var count = $('#selectStatus option').size();
$("#selectStatus").prop('selectedIndex', count - 1);
},
error: function () {
alert("ERROR!");
}
});
});
Check for existing status and set status back as follows:
var existingStatus = db.INV_Statuses.FirstOrDefault(s => s.status_description == description);
if (existingStatus ==null)
{
db.INV_Statuses.Add(status);
db.SaveChanges();
}
else
{
// set the status back to existing
status = existingStatus;
}
Set an existing flag in your response:
return Json(new { ID = status.Id, Text = status.status_description, AlreadyExists = (existingStatus != null) }, JsonRequestBehavior.AllowGet);
Then in your response JavaScript, simply parse out the returned data:
success: function (resp) {
if (resp.AlreadyExists != true)
{
$('#selectStatus').append($('<option></option>').val(resp.ID).text(resp.Text));
form[0].reset();
$('#createStatusFormContainer').hide();
var count = $('#selectStatus option').size();
$("#selectStatus").prop('selectedIndex', count - 1);
}
else
{
alert(resp.status_description + " already exists");
$("#selectStatus").val(resp.Id);
}
}
You can query the database for a status with an existing description and if exists and an model state error.
Be aware that string comparison is case sensitive.
[HttpPost]
public JsonResult createNewStatus(string description)
{
INV_Statuses status = new INV_Statuses()
{
// ID auto-set during save
status_description = description,
created_date = DateTime.Now,
created_by = System.Environment.UserName
};
//var allErrors = ModelState.Values.SelectMany(x => x.Errors);
try
{
var existingStatus = db.INV_Statuses.FirstOrDefault(x => x.status_description.ToUpper() == status.status_description.ToUpper());
var isDuplicateDescription = existingStatus != null;
string error = String.Empty;
if (isDuplicateDescription)
{
error = "[" + status.status_description + "] already exists in the database. Please select from the DropDownList.";
}
else if (ModelState.IsValid)
{
db.INV_Statuses.Add(status);
db.SaveChanges();
}
}
catch (Exception ex)
{
Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
}
return Json(new { ID = status.Id, Text = status.status_description, Error = error , IsDuplicate = isDuplicateDescription }, JsonRequestBehavior.AllowGet);
}
In javascript verify if response have IsDuplicate = true if is true you skip the part where you need to add an element in dropdown.
$('#createNewStatus').click(function () {
$('#createStatusFormContainer').show();
})
$('#cancelNewStatus').click(function () {
$('#createStatusFormContainer').hide();
})
$('#submitNewStatus').click(function () {
var form = $(this).closest('form');
var data = { description: document.getElementById('textNewStatus').value };
$.ajax({
type: "POST",
dataType: "JSON",
url: '#Url.Action("createNewStatus", "INV_Assets")',
data: data,
success: function (resp) {
if(resp.IsDuplicate)
{
//display error from response
//display resp.Error
} else {
$('#selectStatus').append($('<option></option>').val(resp.ID).text(resp.Text));
form[0].reset();
$('#createStatusFormContainer').hide();
var count = $('#selectStatus option').size();
$("#selectStatus").prop('selectedIndex', count - 1);
}
},
error: function () {
alert("ERROR!");
}
});
});

how to send upload control data to jquery ajax wihout plugins

I am trying to upload file/files to server through Ajax request in MVC, but the file is always returning null in the controller, can you please suggest the way to pass the file data in the ajax request?
<form method="post" enctype="multipart/form-data">
<div>
#Html.AntiForgeryToken()
<input type="file" name="file" id="files" multiple><br>
<input type="button" value="Upload File to Server" id="submit">
</div>
</form>
<script type="text/javascript">
$("#submit").click(function () {
var formData = $('#files').val();
alert(formData);
$.ajax({
url: 'home/index',
type: 'POST',
datatype: 'json',
enctype: "multipart/form-data",
data: { file: formData },
//processData: false, // Don't process the files
//contentType: false, // Set content type to false as jQuery will tell the server its a query string request
success: function (data) {
alert(data);
},
error: function () {
alert("failed");
}
});
});
</script>
[HttpPost]
[ActionName("Index")]
public ActionResult Index_Post(HttpPostedFileBase file)
{
string errormsg = string.Empty;
if (file != null)
{
// Verify that the user selected a file
if (file != null && file.ContentLength > 0)
{
// extract only the fielname
var fileName = Path.GetFileName(file.FileName);
// TODO: need to define destination
var path = Path.Combine(Server.MapPath("~/Upload"), fileName);
try
{
file.SaveAs(path);
errormsg = "uploaded";
return Json(fileName + errormsg);
}
catch
{
errormsg = "failed to upload";
return Json(fileName + errormsg);
}
}
}
else
{
errormsg = "No file selected";
return Json(errormsg);
}
return View();
}
}
Take normal button instead of submit button and try below code
$("#submit").click(function () {
var formData = new FormData();
var opmlFile = $('#myFile')[0];
formData.append("opmlFile", opmlFile.files[0]);
$.ajax({
url: 'home/index',
type: 'POST',
datatype: 'json',
enctype: "multipart/form-data",
data: formData ,
//processData: false, // Don't process the files
//contentType: false, // Set content type to false as jQuery will tell the server its a query string request
success: function (data) {
alert(data);
},
error: function () {
alert("failed");
}
});
});
});
and controller action :-
[HttpPost]
[ActionName("Index")]
public HttpResponseMessage Index()
{
HttpResponseMessage result = null;
var httpRequest = HttpContext.Current.Request;
// Check if files are available
if (httpRequest.Files.Count > 0)
{
var files = new List<string>();
// interate the files and save on the server
foreach (string file in httpRequest.Files)
{
var postedFile = httpRequest.Files[file];
var filePath = HttpContext.Current.Server.MapPath("~/" + postedFile.FileName);
postedFile.SaveAs(filePath);
files.Add(filePath);
}
// return result
result = Request.CreateResponse(HttpStatusCode.Created, files);
}
else
{
// return BadRequest (no file(s) available)
result = Request.CreateResponse(HttpStatusCode.BadRequest);
}
return result;
}

Change button status (MVC)

I wanna make twitter like microblog site which other users can follow my posts.
For that i made page with all currently registered users. In front of each name there is button to follow/unfollow user. (Like in Twitter)
View -
#{
ViewBag.Title = "Users";
}
#model MembershipUserCollection
#foreach (MembershipUser item in Model)
{
if(User.Identity.Name != item.UserName)
{
<li>#item.UserName
<span id="sp-#item.UserName"><input id="#item.UserName" name="submit" type="submit" value="Follow" class="follow-user fg-button ui-state-default"/></span>
</li>
}
}
<script type="text/javascript">
$(".follow-user").live("click", function (e) {
e.preventDefault();
var data = $(this).attr("id");
var spid = '#sp-' + data;
var btnid = '#' + data;
var val = $(this).attr('value');
$.ajax({
type: "POST",
url: "User/FollowUser",
data: { id: data },
cache: false,
dataType: "json",
success: function () {
if (val == 'Follow') {
$(btnid).attr('value', 'Unfollow');
}
else {
$(btnid).attr('value', 'Follow');
}
}
});
});
</script>
Controller -
public ActionResult Index()
{
return View(Membership.GetAllUsers());
}
public void FollowUser(string id)
{
ViewData["test"] = "test";
var n = FollowingUser.CreateFollowingUser(0);
n.FollowingId = id;
n.FollowerId = User.Identity.Name;
string message = string.Empty;
var list = new List<FollowingUser>();
list = (from a in db.FollowingUsers where a.FollowerId == User.Identity.Name && a.FollowingId == id select a).ToList();
if (list.Count() == 0)
{
try
{
db.AddToFollowingUsers(n);
db.SaveChanges();
}
catch (Exception ex)
{
message = ex.Message;
}
}
else
{
db.DeleteObject((from a in db.FollowingUsers where a.FollowerId == User.Identity.Name select a).FirstOrDefault());
db.SaveChanges();
}
}
FollowingUsers Table -
Now i wanna change button status on page load checking database whether he is already followed or not.
Ex- If user already followed it should display like below.
When you show this view to a user where this button is displayed, Load the status also, if the person is following or not.
public ActionResult Index()
{
var model = new MemberShipViewModel();
//We check here if the logged in user is already following the user being viewd
foreach(var member in Membership.GetAllUsers())
{
var user = (from a in db.FollowingUsers where a.FollowerId == User.Identity.Name && a.FollowingId == member.UserName select a).FirstOrDefault();
model.Members.Add(new Member{UserName = member.UserName,IsFollowing=user!=null});
}
//This line will remove the logged in user.
model.Members.Remove(model.Members.First(m=>m.UserName==User.Identity.Name));
return view(model);
}
In your index view model, you need to make some changes.
#model MemberShipViewModel
#foreach (var item in Model)
{
<li>#item.UserName
if(!item.IsFollowing)
{
<span id="sp-#item.UserName"><input id="#item.UserName" name="submit" type="submit" value="Follow" class="follow-user fg-button ui-state-default"/></span>
}
else
{
<span id="sp-#item.UserName"><input id="#item.UserName" name="submit" type="submit" value="Follow" class="unfollow-user fg-button ui-state-default"/></span>
}
</li>
}
$(".follow-user").live("click", function (e) {
e.preventDefault();
var data = $(this).attr("id");
var spid = '#sp-' + data;
var btnid = '#' + data;
var val = $(this).attr('value');
$.ajax({
type: "POST",
url: "User/FollowUser",
data: { id: data },
cache: false,
dataType: "json",
success: function () {
if (val == 'Follow') {
$(btnid).attr('value', 'Unfollow');
}
else {
$(btnid).attr('value', 'Follow');
}
}
});
});
You need to write some javascript now. Nobody is going to write full software for you.
Seems you are missing very basic programming skills.
cheers

Categories