Timeout issue for long requests on ajax POST - asp.net-mvc

so I have a .NET MVC project with an Update controller called from an Ajax POST that can take a long time to run which causes a timeout exception.
When I debug it on my local machine it runs fine, however - when I publish it to my azure website and update it from there the request never successfully completes and Chrome's console reports:
POST http://mysiteaddress/Admin/UpdateLibrary/Update?Length=13 504 (Proxy Timeout ( This operation returned because the timeout period expired. ))
Attempting the same operation on a remote desktop within Firefox causes the console to report:
[07:42:13.856] POST http://mysiteaddress/Admin/UpdateLibrary/Update?Length=13 **[HTTP/1.1 502 Bad Gateway 182940ms]**
I've tried setting a long timeout within my web.config file
<httpRuntime executionTimeout="2000"/>
and within the body of my ajax call
$.ajax({
url: this.action,
type: 'POST',
data: $(this).serialize(),
success: function (data) {
document.write(data);
},
failure: function (XMLHttpRequest, textStatus, errorThrown) {
console.log(XMLHttpRequest);
console.log(textStatus);
console.log(errorThrown);
},
timeout: 2000000 //Milliseconds
});
But no joy.

So this is not really a fix, but a workaround. Instead of making a single long request I had my javascript repeatedly query an ActionResult that returned some json deciding whether my long running process had finished. When it had completed I redirect the browser to a results screen.
$.updateProgressbar = function () {
$.get('#Url.Action("GetStatus", "UpdateLibrary", new { countryId = countryId }, Request.Url.Scheme)', function (data) {
$('#progressbar').progressbar('value', data.progress)
if (data.currentItem != null) {
$('#currentWorkItem').text('#l12.View_Update_currentlyWorking' + data.currentItem);
}
if (data.progress == 100) {
window.location =
'#Url.Action("UpdateResults", "UpdateLibrary", new { countryId = countryId }, Request.Url.Scheme)';
} else {
setTimeout($.updateProgressbar, 5000);
}
});
};
$(function () {
$("#progressbar").progressbar({ value: 0 });
setTimeout($.updateProgressbar, 5000);
});

It looks like on your local network to external azure site, you are going out through a proxy/gateway server. Does your company have any block-lists or white-lists for allowed/disallowed websites that might be intercepting and blocking the request?

Related

Request returns 200 on Postman but 404 testing on website

I have built a simple Api that returns a few places with associated data, and everything works fine, but i have a more specific research method that also is working fine in testing phase using Postman. I've made a few requests in my web application and they receive expected result, but now I've come to the point where I need to call this method I made, which returns proper response on Postman but 404 on my web application when I log the response message.
This is how I make my request:
<script>
function getCities() {
var selectedRegion = document.getElementById("region_select").value;
$.ajax({
type: "GET",
url: '#Url.Action("ShowCitiesByRegion", "ClientTourism")',
accepts: "/",
data: {
regionId: selectedRegion
},
success: function (data) {
$('#city_select_div').html(data);
},
failure: function (response) {
console.log(response.responseText);
},
});
console.log(selectedRegion);
}
</script>
This request calls up my controller, which looks like this:
public async Task<IActionResult> ShowCitiesByRegion(int regionId)
{
System.Diagnostics.Debug.WriteLine("ID DA REGIAO-" + regionId);
List<City> cities = new List<City>();
HttpClient httpClient = _api.Initial();
HttpResponseMessage httpResponseMessage = await httpClient.GetAsync("​api​/Cities​/region_cities​/region=" + regionId);
if (httpResponseMessage.IsSuccessStatusCode)
{
var response = httpResponseMessage.Content.ReadAsStringAsync().Result;
cities = JsonConvert.DeserializeObject<List<City>>(response);
System.Diagnostics.Debug.WriteLine("Cidades-" + cities);
}
else
{
System.Diagnostics.Debug.WriteLine("Erro" + httpResponseMessage);
}
return PartialView(cities);
}
This controller calls up the api and it never gets a SuccessStatusCode.
My API console run never indicates it is receiving the request, except when its coming from Postman.
I've narrowed the problem to the request making, although I checked every variable and every data is passing through view to controller as expected. It returns this response message:
Cant seem to figure why I am always getting 404 while doing this request from my web application.
Try to write the complete url in httpclient:
"https://hostname/api​/Cities​/region_cities​/region=" + regionId

Jquery (2) not calling AJAX Success call

