提取API调用导致新的Asp.net会话

时间:2018-07-11 18:08:14

标签: javascript c# jquery asp.net-mvc fetch-api

我正在我的一个asp.net mvc项目中删除jQuery,以支持使用普通的JS。现在,我已将$.ajax POST调用替换为Fetch API调用,每个调用都会在服务器上触发一个新会话。

在过去的几天里,这一直困扰着我,并且我将其范围缩小到专门从使用jQuery Ajax到Fetch API的切换。我的新Fetch API调用可以完美地工作,否则仍可以执行所需的服务器端工作。公正者一旦返回就会触发新的服务器会话。

很明显,这是一个主要问题,因为我的用户会话数据一直在重置。知道为什么会这样吗?还是有人知道任何解决方法,而不必恢复使用jQuery?

我之前基于jQuery的POST调用:

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

我新的基于“提取API”的调用:

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;
}

在我的Global.asax.cs中:

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

如上所述,Fetch API调用除了重置会话(我从Debug.WriteLine知道)以外,还可以正常工作。 jQuery Ajax调用也可以很好地工作,并且不会触发新的会话,但是我试图删除对jQuery的依赖。

有想法吗?

2 个答案:

答案 0 :(得分:4)

您不会通过自定义请求传递ASP.NET_SessionId cookie。

您正在使用fetchBy defaultomit使用credentials。如MDN页面上所述,这意味着:

  

默认情况下,fetch 不会从服务器发送或接收任何Cookie ,如果该站点依赖于维护用户会话(发送Cookie和凭据),则会导致未经身份验证的请求必须设置init选项。)

JQuery 发送cookie,但仅发送相同域中的cookie。

  

AJAX调用仅在您所调用的URL与您的调用脚本位于同一域时发送Cookie。
   Source

要解决此问题,您需要告诉fetch发送cookie。来自this post

fetch('/something', { credentials: 'same-origin' }) // or 'include'

答案 1 :(得分:2)

在@ gunr2171的帮助下找出问题所在,以便在其他任何人遇到类似问题时自行回答。

事实证明,我的新Fetch API调用未随请求发送当前的Asp.net会话cookie,因此服务器会以为尚不存在的新会话开始。调整Fetch API调用,使其在选项中包含credentials: 'include',使其可以发送当前会话cookie,并且服务器将不再在每次调用后创建新的cookie。

作为参考,我的新Fetch API调用现在如下所示:

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;
}