简体   繁体   中英

ASPNET Session between jQuery AJAX calls in a CORS enviroment

Using VS2012, framework 4.5

I have a simple webapp with just a WebService.asmx file. Running the project publishes these 2 webmethods, SetData and GetData , here's the C# code:

[WebService(Namespace = "http://mydomain.com/")]
[System.Web.Script.Services.ScriptService]
public class WebService: System.Web.Services.WebService {

  [WebMethod(EnableSession=true)]
  [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
  public string SetData() {
      HttpContext.Current.Session["someData"] = "xxxxxxxxx";
      return "";
  }

  [WebMethod(EnableSession = true)]
  [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
  public string GetData() {
      if (HttpContext.Current.Session["someData"] == null)
          return "Session NULL";
      else
          return HttpContext.Current.Session["someData"].ToString();
  }
}

The web.config is set to enable CORS and also aspNetCompatibilityEnabled to enable session sharing

<system.webServer>
  <httpProtocol>
    <customHeaders>
      <add name="Access-Control-Allow-Origin" value="null" />
      <add name="Access-Control-Allow-Headers" value="Content-Type" />
      <add name="Access-Control-Allow-Credentials" value="true" />
    </customHeaders>
  </httpProtocol>
</system.webServer>

<system.serviceModel>
  <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
</system.serviceModel>

So the projects runs fine. Now I want to consume these 2 methods from a simple HTML page (the HTML is NOT part of the ASPNET project, is just an HTML file... thus the CORS problem) Here's the HTML code (left out the HTML tags for simplicity, but it's just an empty page):

<script type="text/javascript">
    $(document).ready(function() {
        //jQuery.support.cors = true;
        $.ajax({
            type: "POST",
            url: "http://localhost:62776/WebService.asmx/SetData",
            contentType: "application/json; charset=utf-8",
            dataType: "json",
            success: function(msg) {
                alert('SetData OK');
                $.ajax({
                    type: "POST",
                    url: "http://localhost:62776/WebService.asmx/GetData",
                    contentType: "application/json; charset=utf-8",
                    dataType: "json",
                    //async: true, -- makes no difference
                    //beforeSend: function(xhr){
                    //    xhr.withCredentials = true;
                    //},
                    success: function(msg) {
                        alert('GetData: ' + msg.d);
                    },
                    error: function(e){
                        alert("GetData: Unavailable");
                    }
                });

            },
            error: function(e){
                alert("SetData: Unavailable");
            }
        });
    });
</script>

Running the HTML pages gives me SetData OK and then GetData: Session NULL but I want GetData: xxxxxx

So my question is, how can I access the same Session Object between CORS calls?

I also tried enabling authentication, thinking that ASPNET AUTH COOKIES will somehow keep the correct session ID between AJAX calls, but it didn't work. There is a possible approach using SOAP envelopes to authenticate each AJAX call and send session info, but that seems overkill.

You need to set withCredentials which means the client wants implicit "stuff" to be sent (which includes cookies):

http://brockallen.com/2012/12/15/cors-and-windows-authentication/

Also, given that you need "credentials" to be allowed, the server must respond with Access-Control-Allow-Origin with the specific origin requesting -- it can't use "*".

have you tried following adding to your web.config file

<webServices>
  <protocols>
    <add name="HttpGet"/>
    <add name="HttpPost"/>
  </protocols>
</webServices>

or add following code to your web method:

[ScriptMethod(UseHttpGet = true)]
public string HelloWorld()
{
   return "Hello World";
}

use this to call your service (javascript):

function SendAjaxRequest(url) {

var xmlhttp = "";

if (window.XMLHttpRequest) {
    xmlhttp = new XMLHttpRequest();
} else {
    xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}

xmlhttp.open("GET", url, false);
xmlhttp.onreadystatechange = function () {
    //when response is ready
    if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
        var rspText = xmlhttp.responseText;
        if (rspText != undefined) {
            // here is the response
            var json = JSON.parse(rspText);
        }
    }
}

   xmlhttp.send(null);
}

if you notice the returned data would be wrap in tag to remove it and just get the data use this function:

function TrimXmlTag(start, responseText) {

   var from = responseText.indexOf(start),
       remaining = responseText.substring(from, responseText.length - 9);

   return remaining;
}

and just change this line:

 var json = JSON.parse(TrimXmlTag("[",rspText));

Hope it helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM