ASP.NET MVC caching and IoS safari - ios

I have a Controller like
[OutputCache(Location = System.Web.UI.OutputCacheLocation.Any, VaryByParam = "category", Duration = 60)]
public ActionResult Search(string keywords, string location, string category)
{
//... return View etc..
}
and ajax request on this view
function refreshPager(pageNum, nextOper) {
$.ajax({
url: String.format("/Adv/GetPagesData?currentPage={0}&SortBy={1}&keywords={2}&location={3}&country={4}&category={5}&minPrice={6}&maxPrice={7}&type={8}&condition={9}", pageNum, $("#SortBy option:selected").text(), $("#keywords").val(), $("#id-location").val(), $("#Country option:selected").val(), $("#search-category option:selected").val(), $("#minPrice").val(), $("#maxPrice").val(), $("#ajaxTabs li[class='active']").attr("id"), $("#condition option:selected").val()),
method: 'GET',
datatype: 'json',
data: { query: 'test' },
success: function (pdata) {
pagedata = pdata;
maxPages = pdata.length;
if (pageNum < 1) pageNum = 1;
if (pageNum > maxPages) pageNum = maxPages;
currentPage = pageNum;
ko.mapping.fromJS(pagedata, {}, viewModel.PagedItems);
$(".pageItem").removeClass("selectedItem");
$(".pageItem:eq(" + pageNum + ")").addClass("selectedItem");
}
}).fail(function () { alert('Ошибка получения данных, попробуйте еще раз') }).success(function () {
count = 0;
$('.pager-btn').each(function (index, el) {
if (el.innerHTML == pageNum) {
$(el.parentNode).addClass("active");
count++;
}
});
if (count == 0) {
$('#NotFound').show();
} else {
$('#NotFound').hide();
}
nextOper(currentPage);
});
}
thats fine works in all Windows browsers but fails in IoS Safari.
When caching attribute is off then it's ok in Safari too.
May be someone got that problem too?

The following will prevent all future AJAX requests from being cached, regardless of which jQuery method you use ($.get, $.ajax, etc.)
$.ajaxSetup({ cache: false });
Reference Link : https://stackoverflow.com/a/7750483/3041974

Related

JQuery ajax call blocks RedirectToAction

I have a view with an ajax call:
$.ajax({
url: "CreateChecklistCopies",
type: "POST",
data: JSON.stringify(drivers),
async: false,
contentType: "application/json; charset=utf-8",
});
The controller action performs some tasks and redirects to the index method of the controller:
[HttpPost]
public IActionResult CreateChecklistCopies([FromBody] object i_vm)
{
var tmp = Newtonsoft.Json.JsonConvert.DeserializeObject<List<ChecklistCopyModel>>(i_vm.ToString());
int result = _obj.AddChecklistCopies(tmp);
if (result > 0)
return RedirectToAction("Index", new { SuccessMessage = "Checklists were successfully duplicated." });
else
return RedirectToAction("Index", new { ErrorMessage = "An error occurred when duplicating the checklist." });
}
The Index action is successfully executed but there's no forward to the index page happening:
[HttpGet]
public IActionResult Index(string FilterCreator, string salesPersonFilter, string SuccessMessage, string ErrorMessage)
{
if (FilterCreator == null)
{
FilterCreator = User.Identity.Name.Split("\\")[1];
}
else if (FilterCreator.ToLower() == "all")
{
FilterCreator = null;
}
var checklists = _obj.GetChecklists(true, FilterCreator, salesPersonFilter);
var salespersons = _obj.GetSalespersons();
var chlVm = _mapper.Map<List<ChecklistModel>, List<ChecklistListViewModel>>(checklists);
var ivm = new IndexViewModel
{
CheckLists = chlVm,
Salespersons = salespersons,
SuccessMessage = !string.IsNullOrEmpty(SuccessMessage) ? SuccessMessage : "",
ErrorMessage = !string.IsNullOrEmpty(ErrorMessage) ? ErrorMessage : ""
};
return View(ivm);
}
I played around with the async: false tag in the ajax call but that didn't help. Any ideas?
You cannot use RedirectToAction to action in an ajax call to redirect the entire page. Because the ajax response is limited to the ajax request scope only.
What you can do is return a json object instead of RedirectToAction like this:
[HttpPost]
public IActionResult CreateChecklistCopies([FromBody] object i_vm)
{
var tmp = Newtonsoft.Json.JsonConvert.DeserializeObject<List<ChecklistCopyModel>>(i_vm.ToString());
int result = _obj.AddChecklistCopies(tmp);
JsonResult result = new JsonResult(new JsonSerializerSettings());
if (result > 0)
result = Json(new { IsRedirect = True, RedirectUrl = '/controller/Index/...', SuccessMessage = "Checklists were successfully duplicated." });
else
result = Json(new { IsRedirect = True, RedirectUrl = '/controller/Index/...', SuccessMessage = "An error occurred when duplicating the checklist." });
return result;
}
Then in the ajax call do this:
$.ajax({
url: "CreateChecklistCopies",
type: "POST",
data: JSON.stringify(drivers),
dataType: 'JSON',
async: false,
}).done(function (response) {
if (response != null) {
window.location = response.RedirectUrl;
//You can also use the IsRedirect and SuccessMessage property as needed
} else {
alert('There was a problem processing the request.');
}
}).fail(function () {
alert('There was a problem processing the request.');
});

