I need to be able to send a list of a model back to the controller from a view but only when the input has been checked.
Using AJAX I can get it working but the page refreshes and I don’t catch the data but it does show up in the URL. Example: https://localhost:44308/PlayTest/PlayTest?personName=Test+User&DevOps-rate=3&Software+Development-rate=2&Solution+Architecture-rate=1&comments=&save=Save
But when I try and use Javascript and JQuery, I’m only able to catch the “person name” not the comments or rates in the post method.
HTML
<div class="tabcontent" id="testing">
<form name="skillform"
id="skillform"
asp-action="SaveRecord"
asp-controller="YourSkills"
data-ajax="true"
data-ajax-method="post">
<h3 class="tab-title">Testing</h3>
@foreach (var item in Model.Skills)
{
@if (item.SkillGroupID == 2)
{
<div class="star-rating">
<h5 class="skill-name" id="skill-title">@item.SkillName</h5>
<input type="radio" id="@[email protected]" name="@item.SkillName-rate" value="3" /><label for="@[email protected]" title="Advanced - 3 Stars">3 Stars</label>
<input type="radio" id="@[email protected]" name="@item.SkillName-rate" value="2" /><label for="@[email protected]" title="Intermediate - 2 Stars">2 Stars</label>
<input type="radio" id="@[email protected]" name="@item.SkillName-rate" value="1" /><label for="@[email protected]" title="Beginner - 1 Star">1 Stars</label>
</div>
<br />
<br />
}
}
<div class="comments">
<h6 class="comment-name">Comments</h6>
<textarea rows="4" cols="50" name="comments" id="comment-text-area" spellcheck="true"></textarea>
</div>
<div class="buttons">
<input type="reset" value="Clear">
<button type="button" class="edit" onclick="alert('This will allow the tab to be edited')">Edit</button> <!--add cancel button when opened-->
<input type="submit" name="save" value="Save" id="btnSave" skill-group="2"/>
</div>
</form>
</div>
Post Method
public JsonResult SaveRecord(string PersonName, List<SkillsModel> skill, string comment)
{
SkillsMatrixDB database = HttpContext.RequestServices.GetService(typeof(SkillsMatrix.Models.SkillsMatrixDB)) as SkillsMatrixDB;
List<PersonModel> people = database.GetAllPeople();
PersonModel recordingPerson = FindPerson(people, PersonName);
if (skill.Count() > 1)
{
for (int i = 0; i < skill.Count(); i++)
{
RecordsModel records = new RecordsModel();
records.PersonID = recordingPerson.PersonID;
records.SkillGroupID = skill[i].SkillGroupID;
records.SkillID = skill[i].SkillID;
records.SkillLevelID = Convert.ToInt32(HttpContext.Request.Form[skill[i].SkillName + skill[i].SkillGroupID + "-rate"]);
records.Comments = HttpContext.Request.Form["comments"].ToString();
records.DateSaved = DateTime.Now;
records.YearlyQuarter = DateTime.Now.Month / 3;
//database.SaveRecord(records);
}
}
else if (skill.Count() == 1)
{
RecordsModel records = new RecordsModel();
records.PersonID = recordingPerson.PersonID;
records.SkillGroupID = skill[0].SkillGroupID;
records.SkillID = skill[0].SkillID;
records.SkillLevelID = Convert.ToInt32(HttpContext.Request.Form[skill[0].SkillName + skill[0].SkillGroupID + "-rate"]);
records.Comments = HttpContext.Request.Form["comments"].ToString();
records.DateSaved = DateTime.Now;
records.YearlyQuarter = DateTime.Now.Month / 3;
//database.SaveRecord(records);
}
return Json(recordingPerson.Name);
}
JS
$(document).ready(function () {
$("#btnSave").click(function () {
$.ajax({
contentType: 'application/json; charset=utf-8',
dataType: 'json',
type: "POST", //HTTP POST Method
url: "YourSkills/SaveRecord", //Controller/View
data: $('#skillform').serialize(),
success: function (data) {
console.log(data);
alert('You saved it!');
},
error: function (jqXHR, textStatus, errorThrown) {
console.log(textStatus);
alert('Something went wrong. save failed!');
}
});
});
});
I feel like the way I’ve read to make the list in JS is wrong and to catch the data is not all that correct either. If someone could help that would be great. I’m so confused why doing it without JS works and picks up the right data but for some reason, I can’t.
EDIT
I have tried what Emiel Zuurbier said but I am using Visual Studio 2019 and In the console, all I am getting is the following:
Microsoft.AspNetCore.Hosting.Diagnostics: Information: Request starting HTTP/2.0 POST https://localhost:44308/PlayTest/YourSkills/SaveRecord application/json; charset=UTF-8 235
Microsoft.AspNetCore.Hosting.Diagnostics: Information: Request finished in 6.0162ms 404
Microsoft.AspNetCore.Hosting.Diagnostics: Information: Request starting HTTP/2.0 POST https://localhost:44308/PlayTest/SaveRecord application/x-www-form-urlencoded 233
Failed to load resource: the server responded with a status of 404 () [https://localhost:44308/PlayTest/YourSkills/SaveRecord]
Microsoft.AspNetCore.Routing.EndpointMiddleware: Information: Executing endpoint 'SkillsMatrix.Controllers.PlayTestController.SaveRecord (SkillsMatrix)'
error
Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker: Information: Route matched with {action = "SaveRecord", controller = "PlayTest"}. Executing controller action with signature Microsoft.AspNetCore.Mvc.JsonResult SaveRecord(System.String, System.Collections.Generic.List`1[SkillsMatrix.Models.SkillsModel], System.String) on controller SkillsMatrix.Controllers.PlayTestController (SkillsMatrix).
2
Answers
page reloading may happens because the error occurred in js execution while you are creating skills object.as its not the right way
define skills object this way rest of the things look good.
Your page is being reloaded because you are submitting the form whenever you click the the
#btnSave
button. What you want to do is listen for thesubmit
event on the form itself and cancel it withevent.preventDefault()
. This allows you to create your own submission behavior when submitting. And prevents the form from reloading the page.Your HTML seems to miss the
#skill-id
element. If you mean to include data from your form into your controller then I suggest that you use hidden input fields instead of reading attributes from your elements.These fields will not be visible to the user but will contain data that the server is able to read.
Then instead of use
.val()
to get each individual field use$('form').serialize()
to extract the name and value pairs out of the form and use them in your AJAX request. This way you are sending the same data as you would with a normal submit.I recommend that you check the
$.ajax
docs to use the correct methods and notation to use the function properly.