I am using ajax to send values to my controller from the view:
View where information is collected to send to a different controller:
#using (Html.BeginForm(null, null, FormMethod.Get, htmlAttributes: new { id = "GenerateForm" }))
{
<div class="form-horizontal">
<div class="form-group">
#Html.Label("Choose AC:", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("AC", null, "-- Select AC --", htmlAttributes: new { id = "AC", #class = "form-control" })
</div>
</div>
</div>
<div class="form-horizontal">
<div class="form-group">
#Html.Label("Choose Month:", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("Months", null, "-- Select Month --", htmlAttributes: new { id = "Month", #class = "form-control" })
</div>
</div>
</div>
<div class="form-horizontal">
<div class="form-group">
#Html.Label("Year:", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("Years", null, "-- Select Year --", htmlAttributes: new { id = "Year", #class = "form-control" })
</div>
</div>
</div>
<br />
<input type="submit" id="SendToController" class="btn btn-primary" value="Generate" />
}
<script type="text/javascript">
$('#SendToController').on('click', function() {
sendToController();
return false;
});
function sendToController(){
var selectedAC = $('#AC').val();
var selectedMonth = $('#Month').val();
var chosenYear = $('#Year').val();
$.ajax({
url: '/MonthReports/Generate',
data: { 'id' : selectedAC, 'monthValue' : selectedMonth, 'year' : chosenYear },
type: 'GET',
cache: false,
success: function(data){},
});
}
Controller Method:
public ActionResult Generate(int id, int monthValue, string year)
{
List<DailySum> lstDailySum = db.DailySum.Where(x => x.AID == id && x.Day.Month == monthValue + 1 && x.Day.Year.ToString() == year && x.deleted == false).ToList();
List<string> lstInc = lstDailySum.Select(x => x.codeAC.text).Distinct().ToList();
List<MReport> lstMReport = new List<MReport>();
foreach (var inc in lstInc)
{
MReport mReport = new MReport();
mReport.Inc = inc;
mReport.Count = lstDailySum.Where(x => x.codeAC.text == incident).Count();
lstMReport.Add(mReport);
}
return View(lstMReport);
}
Now the values are being passed through when the button is clicked, and the whole method works, except the View doesn't show up.. it just stays on the View where the button was originally clicked... no Generate View appears.
I have placed a breakpoint on the Generate view and it does get hit but the view doesn't show?
I don't know how else to explain it.. the cshtml code is hit with a breakpoint, but the page doesn't show.. it just stays on the page where the button was clicked.
Any help is appreciated.
Because you are using ajax, you should handle the data in the success callback of your ajax call. The way your code is written, you do nothing with the view. The View is rendered to the data variable.
Try something like this:
$.ajax({
url: '/MonthReports/Generate',
data: { 'id' : selectedAC, 'monthValue' : selectedMonth, 'year' : chosenYear },
type: 'GET',
cache: false,
success: function(data){
$("body").html(data);
}
});
Related
I'm using ajax call to execute partial view controller action to print max batch number. Everything executes, but the value doesn't print in partial view. On selected dropdown list I'm calling ajax method to execute. Below is my code that i'm using.
Models.Batch.cs
[Required]
[StringLength(100)]
[DataType(DataType.Text)]
[Display(Name = "Batch Number")]
public string BatchNumber { get; set; }
BatchController.cs
public PartialViewResult GetBatchNumber(string CourseID)
{
Context.Batches contBatch = new Context.Batches();
Models.Batches b = new Models.Batches();
b.BatchNumber = contBatch.GetallBatchList().ToList().Where(p => p.CourseId == CourseID).Select(p => p.BatchNumber).Max().FirstOrDefault().ToString();
ViewBag.Message = b.BatchNumber;
return PartialView(b);
}
CreateBatch.cshtml
<div class="col-md-10">
#Html.DropDownListFor(m => m.CourseId, Model.Courses, new { id = "ddlCourse" })
<div id="partialDiv">
#{
Html.RenderPartial("GetBatchNumber", Model);
}
</div>
<script>
$("#ddlCourse").on('change', function () {
var selValue = $('#ddlCourse').val();
$.ajax({
type: "GET",
url: '/Batch/GetBatchNumber?CourseId=' + selValue,
dataType: "json",
data: "",
success: function (data) {
$("#partialDiv").html(data);
},
failure: function (data) {
alert('oops something went wrong');
}
});
});
</script>
</div>
GetBatchNumber.cshtml
#model WebApplication1.Models.Batches
<div class="form-group">
#Html.LabelFor(model => model.BatchNumber, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DisplayFor(model => model.BatchNumber)
#Html.ValidationMessageFor(model => model.BatchNumber, "", new { #class = "text-danger" })
</div>
</div>
When the modal pops open the values that were originally selected for the drop down list have been changed to the first item on the list. How do I keep the values that were originally selected?
Controller:
public ActionResult AddEditExam(int exam_id)
{
exam exam = new exam();
ViewBag.credential_id = new SelectList(db.credentials, "credential_id", "credential_code", exam.credential_id);
ViewBag.credential_status_id = new SelectList(db.credential_status, "credentials_status_id", "credentials_status_description", exam.credential_status_id);
if (exam_id > 0)
{
exam ex = db.exams.SingleOrDefault(x => x.exam_id == exam_id);
exam.exam_id = ex.exam_id;
exam.credential_id = ex.credential_id;
exam.credential_status = ex.credential_status;
exam.exam_desc = ex.exam_desc;
exam.exam_last_update = ex.exam_last_update;
exam.exam_passing_score = ex.exam_passing_score;
exam.exam_time = ex.exam_time;
}
return PartialView("AddEdit", exam);
}
Partial View: Slimmed down to drop down list
#Html.LabelFor(model => model.credential_id, "credential_id", htmlAttributes: new { #class = "control-label col-md-2" })
#Html.DropDownList("credential_id", null, htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.credential_id, "", new { #class = "text-danger" })
#Html.LabelFor(model => model.credential_status_id, "credential_status_id", htmlAttributes: new { #class = "control-label col-md-2" })
#Html.DropDownList("credential_status_id", null, htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.credential_status_id, "", new { #class = "text-danger" })
<script>
$(document).ready(function () {
$("#btnSubmit1").click(function () {
$("#loaderDiv").show();
var myModelBody1 = $("#myForm").serialize();
if (!$("#myForm").valid()) {
return false;
}
$.ajax({
type: "POST",
url: "#Url.Action("index", "exams")",
data: myModelBody1,
success: function () {
$("#loaderDiv").hide();
$('#myModalAddEdit').modal('hide');
window.location.href = "#Url.Action("index", "exams")";
}
});
});
});
Original View: Modal
<div class="modal fade" id="myModalAddEdit">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
×
<h3 class="modal-title"><strong style="color:#ff9c21">EDIT </strong> Exam</h3>
</div>
<div class="modal-body" id="myModelBody1">
</div>
<div class="modal-footer">
Update
Close
</div>
</div>
</div>
Original View: Modal Script
var AddEditExam = function (exam_id) {
var exam_id = exam_id;
var url = '#Url.Action("AddEditExam", "exams")?exam_id=' + exam_id;
//var url = "http://localhost/NAHP/exams/AddEditExam?exam_id="+exam_id;
$("#myModelBody1").load(url,
function() {
$("#myModalAddEdit").modal('show');
});
}
I'm trying to send an AJAX post to an MVC action result and pass a custom object (ContactInformationModel) over as the parameter for the action result. However the expected type of the parameter is apparently not correct because the parameter is always null. I thought this was possible but maybe it's not?
My action result is:
[HttpPost]
public ActionResult UpdateContactInformation(ContactInformationModel model)
{
...
}
My jQuery:
//Serialize the ContactInformationModel object
var formData = $('#frmSubmitContactInformation').serialize();
// Submit ajax call
$.ajax({
url: "/api/[Redacted]/UpdateContactInformation",
type: "POST",
data: { model: formData },
cache: false,
success: function (data) {
if (data.Success) {
alert('success');
} else {
alert('fail');
}
}
});
My markup (ASP.NET MVC View):
#model [Redacted].Output.ContactInformationModel
<form id="frmSubmitContactInformation">
Add contact information to your project <button type="button" class="strip-button js-contact-launch js-edit-toggle"><span class="icon icon-edit"></span></button> <button class="btn btn--small btn--green add-half-left-margin js-submit-btn-contactinfo js-contact-launch js-edit-toggle hidden" type="submit">#Translation.Text("done")</button>
#*Done Button*#
<div class="js-contact-drawer hidden">
<div class="reveal-output__form column column--no-vert-padding add-half-bottom-margin add-half-top-margin form-group">
<div class="content-block">
#* First/Last/Company Name *#
<div class="content-block__third-column">
#Html.LabelFor(x => x.FirstName)
#Html.TextBoxFor(x => x.FirstName,
new
{
#Value = Model == null ? "" : Model.FirstName,
#class = "form-control"
})
</div>
<div class="content-block__third-column">
#Html.LabelFor(x => x.LastName)
#Html.TextBoxFor(x => x.LastName,
new
{
#Value = Model == null ? "" : Model.LastName,
#class = "form-control"
})
</div>
<div class="content-block__third-column">
#Html.LabelFor(x => x.CompanyName)
#Html.TextBoxFor(x => x.CompanyName,
new
{
#Value = Model == null ? "" : Model.CompanyName,
#class = "form-control"
})
</div>
</div>
<div class="content-block">
#* Email/Phone *#
<div class="content-block__third-column">
#Html.LabelFor(x => x.EmailAddress)
#Html.ValidationMessageFor(x => x.EmailAddress)
#Html.TextBoxFor(x => x.EmailAddress,
new
{
#Value = Model == null ? "" : Model.EmailAddress,
#class = "form-control"
})
</div>
<div class="content-block__third-column">
#Html.LabelFor(x => x.PhoneNumber)
#Html.ValidationMessageFor(x => x.PhoneNumber)
#Html.TextBoxFor(x => x.PhoneNumber,
new
{
#Value = Model == null ? "" : Model.PhoneNumber,
#class = "form-control"
})
</div>
</div>
<div class="content-block">
#* Address 1/Address 2 *#
<div class="content-block__third-column">
#Html.LabelFor(x => x.Address1)
#Html.TextBoxFor(x => x.Address1,
new
{
#Value = Model == null ? "" : Model.Address1,
#class = "form-control"
})
</div>
<div class="content-block__third-column">
#Html.LabelFor(x => x.Address2)
#Html.TextBoxFor(x => x.Address2,
new
{
#Value = Model == null ? "" : Model.Address2,
#class = "form-control"
})
</div>
</div>
<div class="content-block">
#* City/State/Zip*#
<div class="content-block__third-column">
#Html.LabelFor(x => x.City)
#Html.TextBoxFor(x => x.City,
new
{
#Value = Model == null ? "" : Model.City,
#class = "form-control"
})
</div>
<div class="content-block__third-column">
#Html.LabelFor(x => x.State)
#Html.DropDownListFor(x => x.State, AddressHelper.GetUnitedStatesListItems(), Translation.Text("state"), new {#class = "custom-select"})
</div>
<div class="content-block__third-column">
#Html.LabelFor(x => x.PostalCode)
#Html.ValidationMessageFor(x => x.PostalCode)
#Html.TextBoxFor(x => x.PostalCode,
new
{
#Value = Model == null ? "" : Model.PostalCode,
#class = "form-control"
})
</div>
</div>
<input type="hidden" name="ProjectId" value="#Model.ProjectId" />
</div>
</div>
</form>
I'm positive that the class referenced in the view is the exact same as I am referencing in the controller. Also, the JS runs fine itself. What could be the issue?
Paul,
The issue is your data object. You need to directly post your serialized form object as data.
$.ajax({
url: "/api/[Redacted]/UpdateContactInformation",
type: "POST",
data: formData,
cache: false,
success: function (data) {
if (data.Success) {
alert('success');
} else {
alert('fail');
}
}
});
My Drop-Downs works well the problem is when I want to save my form.
here is my controller
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "Id,TourId,StartDate,EndDate")] TourDate tourDate)
{
if (ModelState.IsValid)
{
db.TourDates.Add(tourDate);
db.SaveChanges();
return RedirectToAction("Index", "Home");
}
ViewBag.TourId = new SelectList(db.Tours, "Id", "TourName", tourDate.TourId);
return RedirectToAction("Index", "test");
}
[HttpPost]
public JsonResult GetT(int? id)
{
var tours = db.Tours.Where(e => e.CountryId == id).ToList()
.Select(e => new
{
Id = e.Id,
TourName= e.TourName
}).ToList();
return Json(tours);
}
and here is My form. in this From, selecttag with id=TourId is filling with data in ajax from the outer drop down dropdownId and it works fine
#Html.DropDownList("dropdownId",
Model.Countries.Select(m => new SelectListItem
{
Value = m.Id.ToString(),
Text = m.CountryName
}),
new { #class = "form-control" })
#using (Html.BeginForm("Create", "test"))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>TourDate</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.TourDate.TourId, "TourId", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
<select class="form-control" id="TourId"></select>
#Html.ValidationMessageFor(model => model.TourDate.TourId, "", new { #class = "text-danger" })
</div>
</div>
<br />
<div class="form-group">
#Html.LabelFor(model => model.TourDate.StartDate, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.TourDate.StartDate, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.TourDate.StartDate, "", new { #class = "text-danger" })
</div>
</div>
<br />
<div class="form-group">
#Html.LabelFor(model => model.TourDate.EndDate, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.TourDate.EndDate, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.TourDate.EndDate, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
the problem is when I submit the form no diffrent which Tour is chosen always there is TourId=0.
Appreciate any help and also here is the ajax if needed
$("#dropdownId").change(function () {
$('#TourId').empty();
var countrySelected = $(this).val();
$.ajax
({
url: '/test/GetT/' + countrySelected,
type: 'POST',
data: {
'countryId': countrySelected
},
success: function (data)
{
var $select = $('#TourId');
for (var i = 0; i < data.length; i++)
{
$('<option/>').attr('value', data[i].Id).html(data[i].TourName).appendTo('#TourId');
}
}
});
});
The reason your second <select> element does not submit a value is because it does not have a name attribute. It would need to be
<select class="form-control" name="TourDate.TourId" id="TourId"></select>
However there are multiple other errors and problems with your code. To note just a couple of them:
The model in your view is is not typeof TourDate (its a model
containing a property which is TourDate) so none of your controls
can be bound to your TourDate tourDate parameter in the POST
method (the model in the parameter needs to be the same as the model
in the view, or you need to use the [Bind(Prefix = "TourDate")]
attribute and you also need to remove the [Bind(Include = "..")]
attribute).
Your not getting client side validation associated with your
dropdownlists and in the POST method, if ModelState is invalid,
your just redirecting (the user would just assume the object has
been saved and not understand what is going on). You need to return
the view so errors can be corrected, but in your case, the values
the user has entered will be reset to the defaults (an annoying user
experience).
Your editing data, so you should always use a view model and in the controller method you need to populate the SelectList's to account for initial values and edited values (for when you need to return the view). You code should be
public class TourDateVM
{
[Required(ErrorMessage = "Please select a country")]
[Display(Name = "Country")]
public int? SelectedCountry { get; set; }
[Required(ErrorMessage = "Please select a tour")]
[Display(Name = "Country")]
public int? SelectedTour { get; set; }
[Required(ErrorMessage = "Please enter a start date")]
[Display(Name = "Start date")]
public DateTime? StartDate { get; set; }
.... // ditto above for EndDate
public IEnumerable<SelectListItem> CountryList { get; set; }
public IEnumerable<SelectListItem> TourList { get; set; }
}
And in the controller
public ActionResult Create()
{
TourDateVM model = new TourDateVM();
ConfigureViewModel(model);
return View(model);
}
[HttpPost]
public ActionResult Create(TourDateVM model)
{
if (!ModelState.IsValid)
{
ConfigureViewModel(model);
return View(model);
}
TourDate tour = new TourDate()
{
TourId = model.SelectedTour,
StartDate = model.StartDate,
EndDate= model.EndDate
};
db.TourDates.Add(tour);
db.SaveChanges();
return RedirectToAction("Index", "Home");
}
private ConfigureViewModel(TourDateVM model)
{
var counties = db.Countries;
model.CountryList = new SelectList(counties, "ID", "Name"); // adjust to suit your property names
if (model.SelectedCountry.HasValue)
{
var tours = db.Tours.Where(e => e.CountryId == model.SelectedCountry);
model.TourList = new SelectList(tours, "Id", "TourName");
}
else
{
model.TourList = new SelectList(Enumerable.Empty<SelectListItem>());
}
}
and finally in the view (note that both dropdownlists need to be inside the <form> element)
#model TourDateVM
....
#using Html.BeginForm())
{
....
<div class="form-group">
#Html.LabelFor(m => m.SelectedCountry, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(m => m.SelectedCountry, Model.CountryList, "- Please select -", new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.SelectedCountry, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.SelectedTour, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(m => m.SelectedTour, Model.TourList, "- Please select -", new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.SelectedTour, "", new { #class = "text-danger" })
</div>
</div>
....
}
and the script should be
var url = '#Url.Action("GetT")'; // assumes its in the same controller
var tours = $('#SelectedTour');
$('#SelectedCountry').change(function() {
tours.empty();
$.post(url , { id: $(this).val() }, function(data) {
if (!data) {
return;
}
tours.append($('<option></option>').val('').text('- Please select -'));
$.each(data, function(index, item) {
tours.append($('<option></option>').val(item.Id).text(item.TourName));
});
});
})
I have a parent View & a child View.
When posing with the Ajax.BeginForm, I'm expecting back the entire parent view plus the results of the partial view updated. Only the results of the partial view is displayed.
In addition, the "OnSuccess" method doesn't seem to be getting hit as I'm debugging.
Can someone please tell me what I'm doing incorrecty?
Controller:
public class HomeController : Controller
{
private DAL db = new DAL();
public ActionResult Index()
{
ViewBag.Message = "Welcome to YeagerTech!";
return View();
}
// GET: Categories/Create
public ActionResult Create()
{
return View();
}
// POST: Categories/Create
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Create(Category category)
{
if (ModelState.IsValid)
{
try
{
await db.AddCategoryAsync(category);
}
catch (System.Exception ex)
{
throw ex;
}
}
return View(category);
}
public PartialViewResult ShowDetails()
{
//string code = Request.Form["txtCode"];
Category cat = new Category();
//foreach (Product p in prodList)
//{
// if (p.ProdCode == code)
// {
// prod = p;
// break;
// }
//}
cat.CategoryID = 1;
cat.Description = "Financial";
return PartialView("_ShowDetails", cat);
}
}
Parent View
#model Models.Models.Category
#{
ViewBag.Title = "Create Category";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Create Category</h2>
#using (Ajax.BeginForm("ShowDetails", "Home", new AjaxOptions
{
HttpMethod = "POST",
UpdateTargetId = "div1",
InsertionMode = InsertionMode.Replace,
OnSuccess = "OnSuccess",
OnFailure = "OnFailure"
}, new { #class = "form-horizontal" }))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary()
<div class="body-content">
<h4>Category</h4>
<hr />
<div class="form-group">
<div class="col-offset-1 col-lg-11 col-md-11 col-sm-11 col-xs-11">
#Html.EditorFor(model => model.Description, new { htmlAttributes = new { #class = "form-control", #placeholder = "Description" } })
#Html.ValidationMessageFor(model => model.Description, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-lg-11 col-md-11 col-sm-11 col-xs-11">
<button type="submit" id="btnCategoryCreate" class="btn btn-primary"><span class="glyphicon glyphicon-save"></span>Create</button>
</div>
</div>
</div>
}
<div id="div1">
</div>
#*<div>
#Html.ActionLink("Back to List", "Index")
#Html.Hidden("categoryCreateUrl", Url.Action("Create", "Home"))
</div>*#
#section Scripts {
<script>
$(document).ready(function ()
{
function OnSuccess(response)
{
$('#form1').trigger("reset");
}
//if (typeof contentCreateCategory == "function")
// contentCreateCategory();
});
</script>
}
Partial View
#model Models.Models.Category
<h1>Cat Details</h1>
<h2>
Cat Code: #Model.CategoryID<br />
Cat Name: #Model.Description<br />
</h2>
EDIT # 1
Parent & child view displayed (due to a missing JS file, thanks to the mention of Stephen), plus was able to programmatically clear out the form with the OnSuccess method.
I had thought since that was JS, it needed to go in the Scripts section, but did not recognize it there.
Here is the finished code.
#using (Ajax.BeginForm("ShowDetails", "Home", new AjaxOptions
{
HttpMethod = "POST",
UpdateTargetId = "div1",
InsertionMode = InsertionMode.Replace,
OnSuccess = "OnSuccess",
OnFailure = "OnFailure"
}, new { #id = "frm1", #class = "form-horizontal" }))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary()
<div class="body-content">
<h4>Category</h4>
<hr />
<div class="form-group">
<div class="col-offset-1 col-lg-11 col-md-11 col-sm-11 col-xs-11">
#Html.EditorFor(model => model.Description, new { htmlAttributes = new { #class = "form-control", #placeholder = "Description" } })
#Html.ValidationMessageFor(model => model.Description, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-lg-11 col-md-11 col-sm-11 col-xs-11">
<button type="submit" id="btnCategoryCreate" class="btn btn-primary"><span class="glyphicon glyphicon-save"></span>Create</button>
<button type="reset" id="btnClear" class="btn btn-default"><span class="glyphicon glyphicon-eye-close"></span>Clear</button>
</div>
</div>
</div>
}
<div id="div1">
</div>
<script type="text/javascript">
function OnSuccess(response)
{
$('#frm1').trigger("reset");
}
function OnFailure(response)
{
alert("Whoops! That didn't go so well did it?");
}
</script>
A bit late for answer, but yet it might help someone else.
The issue might be that the javascript files required for Ajax.BeginForm are not loaded in your page.
Microsoft.jQuery.Unobtrusive.Ajax
Nuget package to search for
<package id="Microsoft.jQuery.Unobtrusive.Ajax" version="3.2.3" targetFramework="net45" />
of course that the version might differ.
Add reference to the page after your jQuery and it should work.