Unable to send array data using ajax with ASP.NET Core and Entity Framework Core

I am trying to send array to the controller but it's blank in the controller parameter.
Ajax function is:
$('#pending').click(function () {
SaveTestResult("/Reception/PatientTests/SavePendingTest");
});
function SaveTestResult(url) {
var pid = $('.patientId').attr('id');
var tid = "";
var tval = "";
var tpid = "";
var tests = [];
$("table > tbody > tr").each(function () {
testId = $(this).find('.tid').val();
if (typeof (testId) != "undefined") {
tid = testId;
}
var rowText = ""
$(this).find('td').each(function () {
tpid = $(this).find('.tpId').val();
tval = $(this).find('.result').val();
if (typeof (tpid) != "undefined") {
tests.push({ PatientId: pid, TestId: tid, TestParameterId: tpid, TestValue: tval });
}
});
});
// alert(JSON.stringify(tests));
$.ajax({
type: "POST",
url: url,
data: JSON.stringify(tests),
contentType: "application/json",
headers: { "RequestVerificationToken": $('input[name="__RequestVerificationToken"]').val() },
success: function (data) {
alert(data);
},
error: function (e) {
alert('Error' + JSON.stringify(e));
}
});
}
This is the controller method:
[HttpPost]
[Route("Reception/PatientTests/SavePendingTest")]
public async Task<IActionResult> SavePendingTest(List<PendingTestResult> pendingTestResult)
{
if (ModelState.IsValid)
{
foreach (PendingTestResult ptr in pendingTestResult)
{
_db.Add(ptr);
await _db.SaveChangesAsync();
}
// return new JsonResult("Index");
}
return new JsonResult(pendingTestResult); ;
}
But when run the code I see data array filled but inside of the SavePendingTest action, pendingTestResult is empty and not filled! I also tried the [FromBody] tag inside action params, but it does not work either!
Help me resolve this
you are sending a string with no names so the controller can not get the values.
change you code to
$.ajax({
type:"POST",
url:url,
data:test
...
});
the test should be an object not a string.
You can pass the list of objects by :
$.ajax({
type: "POST",
url: "Reception/PatientTests/SavePendingTest",
data: { pendingTestResult: tests },
headers: { "RequestVerificationToken": $('input[name="__RequestVerificationToken"]').val() },
success: function (data) {
alert(data);
},
error: function (e) {
alert('Error' + JSON.stringify(e));
}
});
pendingTestResult in data:{ pendingTestResult: tests } matches the parameter name on action and remove the contentType setting .

How do we bind the data in kendo?

