MVC5 Controller: Check for duplicate in DB before saving? - c#

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!");
}
});
});

Related

Why querystring after ajax call while using datatable checkboxes?

I am trying to save the data by selecting multi checkboxes in datatables. But after ajax call in the submit click the the ajax not hitting success function. It is showing querystring along with the controller/action.Like following
https://localhost:44307/Leaves/Approval?leaveApproveDataTable_length=10&id%5B%5D=11
This is my js
$(document).on('click', '.btn-Approve', function (e) {
var form = this;
var rows = $(table.rows({
selected: true
}).$('input[type="checkbox"]').map(function () {
return $(this).prop("checked") ? $(this).closest('tr').attr('leaveid') : null;
}));
rows_selected = [];
$.each(rows, function (index, rowId) {
console.log(rowId)
// Create a hidden element
rows_selected.push(rowId);
$(form).append(
$('<input>')
.attr('type', 'hidden')
.attr('name', 'id[]')
.val(rowId)
);
});
var remarks = $('#Remarks').val();
console.log($(this).closest('tr').attr('leaveid'));
$.ajax({
url: '/Leaves/LeaveApproval',
data: { approveId: rows_selected, remarks: remarks },
type: 'POST',
processData: true,
dataType: 'JSON',
success: function (result) {
console.log(result);
debugger;
if (result) {
window.location.href = "/Leaves/Approval";
}
else {
return result;
}
},
error: function () {
}
});
});
This is my controller
public async Task<IActionResult> LeaveApproval(List<int> approveId, string remarks)
{
foreach (int id in approveId)
{
var leave = await _context.Leaves.FindAsync(id);
if (leave == null)
{
return Json(new { success = false });
}
leave.Status = "Approved";
leave.Remarks = remarks;
leave.ApprovedDate = DateTime.Now;
_context.Update(leave);
await _context.SaveChangesAsync();
}
return Json(new { success = true });
}
Kindly help me to solve the issue.
While returning from the controller replace:
return Json(new { success = true }); this line with
return Json(new { success = true }, JsonRequestBehavior.AllowGet);

how to correctly delete file from server

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

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();

Why my data is not updating?

I am trying to update ClientInfo table. But it is not updating and shows that Undefined. Those code below i have used in my controller for updating my database table data. Where is my problem i cannot find out? experts please help me..
[HttpPost]
public JsonResult Update(ClientInfo clnt, int id)
{
if (ModelState.IsValid)
{
ClientInfo c = db.Query<ClientInfo>("Select * from ClientInfo Where CId=#0", id).First<ClientInfo>();
c.CName = clnt.CName;
c.CCName = clnt.CCName;
c.Address = clnt.Address;
c.PhoneNo = clnt.PhoneNo;
c.Fax = clnt.Fax;
c.Email = clnt.Email;
c.Country = clnt.Country;
c.PostalCode = clnt.PostalCode;
c.Update();
return Json(c, JsonRequestBehavior.AllowGet);
}
else
return Json(new { msg = "Fail to Update Client Info." + id });
}
And Search Controller For searching Data
public JsonResult Search2(string id=null)
{
if (id != null)
{
var sresult = db.Query<ClientInfo>("Where CId=" + id).ToList<ClientInfo>();
return Json(sresult, JsonRequestBehavior.AllowGet);
}
else
return null;
}
And my ajax call from views For searching data by cid value..
#section scripts{
#Scripts.Render("~/bundles/jqueryui")
#Scripts.Render("~/bundles/jqueryval")
#Styles.Render("~/Content/themes/base/css")
<script type="text/javascript">
$(document).ready(function () {
$('#CId').blur(function () {
var v = $('#CId').val();
var url = "/Clients/Search2/" + v;
// alert("Test : " + url);
$("#CName").val("");
$("#CCName").val("");
$("#PhoneNo").val("");
$("#Fax").val("");
$("#Email").val("");
$("#Address").val("");
$("#PostalCode").val("");
$("#Country").val("");
$.getJSON(url, null, function (data, status) {
$.each(data, function (index, C) {
$("#CName").val(C.CName);
$("#CCName").val(C.CCName);
$("#PhoneNo").val(C.PhoneNo);
$("#Fax").val(C.Fax);
$("#Email").val(C.Email);
$("#Address").val(C.Address);
$("#PostalCode").val(C.PostalCode);
$("#Country").val(C.Country);
});
});
});
For database update i have used this function ...
$('#btnUpdate').click(function () {
var CId = $("#CId").val();
var CName = $("#CName").val();
var CCName = $("#CCName").val();
var PhoneNo = $("#PhoneNo").val();
var Fax = $("#Fax").val();
var Email = $("#Email").val();
var Address = $("#Address").val();
var PostalCode = $("#PostalCode").val();
var Country = $("#Country").val();
var client1 = {
"CId": CId,
"CName": CName,
"CCName": CCName,
"PhoneNo": PhoneNo,
"Fax": Fax,
"Email": Email,
"Address": Address,
"PostalCode": PostalCode,
"Country": Country
};
var lk = "/Clients/Update/" + CId;
//alert("Test : Update " + lk + "\n" + client1.Country);
client = JSON.stringify(client1);
$.ajax({
cashe: false,
async: false,
url: lk,
type: 'POST',
data: client,
dataType: "json",
success: function (data) {
alert(data.msg);
},
error: function (data) {
alert(data.msg);
}
});
});
});
</script>
}
If you mean Undefined in your alert message box, it's simple:
$.ajax({
cashe: false,
async: false,
url: lk,
type: 'POST',
data: client,
dataType: "json",
success: function (data) {
alert(data.msg);
},
error: function (data) {
alert(data.msg);
}
});
Your ajax code displays the content of data.msg. But when your model is valid, it retrieves the model from the database, updates it and returns the new model. There is no msg json property if it succeeds, hence data.msg is undefined.
If you want it to return a success message, you need to change
return Json(c, JsonRequestBehavior.AllowGet);
into
return Json(new { msg = "Update Successful.", record = c }, JsonRequestBehavior.AllowGet);
then you will have a message in data.msg and your newly updated record in data.record.
DBContext have a save method you must run this.
Did you run Save(); method ?

