3

I'm in the process of removing jQuery in one of my asp.net mvc projects in favor of using straight vanilla JS. Now that I've replaced $.ajax POST calls with Fetch API calls, each call triggers a new session on the server.

This has been driving me up the wall for the past few days, and I've narrowed it down to specifically this switch from using jQuery Ajax to Fetch API. My new Fetch API calls work perfectly otherwise, still performing the needed server-side work. The just trigger a new server session once they return.

Obviously, this is a major issue, as my user session data keeps getting reset. Any idea as to why this happens? Or anyone know of any workarounds, while not having to revert back to using jQuery?

My previous 'jQuery'-based POST call:

Post(route, data) {
    $.ajax({
        type: 'POST',
        url: route,
        data: JSON.stringify(data),
        contentType: "application/json; charset=utf-8"
    }).done((result, statusText, jqXHR) => {
        return result;
    });
}

My new 'Fetch API'-based call:

async Post(route, data) {
    let response = await fetch(route, {
        method: 'POST',
        headers: {
            'Accept': 'application/json',
            'Content-type': 'application/json'
        },
        body: JSON.stringify(data)
    });
    let result = await response.json();
    return result;
}

In my Global.asax.cs:

protected void Session_Start(object o, EventArgs e) {
    Debug.WriteLine("Session_Start");
    HttpContext.Current.Session.Add("__MySessionData", new MySessionDataClass());
}

As I mentioned above, the Fetch API call works perfectly fine other than resetting my session, which I know from the Debug.WriteLine call. The jQuery Ajax call also works perfectly fine, and does not trigger a new session, however I'm trying to remove my dependency on jQuery.

Thoughts?

SLT
  • 61
  • 3
  • 6
  • 1
    Are the cookies sent to the server different in either case? – gunr2171 Jul 11 '18 at 18:10
  • @gunr2171 Good question. It didn't occur to me to check. It appears that the Asp.net session cookie is sent with the jQuery Ajax call, but it is not sent with the Fetch API call. Perhaps I'll have to tweak the Fetch API call to also send the session cookie... – SLT Jul 11 '18 at 18:15
  • @gunr2171 I just tweaked the Fetch API call to add `credentials: 'include'` in the options, so it now sends the session cookie, and that fixed the issue. If you want to put that as an answer, I'll accept it. Otherwise, I can self-answer the question. – SLT Jul 11 '18 at 18:22

2 Answers2

4

You're not passing in the ASP.NET_SessionId cookie with your custom request.

You are using fetch. By default it uses omit for the credentials. This means, as said on the MDN page:

By default, fetch won't send or receive any cookies from the server, resulting in unauthenticated requests if the site relies on maintaining a user session (to send cookies, the credentials init option must be set).

JQuery does send cookies, but only those on the same domain.

AJAX calls only send Cookies if the url you're calling is on the same domain as your calling script.
Source

To fix this, you need to tell fetch to send cookies. From this post:

fetch('/something', { credentials: 'same-origin' }) // or 'include'
gunr2171
  • 16,104
  • 25
  • 61
  • 88
2

Figured out the issue with the help of @gunr2171, so self-answering in case anyone else comes across a similar issue.

Turns out that my new Fetch API call was not sending the current Asp.net session cookie with the request, so the server would start a new session thinking that one didn't exist yet. Tweaking the Fetch API call to include credentials: 'include' in the options allows it to send the current session cookie and the server will no longer create a new one after every call.

For reference, my new Fetch API call now looks like:

async Post(route, data) {
    let response = await fetch(route, {
        method: 'POST',
        headers: {
            'Accept': 'application/json',
            'Content-type': 'application/json'
        },
        credentials: 'include',
        body: JSON.stringify(data)
    });
    let result = await response.json();
    return result;
}
SLT
  • 61
  • 3
  • 6