I've the following generic PostTo method which can be used to post data to an ASP.NET MVc Controller, without the need for repetitive mark-up, I'm pretty sure it was working at one point, but for some reason, the success callback (any of it) doesn't get called.
Any thoughts? Everything looks right, and the server is responding with a valid 200 OK response.
It is however, an empty response. I tried a different (and empty) dataType value, but nothing changed.
function PostTo(controller, action, data, successCallback) {
$.ajax({
url: Settings.HostPath + controller + "/" + action,
type: "POST",
cache: false,
dataType: "json",
data: data,
success: function (data, textStatus, jqXHR) {
if (typeof (successCallback) != "undefined")
successCallback.call(this, data);
}
});
}
ajax method in your script, excepts json data from the server, but as you told in comments, your actions returns nothing (i thinks it's returns EmptyResult).
So, add any json result in your action:
public ActionResult Test()
{
return Json(new {Success = true});
}

JQuery AJAX Call to MVC action , asking the Credentials in Windows Server 2008R2

I have a jquery ajax POST to a MVC Action (which returns action result). In that i retrive record from DB and store in Session and return partial view result . On my machine this works well, when deployed it in Windows Server 2008 R2 , A popup appears in the browser asking me to enter credentials (authentication required).
The jquery call:
var data = $('#SearchForm').serialize();
window.location.hash = '#/' + data;
$.ajax({
url: '/PromotionManagement/PromotionsSearch',
type: 'POST',
data: data,
beforeSend: function (xhr) {
$('#search-result').hide();
$('#divresetCancel').hide();
$('#divwait').show();
// console.log('before sending request...');
},
error: function () {
//console.log("error processing request...");
},
success: function (data) {
debugger;
//console.log("successfully processed request...");
$('#search-result').html(data);
$('#search-result').show();
$('#divwait').hide();
$("#validation").html("");
if ($(data).html() == '\n No Records Found \n ') {
$('#divresetCancel').hide();
}
else {
$('#divresetCancel').show();
}
}
});
MVC Action :
[HttpPost]
public ActionResult PromotionsSearch(string list,string query)
{
//code to retrive the data from DB.
Session["SearchPerameters"] = objSearchPerameters;
return PartialView("PromotionsGrid", Promotions);
}
I referred this link and stopped storing the data in Session.
Even though it didn't work .
Can you pls suggest me what is missing..
any help can be greatly appreciated.
This issue got fixed by changing the AJAX call url: '/PromotionManagement/PromotionsSearch' [controllerName/ActionName] as 'PromotionsSearch' [Only Action Name].

jQuery.ajax reloads page instead of performing ajax request in Safari on iOS

I have a function being called on a page on a local apache instance (/test) which calls a subpage (/test/info) with jQuery.ajax and correctly makes an AJAX call and dynamically loads the content from the response on my desktop in FF, Safari, Chrome, but in the iOS emulator, no call is made and the page is refreshed.
window.getInfo = function ( event ) {
console.log('1) prior to $.ajax');
$.ajax({
url: 'http://localhost/test/info',
dataType: 'html',
beforeSend: function(xhr) {
console.log('2) beforeSend');
},
success: function(data, textStatus) {
console.log('3) success');
if ( textStatus == 'success' ) {
// doing stuff with data
}
}
}).always( function() { console.log('4) always'); });
};
From the desktop browsers all of the logs are printed and my apache server reports a request at /test, but on Safari in the iOS emulator, only the '1) prior to $.ajax' and '2) beforeSend' logs are printed and the next request made to apache is for /test.
Does anyone have any idea what is happening here, and how to make iOS behave itself?
UPDATE: When I add the async: false attribute to the ajax call, all the logs are printed, and the request is made, so that basically fixed the issue; however the page still reloads which I believe is a different issue related to event propagation on iOS.
All that is needed to make this work is a return false; from the handler function. See event.preventDefault() vs. return false for a more complete explanation, but basically "return false from within a jQuery event handler is effectively the same as calling both e.preventDefault and e.stopPropagation on the passed jQuery.Event object."
So a fully functional version of the above code is:
getInfo = function() {
$.ajax({
url: '/test/info',
dataType: 'html',
success: function(data, textStatus) {
if ( textStatus == 'success' ) {
// doing stuff with data
}
}
});
return false;
};
// The order of vv that string may be important
$(document).on('click touchend', '.getInfo', getInfo );

jQuery UI- How to prevent autocomplete menu from temporarily disappearing between keystrokes?

I'm using jQuery UI autocomplete with data from a remote datasource. My use case is really similar to the example here:
http://jqueryui.com/demos/autocomplete/#remote
The only difference is that I set my delay to 0. In between the keystrokes, the menu disappears for about 1/10th of a second ~100milli seconds prior to the updated autocomplete list being displayed.
Is there anyway I can prevent the menu from temporarily disappearing between keystrokes? A good use case is google's search, where between keystrokes, the suggestion box does not temporarily disappear.
IMO, it is not a good practice to set a delay of zero when using a remote datasource. It will send more requests than needed and surcharge the server with no benefit.
Anyway, I think you can achieve what you want by defining the source option as a callback yourself.
First a bit of explanaton. I suppose you are using the remote feature passing an url as the source for the plugin. The plugin actually wraps this into a callback implemented this way:
// in case the option "source" is a string
url = this.options.source;
this.source = function(request, response) {
if (self.xhr) {
self.xhr.abort();
}
self.xhr = $.ajax({
url: url,
data: request,
dataType: "json",
autocompleteRequest: ++requestIndex,
success: function(data, status) {
if (this.autocompleteRequest === requestIndex) {
response(data);
}
},
error: function() {
if (this.autocompleteRequest === requestIndex) {
response([]);
}
}
});
};
As you can see, if there is already an ajax request going on, it abords it. This happenning in your case as a request, as fast as your server can be, takes some time and your delay is zero.
if (self.xhr) {
self.xhr.abort();
}
This will actually execute the error callback of the aborted request that will execute itself the response callback with an empty dataset. If you look at the response callback, it closes the menu if data is empty:
_response: function(content) {
if (!this.options.disabled && content && content.length) {
...
} else {
this.close();
}
You can actually define your own source callback to make your ajax request yourself and change the default behavior by not aborting any pending request. Something like:
$('#autocomplete').autocomplete({
source: function(request, response) {
$.ajax({
url: url,
data: request,
dataType: "json",
success: function(data, status) {
// display menu with received dataset
response(data);
},
error: function() {
// close the menu on error by executing the response
// callback with an empty dataset
response([]);
}
});
}
});

Resources