function showCopy() {
var arr = [];
var data = $("#PlanDetailGrid").data("kendoGrid").dataSource.data();
for (var i >
= 0; i < data.length; i++) {
if (arr.indexOf(data[i].SessionName) === -1) {
arr.push(data[i].SessionName);
}
}
You can use this syntax
$('#PlanDetailGrid').data('kendoGrid').dataSource.data(result);//result is the data in json format
From the controller you can return the result as Json and bind it direclty using an ajax like
$.ajax({
type: "post",
datatype: "json",
contenttype: "application/json",
url: "/Controller/getResult",
success: function (result) {
if (result.Data.length > 0) {
$('#PlanDetailGrid').data('kendoGrid').dataSource.data(result.Data);
}
else {
$("#PlanDetailGrid").data("kendoGrid").dataSource.data([]);
}
}
});
in Controller
public ActionResult getResult([DataSourceRequest]DataSourceRequest request)
{
//get the result list
DataSourceResult result = lst.ToDataSourceResult(request);//lst is your resultant list
var jsonResult = Json(result, JsonRequestBehavior.AllowGet);
return jsonResult;
}

Posting form data from Partial view to controller using ajax

I have a jquery grid that has a list of Employee Records.To edit the records there is a link on each row.On click of that A jquery model popup opens and loads the partial view to show and edit the data.But on click of the button(custom button not the jquery model button) on the popup(that loads a partial view),the client side validation using dataAnnotation does not work. If I make a submit form like:-
$("#btnUpdate).submit(function (e) {
e.preventDefault();
var $form = $(this);
if ($form.valid()) {
//Add ajax call
}
});
Then after submit it redirects to:- { ../Employee/Edit/EmployeeId } where it shows a blank screen as I dont have any view for this.
I want that after the form post it should just refresh the jquery grid.
public PartialViewResult _CreateSupplier()
{
return PartialView(new Supplier());
}
[HttpPost]
public JsonResult _CreateSupplier(Supplier model)
{
//Validation
return Json(new
{
status = transactionStatus,
modelState = ModelState.GetModelErorrs()
}, JsonRequestBehavior.AllowGet);
}
Form post jquery method
$('#create-supplier').submit(function (e) {
e.preventDefault();
var $form = $(this);
if (!ModelIsValid($form))
return;
AjaxPost($form.serialize(), '#Url.Action("_CreateSupplier")', function (result) {
if (result.status == 0) {
$form[0].reset();
//Success
var grid = $("#gridSupplier").data("kendoGrid");
grid.dataSource.read();
} else if (result.status == 1)
AddFormErrors($form, result);
else if (result.status == 2)
//error;
});
});
Checking model method is valid and if invalid adding errors to form
function ModelIsValid(form) {
var validator = $(form).validate(); // obtain validator
var anyError = false;
form.find("input").each(function () {
if (!validator.element(this)) { // validate every input element inside this step
anyError = true;
}
});
if (anyError)
return false; // exit if any error found
return true;
}
function AddFormErrors(form, errors) {
for (var i = 0; i < errors.modelState.length; i++) {
for (var j = 0; j < errors.modelState[i].errors.length; j++) {
var val = $(form).find("[data-valmsg-for='" + errors.modelState[i].key + "']");
if (val.html().length > 0) {
$(form).find("[for='" + errors.modelState[i].key + "']").html(errors.modelState[i].errors[j]);
} else {
val.html('<span for="' + errors.modelState[i].key + '" generated="true" class="" style="">' + errors.modelState[i].errors[j] + '</span>');
}
}
}
}
Ajax post method:
function AjaxPost(postData, url, callback) {
$.ajax({
url: url,
type: 'POST',
data: postData,
dataType: 'json',
success: function (result) {
if (callback) callback(result);
}
});
}
And last c# generic method which checks returns model state errors
public static IEnumerable<object> GetModelErorrs(this ModelStateDictionary modelState)
{
return modelState.Keys.Where(x => modelState[x].Errors.Count > 0)
.Select(x => new {
key = x,
errors = modelState[x].Errors.Select(y => y.ErrorMessage).ToArray()
});
}
Hope answer is useful...

MVC: pass parameter to action using Jquery.ajax()

