如何使启用会话的 ASP.NET Web 服务与不同域中的 ajax 客户端一起工作?
Posted
技术标签:
【中文标题】如何使启用会话的 ASP.NET Web 服务与不同域中的 ajax 客户端一起工作?【英文标题】:How to make a session enabled ASP.NET web service work with an ajax client in a different domain? 【发布时间】:2014-09-02 15:30:37 【问题描述】:我和我的同事花了很多时间寻找这个答案,所以我想我应该分享这个自我回答的问题。
我有一个 Web 服务 (ASP.NET 4.5),其方法需要使用会话状态。为了存档这个,我用 EnableSession=true 修饰了这个方法。这是 MS 在this article 中建议做的事情(见最后的“代码块 A”)。
为了让网络服务能够重新使用会话,它需要找到一个带有会话 ID 的 cookie。该 cookie 在服务器端由 Web 服务器本身在第一次调用该方法时创建和设置。为了在每次调用时重新发送此 cookie,MS 建议使用分配给 Web 服务代理的“cookie 容器”,在调用之间保存并在每次调用时重复使用。 (见最后的“代码块 B”)。
只要您打算从服务器端调用 Web 服务,这非常有效。我需要使用 jQuery ajax JSON Post 调用从客户端调用它(参见最后的“代码块 C”)。这段代码很好用。事实上,带有会话 ID 的 cookie 会自动传递给 Web 服务。不需要cookie jar...只要客户端和Web 服务在同一个域中。
如果客户端位于与 Web 服务 (domainb.com) 不同的域 (domaina.com) 中,则根本不会传递带有会话 ID 的 cookie。因此,对 Web 服务的每次调用都被视为第一次调用。
我在网络配置中定义了以下标头以允许跨域调用。
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Headers" value="Content-Type" />
那么,缺少什么?
代码块 A:带有修饰方法的 Web 服务
public class Util: WebService
[ WebMethod(EnableSession=true)]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public int SessionHitCounter()
if (Session["HitCounter"] == null)
Session["HitCounter"] = 1;
else
Session["HitCounter"] = ((int) Session["HitCounter"]) + 1;
return ((int) Session["HitCounter"]);
代码块 B:服务器端 Cookie Jar 解决方案
<script runat="server">
void EnterBtn_Click(Object Src, EventArgs E)
// Create a new instance of a proxy class for your XML Web service.
ServerUsage su = new ServerUsage();
CookieContainer cookieJar;
// Check to see if the cookies have already been saved for this session.
if (Session["CookieJar"] == null)
cookieJar= new CookieContainer();
else
cookieJar = (CookieContainer) Session["CookieJar"];
// Assign the CookieContainer to the proxy class.
su.CookieContainer = cookieJar;
// Invoke an XML Web service method that uses session state and thus cookies.
int count = su.PerSessionServiceUsage();
// Store the cookies received in the session state for future retrieval by this session.
Session["CookieJar"] = cookieJar;
// Populate the text box with the results from the call to the XML Web service method.
SessionCount.Text = count.ToString();
</script>
代码块 C:Ajax 调用
$.ajax(
type: "POST",
url: web_services_url + "/SessionHitCounter",
data: "",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (msg)
alert(msg.d);
);
【问题讨论】:
【参考方案1】:经过数小时的思考和谷歌搜索我的伴侣发现我们失踪了
一个额外的标头(“Access-Control-Allow-Credentials”) 将“Access-Control-Allow-Origin”上的“*”更改为调用 Web 服务的特定域 在 ajax 调用中添加额外参数 (withCredentials)这些是启用 CORS 所需的标头
<add name="Access-Control-Allow-Origin" value="http://localhost:53710" />
<add name="Access-Control-Allow-Headers" value="Content-Type" />
<add name="Access-Control-Allow-Credentials" value="true" />
这是带有额外参数的ajax调用
$.ajax(
type: "POST",
xhrFields: withCredentials: true ,
url: web_services_url + "/SessionHitCounter",
data: "",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (msg)
alert(msg.d);
);
【讨论】:
以上是关于如何使启用会话的 ASP.NET Web 服务与不同域中的 ajax 客户端一起工作?的主要内容,如果未能解决你的问题,请参考以下文章
电话间隙 HTML 应用程序可以与 asp.net Mvc Web 服务器建立会话吗
如何使 ASP.NET Web API Web 服务在本地网络中可用