Send parameters to controller from view with no form/input

I reached a point in my code where I need to call a method in the controller from the view.
I need to send some parameters with him from DropDownLists and TextBoxes.
I dont want to make a #using (Html.BeginForm... and an <input>, I just want to keep a <button> with a function call there that gathers that info and runs the method.
Is it possible?
An example of my DDL and Textbox:
#Html.DropDownListFor(cModel => cModel.QueueMonitorConfigTypeName, Enum.GetValues(typeof(BPM.Website.Models.PathType)).Cast<BPM.Website.Models.PathType>().Select(v => new SelectListItem
{
Text = v.ToString(),
Value = v.ToString()
}), new { id = "ddlConfigTypeName" })
#Html.TextBoxFor(cModel => cModel.Location, new { id = "txtbLocation" })
My button:
<button id="btnAddUpdateConfig" name="btnAddUpdateConfig" value="Apply" onclick="ValidateValues()">Apply</button>
JS:
function ValidateValues()
{
$.ajax({
type: "POST",
url: "Storage/AddUpdateConfigs",
data: ({id: #Model.QueueMonitorConfigurationsID, PathType: $('#ddlConfigTypeName').val(), Threshold:$('#ddlThreshold').val(), ValueType:$('#ddlValueTypeName').val(), Location: $('#txtbLocation').val(), Limit: $('#txtbLimit').val(), config: $('#NewOrUpdate').val() }),
dataType: JSON
});
}
But my function AddUpdate Configs is not being triggered:
public ActionResult AddUpdateConfigs(int id, string configType, string location, string threshold, string valueType, int limit)
{
return PartialView();
}
I put a breakpoint in the return and is not reached
Something like this should work:
$.postify = function(value) {
var result = {};
var buildResult = function(object, prefix) {
for (var key in object) {
var postKey = isFinite(key)
? (prefix != "" ? prefix : "") + "[" + key + "]"
: (prefix != "" ? prefix + "." : "") + key;
switch (typeof (object[key])) {
case "number": case "string": case "boolean":
result[postKey] = object[key];
break;
case "object":
if (object[key].toUTCString)
result[postKey] = object[key].toUTCString().replace("UTC", "GMT");
else {
buildResult(object[key], postKey != "" ? postKey : key);
}
}
}
};
buildResult(value, "");
return result;
};
function login() {
var logonmodel = {
UserName: $tbUsername.val(),
Password: $tbPassword.val()
};
$.ajax({
type: "POST",
url: "/account/logon",
data: $.postify(logonmodel),
asynch: true,
dataType: "json",
success: function (msg) {
console.log(msg.state);
if (msg.state == 'good') {
window.location.href = msg.url;
}
else {
var $generalLoginError = $('span#generalLoginError');
var $loginuserNameError = $('span#loginUserNameError');
var $loginPasswordError = $('span#loginPasswordError');
$loginuserNameError.html(msg.errors.username);
$loginPasswordError.html(msg.errors.password);
if (msg.errors.incorrect != '')
$generalLoginError.html(msg.errors.incorrect);
}
}
});
}
Here's the controller action:
[HttpPost]
public ActionResult LogOn(LogOnModel model, string returnUrl)
{
if (ModelState.IsValid)
{
if (Membership.ValidateUser(model.UserName, model.Password))
{
FormsAuthentication.SetAuthCookie(model.UserName, false);
if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/")
&& !returnUrl.StartsWith("//") && !returnUrl.StartsWith("/\\"))
{
return Json(new { url = returnUrl, message = "", state = "good" });
}
else
{
return Json(new { url = "/", message = "", state = "good" });
}
}
}
// If we got this far, something failed, redisplay form
return Json(new
{
url = "/",
errors = new
{
username = (model.UserName == null) ? "required" : "",
password = (model.Password == null) ? "required" : "",
incorrect = (!Membership.ValidateUser(model.UserName, model.Password)) ? "The user name or password provided is incorrect." : "",
//generic = "An error has occurred. If the error persists, please contact the webmaster."
},
state = "error"
});
}
Do an AJAX request when the button is clicked.
$.ajax({
type: "POST",
url: http://site.com/Controller/Action,
data: data,
success: success,
dataType: dataType
});
See:
http://api.jquery.com/jQuery.post/

Categories