I have a view Index, called from Index Action inside EnqueteController, which has all my javascript code in it. This view RenderPartial a form, _EnqueteForm which has all my form inputs. In my javascript section (in Index) I have the following:
#section Scripts{
<script type="text/javascript">
var IDLE_TIMEOUT = 10; //seconds
var _idleSecondsCounter = 0;
document.onclick = function () {
_idleSecondsCounter = 0;
};
document.onmousemove = function () {
_idleSecondsCounter = 0;
};
document.onkeypress = function () {
_idleSecondsCounter = 0;
};
window.setInterval(CheckIdleTime, 1000);
function CheckIdleTime() {
_idleSecondsCounter++;
if (oPanel)
oPanel.innerHTML = (IDLE_TIMEOUT - _idleSecondsCounter) + "";
if (_idleSecondsCounter >= IDLE_TIMEOUT) {
$.ajax({
cache: false,
url: '/Enquete/Inactive',
type: 'POST',
dataType: "json",
data: $('form').serialize(),
});
}
}
}
After 10 seconds of inactivity, it's calling Inactive action from Enquete Controller.
This action looks like this:
[HttpPost]
public ActionResult Inactive([System.Web.Http.FromBody] InfoFormulaireEnqueteModele m)
{
int userId = this.UserId();
LibraryEnquete.EnregistrerFormulaire(m, userId);
TransitionEtatPrecedent(m.HevEvenementID, userId);
return View("Logout");
}
My action is called correctly after 10s and it's calling LibraryEnquete.EnrigistrerFormulaire and also TransitionEtatPrecedent. But my problems are:
1) It wont change to the 'Logout' view
2) For some reason, my Inactive method is called from other page?! After one call, I stop the application and once I restart it, from the main page (which is not the EnqueteController Index page), it's calling the Inactive method like 20 times until I stop the application
Ajax calls do not handle redirect responses (http status code 3xx).
By returning the view to an ajax call, you are just getting the view rendered as string in the ajax success event handler.
In order for the browser to render the logout view, you can just proceed to submit the form without using ajax:
if (_idleSecondsCounter >= IDLE_TIMEOUT) {
$('form').submit();
}
If the form's action it's not poiting to /Enquete/Inactive, you can change the action before submiting the form:
if (_idleSecondsCounter >= IDLE_TIMEOUT) {
$('form').prop('action', '/Enquete/Inactive');
$('form').submit();
}
Related
I got Main View which contains table, on row click ajax request will be send.
$.ajax({
url: `/home/setViewBag/${id}`,
type: "get",
success: function (msg) {
$("#modal").html("");
$("#modal").append(msg);
modal.style.display = "block";
},
});
"SetViewBag"
[HttpGet]
[Route("setViewBag/{id}")]
public async Task<ActionResult> SetViewBag(int id)
{
ViewBag.Id = id;
return View("AjaxGrid");
}
AjaxGrid.cshtml
#using NonFactors.Mvc.Grid
#Html.AjaxGrid(
Url.Action("TestMethod", "Main", new { Id = ViewBag.Id }))
"TestMethod"
[HttpGet]
[Route("TestMethod/{id}")]
public async Task<ActionResult> TestMethod(int id)
{
return PartialView(await _service.Get(id));
}
PROBLEM: Ajax request append to my modal new div without TABLE
<div class="mvc-grid" data-url="/main/testMethod/1"></div>
As you can see on image, modal is empty
Modal should contains rendered table
#Html.Grid(Model).Build(columns =>
{
columns.Add(model => model.Id).Titled("Id");
columns.Add(model => model.Name).Titled("Name");
}).Pageable(pager =>
{
pager.PageSizes = new Dictionary<Int32, String> {{0, "All"}, {1, "1"}, {20, "20"}};
pager.ShowPageSizes = true;
pager.PagesToDisplay = 3;
pager.CurrentPage = 1;
pager.RowsPerPage = 1;
})
App: Asp.Net CORE 3.1
MVC-Grid v6.2.4
First of all there is a problem with your ajax call. You would like to return html to put it in your modal.
$.ajax({
url: `/home/setViewBag/${id}`,
type: "get",
dataType: 'html',
success: function (msg) {
$("#modal").html("");
$("#modal").append(msg);
modal.style.display = "block";
},
});
Then in controller you should return PartialView instead of View. I am not familiar with component you are using, but if it returns table you should just use in your success function $('#modal').html(msg); . If data is correctly returned from conroller and modal dialog is still empty, there is a problem with your modal setup. Make sure where you put your data.
I am trying to do an ajax request and depending on the ajax request results I will allow the form to submit to the controller. However everytime the ajax request runs I get the error message.
Here is my javascript function:
function CheckForValidation(e) {
var scholarshipRequest = $("#scholars").val();
var aidYearRequest = $("#aidYear").val();
var amountRequest = $("#amount").val();
$.ajax({
type: "POST",
url: '#Url.Action("Validate_ScholarshipRequest", "RequestController")',
data: {
scholarshipId: scholarshipRequest,
aidYear: aidYearRequest,
amount: amountRequest
}
}).success(function(response) {
if (!response.success) {
e.preventDefault();
alert(success);
} else {
e.preventDefault();
}
}).error(function() {
e.preventDefault();
alert("Error on Submission");
});
}
This function is called from here:
$("#SubmitTutorRequestFrm").submit(function(e) {
e.PreventDefault();
CheckForValidation(e);
});
I try to debug the code and put a breakpoint on Validate_ScholarshipRequest but that method never gets called. The method signature is:
public ActionResult Validate_ScholarshipRequest(string scholarshipId, string aidYear, string amount)
This is the start of my form:
#using (Html.BeginForm("SubmitScholarshipRequest", "Request", FormMethod.Post, new { id = "SubmitTutorRequestFrm" }))
Just to get this officially answered and "closed", this was caused by a syntax-error:
url: '#Url.Action("Validate_ScholarshipRequest", "RequestController")',
Controller should not be included in the controller name. The correct action would then be:
url: '#Url.Action("Validate_ScholarshipRequest", "Request")',
I have a panel with a header form and a detail form detail form consist of a grid and a form.
If the user clicks on save button which is in the header I have to take the value JDE present in the header as one parameter and check the REFNo present in each record present in the detailStore and make an ajax call.
If the data returned from the response is null I have to disable the save call.
Sample ajax call I am using in my code:
Ext.Ajax.request({
url: webContext + '/services/adjustment/accountsreceivableledger',
timeout: 120000,
method: 'GET',
params: {
addressNumber: jde,
documentNumber: r.data.customerInvoiceDebitNo
},
success: function(response) {
var returnedValue = Ext.decode(response.responseText);
if (returnedValue.data != null && returnedValue.data.length === 0) {
me.lookupReference('submit').disable();
Ext.Msg.alert('Submitting Error on Detail Reference number');
refValid = false;
me.getView().up('panel').ownerCt.unmask();
} else {
refValid = true;
}
return refValid;
}
});
Sample fiddle
Why don't you just concatenate all the ref numbers and pass to the server in one go?
var myRefParameter;
YourStore.each(function(r) {
if (myRefParameter!='')
myRefParameter +='|';
myRefParameter += r.get('RefField');
});
Ext.Ajax.request({
url: webContext + '/services/adjustment/accountsreceivableledger',
timeout: 120000,
method: 'GET',
params: {
addressNumber: jde,
documentNumber: myRefParameter //Pass it here
},
...........
Just split the Ref. Numbers on the server and do all the necessary validations.
As per your requirement,
I need to check all the return responses and if the response data is not null or Empty then only submit the call
For this you need to create a common ajax call function and call this function on save button for every record as present on store. You have to maintain one array for customerInvoiceDebitNo and one ajaxcount to check all response. You need to put bellow code on your save button click event.
You can modify below code basis of your requirement.
Code Snippet
var customerInvoiceDebitNo = '',
allCustomerInvoiceDebitNo = [],
ajaxCount = 0;
detailStore.each(function(r) {
customerInvoiceDebitNo = r.get('customerInvoiceDebitNo');
if (customerInvoiceDebitNo !== 0 && detlview.getViewModel().get('currentHeader').data.sourceDocuments[0].documentNumber !== customerInvoiceDebitNo) {
//call ajax request for per record
doApiCall({
addressNumber: jde,
documentNumber: customerInvoiceDebitNo
});
//Push customer invoice debit no in Array for checking response in Ajax request success.
allCustomerInvoiceDebitNo.push(customerInvoiceDebitNo);
//For checking number of ajax call.
ajaxCount++;
}
});
//This function will make ajax call for per record
function doApiCall(data) {
Ext.Ajax.request({
url: webContext + '/services/adjustment/accountsreceivableledger',
timeout: 120000,
method: 'GET',
params: data,
customerInvoiceDebitNo: data.customerInvoiceDebitNo,
success: function(response) {
ajaxCount--;
//When All ajax request response will get then unmask on view
if (ajaxCount == 0) {
me.getView().up('panel').ownerCt.unmask();
}
var returnedValue = Ext.decode(response.responseText);
if (returnedValue.data != null && returnedValue.data.length === 0) {
//Remove this current customerInvoiceDebitNo from array if response is not null.
Ext.Array.remove(allCustomerInvoiceDebitNo, this.customerInvoiceDebitNo);
//Initially submit button will be disable
//If all ajax request response is not null then array will be empty then we can make sumit button enable.
if (Ext.isEmpty(allCustomerInvoiceDebitNo)) {
}
}
}
});
}
//Initially submit button will be disable
//This function will enable submit button when all request reponse will not null or empty.
function doEnableSumbitButton() {
me.lookupReference('submit').setDisabled(false);
}
I hope this will guide or help you to achieve your requirement.
I am building a MVC3 web application and I am using knockoutjs. There are two views in the application. SetUpNewCompany and ManageAccount. To Set up a new company the user first enters the account number and clicks search. If the account number already exists the user can click on a button to go to the ManageAccount view. In the SetUpNewCompanyController I redirect using the RedirectToAction method. However, when the Index2 action in ManageAccount is executed the view is not displayed. If I type in the complete URL the view is displayed.
SetUpNewCompanyController.cs
[HttpPost]
public RedirectToRouteResult RedirectToManageAccount(string accountNumber)
{
return RedirectToAction("Index2", new RouteValueDictionary(new {controller=
"ManageAccount", companyId = "7e96b930-a786-44dd-8576-052ce608e38f" }));
}
This above is called by the function below when a button is clicked
self.redirectToManageAccount = function () {
var accountNumber = "7e96b930-a786-44dd-8576-052ce608e38f";
$.ajax({
type: "POST",
url: "/SetUpNewCompany/RedirectToManageAccount",
data: { accountNumber: accountNumber },
success: function (data) {
},
error: function () {
}
});
}
ManageAccountController.cs
public ActionResult Index2(String companyId)
{
var viewModel = new Models.Index();
List<String> compList = new List<String>();
compList.Add("MyCompany");
List<String> usersList = new List<String>();
usersList.Add("User1");
viewModel.Users = usersList;
viewModel.Companies = compList;
viewModel.CompanyId = companyId;
viewModel.Role = "Role1";
return View("ManageAccount",viewModel);
}
The URL that is generated is
http://localhost:53897/ManageAccount/Index2?companyId=7e96b930-a786-44dd-8576-
052ce608e38f
The console window in Firebug shows
GET http://localhost:53897/ManageAccount/Index2?companyId=7e96b930-a786-44dd-8576-
052ce608e38f 200 OK and the spinner keeps spinng
Also, how do I get the URL below instead of the one with querystring
http://localhost:53897/ManageAccount/Index2/7e96b930-a786-44dd-8576-052ce608e38f
Since you use AJAX to call the RedirectToManageAccount action method, you are responsible for handling its response yourself and as your success handler function is empty, you are effectively ignoring whatever arrives as a response.
If you want to force a redirect from within the AJAX response handler, I suggest
Modifying your action method as follows
[HttpPost]
public ActionResult RedirectToManageAccount(string accountNumber)
{
var redirectUrl = new UrlHelper(Request.RequestContext).Action("Index2", "ManageAccount", new { companyId = "7e96b930-a786-44dd-8576-052ce608e38f" });
return Json(new { Url = redirectUrl });
}
Updating your AJAX call in this way
self.redirectToManageAccount = function () {
var accountNumber = "7e96b930-a786-44dd-8576-052ce608e38f";
$.ajax({ type: "POST",
url: "/SetUpNewCompany/RedirectToManageAccount",
data: { accountNumber: accountNumber },
dataType: 'json',
success: function (response) {
window.location.href = response.Url;
},
error: function () {
}
});
}
As for your second question:
Also, how do I get the URL below instead of the one with querystring
http://localhost:53897/ManageAccount/Index2/7e96b930-a786-44dd-8576-052ce608e38f
You just have to define an appropriate route entry for this URL in your RegisterRoutes() function:
routes.MapRoute(null,
"ManageAccount/Index2/{companyId}",
new { controller = "ManageAccount",
action = "Index2" }
);
EDIT: As your AJAX call only serves to call an action method which causes a redirect, you can simplify it in a following way, provided you in this point (on the client side) know the companyId already:
self.redirectToManageAccount = function () {
var companyId = "12345";
window.location.href = '#(Html.ActionUri("Index2", "ManageAccount"))?companyId=' + companyId;
}
where I used this extension method
public static string ActionUri(this HtmlHelper html, string action, string controller)
{
return new UrlHelper(html.ViewContext.RequestContext).Action(action, controller);
}
I have an MVC application that I'm using various JsonResult endpoints to populate the javascript ViewModel.
I have been using several jQuery Ajax requests to populate the model, but I'd like as much of the inital model to be passed to the view on the server.
The ViewModel has 3-5 pieces (depending on where the user is in the application):
Basic page links, these don't change very often and could be the exact same throughout the entire user's session
User notifications.
User data.
(optional) Viewable data
(optional) misc data
I'm currently using this code to load the first three pieces:
$(document).ready(function () {
ko.applyBindings(viewModel);
#Html.Raw(ViewBag.Script)
// Piece 1. Almost always the same thing
postJSON('#Url.Action("HomeViewModelJson", "Home")', function (data) {
if (data == null)
return;
for (var i in data.Tabs) {
viewModel.tabs.push({ name: data.Tabs[i] });
}
for (var i in data.Buttons) {
viewModel.metroButtons.push({ name: data.MetroButtons[i] });
}
for (var i in data.Ribbons) {
viewModel.ribbons.push(data.Ribbons[i]);
}
ApplyButtonThemes();
});
});
// Piece 2. Changes constantly. OK as is
postJSON('#Url.Action("GetNotifications", "NotificationAsync")', function (nots) {
viewModel.notifications.removeAll();
ko.utils.arrayForEach(nots, function (item) {
item.readNotification = function () {
hub.markNotificationAsRead(this.Id);
return true;
};
viewModel.notifications.push(item);
});
});
// Piece 3. Changes but should also be loaded at startup
postJSON('#Url.Action("GetUser", "UserAsync")', function (user) {
viewModel.user(koifyObject(user));
});
postJSON = function(url, data, callback) {
if($.isFunction(data)) {
callback = data;
data = {};
}
$.ajax({
'type': 'POST',
'url': url,
'contentType': 'application/json',
'data': ko.toJSON(data),
'dataType': 'json',
'success': callback
});
};
I tried doing something like this, but I'm finding that by using the #Html.Action("HomeViewModelJson", "Home") is causing the HTTP headers to get changed and the whole page is sent as if it were JSON
(function (data) {
if (data == null)
return;
for (var i in data.Tabs) {
viewModel.tabs.push({ name: data.Tabs[i] });
}
for (var i in data.MetroButtons) {
viewModel.metroButtons.push({ name: data.MetroButtons[i] });
}
for (var i in data.Ribbons) {
viewModel.ribbons.push(data.Ribbons[i]);
}
ApplyMetroButtonThemes();
})('#Html.Action("HomeViewModelJson", "Home")');
What I'd like to do is use the existing JsonResult endpoints to get Json data into my ViewModel on the server side, before the page is sent to the user.
Are there any options that will allow me to do that w/o rewriting my controllers?
When rendering the main view you are using a view model, right? In this view model simply populate the properties that you don't want to be fetched with AJAX before returning the view:
public ActionResult Index()
{
MyViewModel model = ...
model.Prop1 = ...
model.Prop2 = ...
return View(model);
}
for example if you have the following action that is used for the AJAX requests:
public JsonResult GetProp1()
{
Property1ViewModel model = ...
return Json(model, JsonRequestBehavior.AllowGet);
}
you could use it from the main action to populate individual properties:
model.Prop1 = (Property1ViewModel)GetProp1().Data;
model.Prop2 = (Property2ViewModel)GetProp2().Data;
and then inside the corresponding view you could use the Json.Encode method to serialize the entire model into a JSON string:
#model MyViewModel
<script type="text/javascript">
var model = #Html.Raw(Json.Encode(Model));
// You could use model.Prop1 and model.Prop2 here
</script>
or you could also serialize individual properties if you don't need all of them:
#model MyViewModel
<script type="text/javascript">
var prop1 = #Html.Raw(Json.Encode(Model.Prop1));
</script>