Reputation: 3934
I am working on a View for an MVC5 app. This is an Edit
View with multiple properties, several of which are related to other models. I have my main INV_Assets
model and then several other tables for Location, Manufacturer, Model, Status, Type, Vendor
, etc. On this Edit
view, I'm displaying those particular properties as dropdown lists containing all values currently in those tables, along with a [CREATE NEW] button by each list.
When user selects the [CREATE NEW] button, I have a hidden form which appears and allows a user to enter a new value for the specific Table/DropDown. I've got everything working except the POST where I add the value to the Table and refresh the DropDown list.
Below is what I have put together for my first dropdown (the Model
selection) -- everything is functioning up to the POST:
INV_Assets.Edit View:
<div class="form-group">
<span class="control-label col-md-2">Manufacturer:</span>
<div class="col-md-4">
@Html.DropDownListFor(model => model.Manufacturer_Id, (SelectList)ViewBag.Model_List, htmlAttributes: new { @class = "form-control dropdown" })
@Html.ValidationMessageFor(model => model.Manufacturer_Id, "", new { @class = "text-danger" })
</div>
<div class="col-md-1">
<div class="btn-group">
<button type="button" class="btn btn-success" aria-expanded="false">CREATE NEW</button>
</div>
</div>
</div>
INV_Assets.Edit Script:
<script type="text/javascript">
$(document).ready(function () {
// Show() form to enter new Model.
$('#createNewModel').click(function () {
$('#createModelFormContainer').show();
})
// Submit new Model value and refresh dropdown
$('#submitNewModel').click(function () {
alert("New Function!"); // WORKING
var form = $(this).closest('form');
var url = form.attr('action');
var data = { Text: form.find('input').first().val() };
alert("Prior to Post"); // WORKING
$.post(url, form.serialize(), function (data) {
alert("Begin POST!"); // NOT BEING REACHED!
$('#selectModel').append($('<option></option>').val(data.ID).text(data.Text));
form[0].reset();
$('#createModelFormContainer').hide();
})
});
});
</script>
When my code hits the $.post
something goes wrong. It was previously getting:
Since post()
seemed to be the anonymous function, I assumed I did not have ajax installed. I then installed Microsoft.jQuery.Unobtrusive.Ajax
, which now renders my error as: Failed to load resource: the server responded with a status of 404 (Not Found) - http://localhost:4545/INV_Assets
.
Any thoughts on this?
As best as I understand it, my submit should be posting to my below createNewModel()
method inside my INV_AssetsController
:
[HttpPost]
public JsonResult createNewModel(INV_Models model)
{
model.created_date = DateTime.Now;
model.created_by = System.Environment.UserName;
model.modified_date = DateTime.Now;
model.modified_by = System.Environment.UserName;
if (ModelState.IsValid == false && model.Id == 0)
{
ModelState.Clear();
}
if (ModelState.IsValid)
{
db.INV_Models.Add(model);
db.SaveChangesAsync();
}
return Json(new { ID = model.Id, Text = model.model_description });
}
Assuming it is something to do with my routing, this is my current RouteConfig.cs
:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
Anyone with more expertise able to see what I'm doing wrong?
EDIT:
Using wahwahwah's suggestion, I made the following modification to my script:
$('#createNewModel').click(function () {
$('#createModelFormContainer').show();
})
$('#submitNewModel').click(function () {
var form = $(this).closest('form');
var data = { Text: form.find('input').first().val() };
$.ajax({
type: "POST",
dataType: "JSON",
url: '@Url.Action("createNewModel", "INV_Assets")',
data: data,
success: function (resp) {
alert("SUCCESS!");
},
error: function () {
alert("ERROR!");
}
});
Going this route, my createNewModel()
action is correctly called in the controller, but fails out at db.SaveChangesAsync()
:
[HttpPost]
public JsonResult createNewModel(INV_Models model)
{
model.created_date = DateTime.Now;
model.created_by = System.Environment.UserName;
model.modified_date = DateTime.Now;
model.modified_by = System.Environment.UserName;
if (ModelState.IsValid == false && model.Id == 0)
{
ModelState.Clear();
}
if (ModelState.IsValid)
{
db.INV_Models.Add(model);
db.SaveChangesAsync();
}
return Json(new { ID = model.Id, Text = model.model_description });
}
The error is as follows:
An exception of type 'System.Data.Entity.Validation.DbEntityValidationException' occurred in EntityFramework.dll but was not handled in user code
Additional information: Validation failed for one or more entities. See 'EntityValidationErrors' property for more details.
EDIT2:
Modified my troublesome code to be in a try/catch and then set a Watch
on ex:
[HttpPost]
public JsonResult createNewModel(INV_Models model)
{
model.created_date = DateTime.Now;
model.created_by = System.Environment.UserName;
model.modified_date = DateTime.Now;
model.modified_by = System.Environment.UserName;
// Set ID
int lastModelId = db.INV_Models.Max(mdl => mdl.Id);
model.Id = lastModelId+1;
if (ModelState.IsValid == false && model.Id > 0)
{
ModelState.Clear();
}
if (ModelState.IsValid)
{
try
{
db.INV_Models.Add(model);
db.SaveChangesAsync();}
catch (Exception ex)
{
Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
}
}
return Json(new { ID = model.Id, Text = model.model_description });
}
ex
Details:
Apparently the description
I'm entering for the new Model is not being included in the new Model
that is being saved?
EDIT3:
Below is my current script/controller action code. When I break inside the controller and type ?model.model_description
into the Immediate Window
, it returns null
.
Regarding my below alerts, the value in my <input type="text" name="model_description" />
appears to not be correctly stored in the variable for use by JSON, and thus is not passed to the controller?
alert(test)
: S2EFXrd3nXdWOIES5eBi4e_Fz3wrqCwP44hhQ7kj_foL3qkNv26OBgQoqHC-8BV8HKC6xdDEa7uCBnhOFPKL3AwIko99p-j_887qQgOXRPg1
alert(data.model_description)
: S2EFXrd3nXdWOIES5eBi4e_Fz3wrqCwP44hhQ7kj_foL3qkNv26OBgQoqHC-8BV8HKC6xdDEa7uCBnhOFPKL3AwIko99p-j_887qQgOXRPg1
alert(jasonData.valueOf())
: {"model_description":"S2EFXrd3nXdWOIES5eBi4e_Fz3wrqCwP44hhQ7kj_foL3qkNv26OBgQoqHC-8BV8HKC6xdDEa7uCBnhOFPKL3AwIko99p-j_887qQgOXRPg1"}
INPUT FORM:
<div id="createModelFormContainer" style="display:none">
<form action="/createNewModel">
<input type="text" name="model_description" />
<input type="button" id="submitNewModel" value="Submit" />
</form>
</div>
Script:
$('#submitNewModel').click(function () {
var form = $(this).closest('form');
var test = form.find('input').first().val();
alert(test);
var data = { model_description: form.find('input').first().val() };
alert(data.model_description);
//var data = { model_description: $("input[name = 'model_description']").text.toString() };
var jsonData = JSON.stringify(data);
alert(jsonData.valueOf());
$.ajax({
type: "POST",
dataType: "JSON",
url: '@Url.Action("createNewModel", "INV_Assets")',
data: jsonData,
success: function (resp) {
alert("SUCCESS!");
},
error: function () {
alert("ERROR!");
}
});
Upvotes: 1
Views: 16219
Reputation: 3177
Here are a few things that might help you troubleshoot your View / jQuery:
Here's an example (not in order):
//... earlier code omitted for brevity
var test = form.find('input').first().val();
alert(test); // <--- should return the value you want to post (2)
// ... (4) need to change 'Text' to 'model_description' to reflect your model
// properties (otherwise, how can your controller bind your model to the json object your submitting to it?)
var data = { model: [{ model_description: form.find('input').first().val(); }]};
// need to make data a JSON object (1a)
var jsonData = JSON.stringify(data);
$.ajax({
type: "POST", //<-- specify POST (1b)
dataType: "JSON", // <-- specify JSON (1c)
url: '@Url.Action("createNewModel", "INV_Assets")', // <-- Easier way to do URL (3)
data: jsonData, // JSON
success: function(resp){
//callback
},
error: function() {
//callback
}
});
Now, with your Controller...
Toggle a breakpoint and make sure that your JSON object is binding to your model object:
public JsonResult createNewModel(INV_Models model)
{
// jsonData.model_description should have automatically bound to
// model.model_description because the property names are the same
}
With regards to your SaveChanges()
issue, this error is normally thrown when there's a type mismatch - or null
data where required - you might want to wrap your db call in a try-catch
then read/handle the error:
try
{
db.INV_Models.Add(model);
db.SaveChangesAsync();
}
catch (Exception Ex)
{
// toggle breakpoint --> read error --> do something else?
// throw http error --> catch in ajax error callback?
}
Upvotes: 2