I'm pretty new to MVC. I need to make ajax call to an Action with parameters using html.Action(). I'm unable to pass this..
Hope it will be helpful for other MVC begineers as well..
HTML:
<%: Html.ActionLink("Add Race", "AddRace",
new {eventId = Model.EventId, fleetId=Model.SelectedFleet.ID},
new{#onclick=string.Format("return checkFleetAddedandScroing()")}) %>
Jquery:
function checkFleetAddedandScroing() {
debugger;
$.ajax({
type: "GET",
url: '<%=Url.Action("CheckFleetExists")%>',
dataType: "json",
cache: false,
success: function (data, textStatus) {
data = eval("(" + data + ")");
if (data == true) {
return true;
}
else {
alert("Cannot Add race becasue you have not yet added any fleets and fleet scoring is checked.");
return false;
}
}, //success
error: function (req) {
}
});
}
Action:
public JsonResult CheckFleetExists(Guid fleetId )
{
bool exists = false;
try
{
exists = !db.Races.Any(r => r.FleetID == fleetId);
}
catch
{
}
return Json(exists, JsonRequestBehavior.AllowGet);
}
I need to pass fleetid to action which is in Model.SelectedFleet.ID. Its being used somewhere on pages. But i'm unable to use that somehow..
please suggest where i'm doing wrong...
It looks like you are trying to invoke a controller action using AJAX when the link is clicked and depending on the result of this call either allow the user to be redirected to the actual AddRace action or be prompted with an error message.
The problem with your code is that you are attempting to return true/false from within the success AJAX callback which doesn't make any sense. You need to always return false from the click callback and inside the success callback, depending on the returned value from the server, redirect manually using the window.location.href function.
HTML:
<%: Html.ActionLink(
"Add Race",
"AddRace",
new {
eventId = Model.EventId,
fleetId = Model.SelectedFleet.ID
},
new {
data_fleetid = Model.SelectedFleet.ID,
#class = "addRace"
}
) %>
Jquery:
<script type="text/javascript">
$(function () {
$('.addRace').click(function (evt) {
$.ajax({
type: 'GET',
url: '<%= Url.Action("CheckFleetExists") %>',
cache: false,
data: { fleetId: $(this).data('fleetid') },
success: function (data) {
if (data.exists) {
// the controller action returned true => we can redirect
// to the original url:
window.location.href = url;
}
else {
alert("Cannot Add race becasue you have not yet added any fleets and fleet scoring is checked.");
}
},
error: function (req) {
}
});
// we make sure to cancel the default action of the link
// because we will be sending an AJAX call
return false;
});
});
</script>
Action:
public ActionResult CheckFleetExists(Guid fleetId)
{
bool exists = false;
try
{
exists = !db.Races.Any(r => r.FleetID == fleetId);
}
catch
{
}
return Json(new { exists = exists }, JsonRequestBehavior.AllowGet);
}
Remark: inside your AddRace controller action don't forget to perform the same verification as you are doing inside your CheckFleetExists. The user could simply disable javascript and the AJAX call will never be done.
change your action like this :
public JsonResult CheckFleetExists(string fleetId)
{
var fleetGuid = Guid.Parse(fleetId);
bool exists = false;
try
{
exists = !db.Races.Any(r => r.FleetID == fleetGuid );
}
catch
{
}
return new JsonResult{ Data = exists};
}
and change you ActionLink so :
<%: Html.ActionLink("Add Race", "AddRace",
new {eventId = Model.EventId, fleetId=Model.SelectedFleet.ID},
new{onclick=string.Format("return checkFleetAddedandScroing({0})",Model.SelectedFleet.ID)}) %>
and your script block may look something like this :
function checkFleetAddedandScroing($fleetId) {
$.ajax({
type: "POST",
url: '<%=Url.Action("CheckFleetExists")%>',
dataType: "json",
data : { "fleetId" : $fleetId },
cache: false,
success: function (data, textStatus) {
data = eval("(" + data + ")");
if (data == true) {
return true;
}
else {
alert("Cannot Add race becasue you have not yet added any fleets and fleet scoring is checked.");
return false;
}
}, //success
error: function (req) {
}
});
}
Problem was in answers that url to action was not complete..i did it using this way
function checkFleetAddedandScroing() {
// debugger;
$.ajax({
type: "POST",
url: '<%=Url.Action("CheckFleetExists", new {eventId=Model.EventId})%>',
dataType: "json",
cache: false,
success: function (data, textStatus) {
data = eval("(" + data + ")");
if (data == true) {
return true;
}
else {
alert("Cannot Add race becasue you have not yet added any fleets and fleet scoring is checked.");
return false;
}
}, //success
error: function (req) {
}
});
}

Resources