Iztoksson
Iztoksson

Reputation: 990

Ajax call to controller takes a long time

I have a simple ajax call from a Javascript file to a MVC5 controller. This call takes approximately 2 seconds. The tasks both in javascript and controller are extremely simple. I cannot show my full code but I made performance measurements for the whole call stack.

Where does this delay come from if all the actions complete in less than 10ms? You can see in the image below where a TTFB is 2.12s, my controller clearly finishes this action sooner than 2,12s (2ms as per my perf test).

Did I miss anything like a network issue - doubtfully as this is all done on my dev PC. I also tried the same with a fully compiled application deployed to a standalone IIS server (UAT but still...) and the results are the same.

The only thing that comes to my mind is asp.net doing something after the controller method completes and before actually returning JSON data back to the browser?

Javascript execution:

1: 1.2000 milliseconds (get values)
2: 2.4000 milliseconds (validation)
3: 2.9000 milliseconds (just before Ajax call)
4: 2172.3 milliseconds (inside Ajax Success)
5: 2174.3 milliseconds (last step in Ajax Success)
6: 0, 0, 1 (see below, these are controller values)

Controller execution:

1: 0 milliseconds (Controller init, constructor completed)
2: 0 milliseconds (Action start)
3: 1 milliseconds (Action end (just before return)

Javascript code:

// previous steps omitted, you can see the times for steps 1-3.

$.ajax({
    type: "POST",
    url: $("#appPath").val() + "/MyController/TrivialAction",
    data: req,
    cache: false,
    global: false,
    success: function (response) {
        console.log("4: " + (performance.now() - t0) + " milliseconds.")

        // some code here...

        console.log("5: " + (performance.now() - t0) + " milliseconds.")

        console.log(response.StepsInCtrlr);
    },
    error: function (errorxhr, status, error) {
        BootBoxDiplayHtml(errorxhr.responseText);
    }
});

Here is the controller return method (as per Peter B answer)

return Json(new
    {
        IsError = resp.IsError,
        ErrorMessage = string.Join("<br>", resp.ErrorMessages),
        Amount = resp.Amount.ToString("n2")
    }, JsonRequestBehavior.AllowGet);

(not the exact request above, but a similiar one)

enter image description here

Upvotes: 0

Views: 2053

Answers (2)

Slicksim
Slicksim

Reputation: 7172

If you get consistent cold and warm long requests with missing time, then it could point to the IoC project you are using.

I have seen some of them taking 0.5s to resolve a request which means you lose time down a black hole.

I have experienced Ninject swallowing nearly 0.4s of time in a large scale app, way too much. I ported that project to SimpleInjector and it was near instantaneous.

And while SimpleInjector keeps you to a stricter rule set and doesn't provide some of the automatic configuration of dependencies, it does reward you for going that extra mile with a lightning quick resolution time. It is now my defacto standard when I am putting in IoC now.

Upvotes: 1

Peter B
Peter B

Reputation: 24136

What you call 'Action end (just before return)' does not at all mean that MVC is done:

  • If you specified return View(YourModel); then MVC renders the specified View to HTML using the Model object, and that takes time.

  • If you did something like return YourModel; or return Json(YourModel); then MVC will serialize YourModel to JSON. That might seem straightforward, but is it...? If YourModel happens to be a live Entity Framework object, then it may be that only during this phase Entity Framework realizes that it needs to generate and then fire its database queries in order to supply you with data. And only after that, the serialization can really start.

You need to investigate more what is happening out of sight and behind the scenes. Try constructing an actual ViewModel object that is disconnected from Entity Framework, and then do return YourViewModel; from the Action method. If you do so then you may see that processing-time shifts to code inside the Action method, instead of behind the scenes, and then you can try to optimize this.

Upvotes: 1

Related Questions