Hours of befuddlement leads me to make my own contribution question to SO:
I have narrowed down the issue to a test solution, and here is what I have:
Upon the click of a button, RunService() makes a call to a WCF service (webHttpBinding), then displays the response from the service. The subsequent step is that it is to save some data to the HttpContext.Current.Session (another multi-day headache where a solution was found by blindly stabbing about).
This is a Visual Studio 2012 solution, with a Webforms project (com.dwf) and WCF service project (com.dwf.services) that are sent to the local host (different local hosts since they are two different projects). To account for the cross domain issue, on the javascript side, I have added the $.support.cors = true flag to prevent the "No Transport" error. When this gets published to a shared server, the service will exist in a virtual directory that is a subdirectory of the original domain (httpdocs/Service).
When the user clicks a button, the following function runs client-side.
function RunService() {
$.support.cors = true;
$.ajax({
url: 'http://localhost:XXXX/Service1.svc/web/GetData',
cache:false,
data: {
userName: 'DWF',
password: 'ban',
},
contentType: 'application/json; charset=utf-8',
success: function (response) {
$('#results').text('jQuery says ' + response);
$.ajax({
type:'POST',
url: location.href.slice('http://localhost:7177/'.length + '/SaveToSession',
data: JSON.stringify({userName: 'DWF',password: 'ban'}),
error: function (e) {
alert(e.statusText);
},
contentType: 'application/json; charset=utf-8'
});
},
error: function (err) {
$('#results').text(err.statusText);
}
});
}
Service1.svc is a REST enabled service, like so:
[System.ServiceModel.Activation.AspNetCompatibilityRequirements
(RequirementsMode=
System.ServiceModel.Activation.AspNetCompatibilityRequirementsMode.Allowed)]
public class Service1 : IService1
{
public string GetData(string userName, string password)
{
return string.Format("You entered: {0}/{1}", userName, password);
}
}
And of course, its interface is like so:
[ServiceContract]
public interface IService1
{
[OperationContract]
[WebGet(ResponseFormat=WebMessageFormat.Json)]
string GetData(string userName, string password);
}
and the web config is like so
<system.serviceModel>
...
<behaviors>
<endpointBehaviors>
<behavior name="RESTEndpointBehavior">
<webHttp helpEnabled="true"/>
</behavior>
</endpointBehaviors>
</behaviors>
<services>
<service name="com.dwf.services.Service1">
<endpoint address="web" behaviorConfiguration="RESTEndpointBehavior" binding="webHttpBinding" contract="com.dwf.services.IService1"></endpoint>
<endpoint address="ws" binding="wsHttpBinding" contract="com.dwf.services.IService1"></endpoint>
</service>
</services>
The WebMethod SaveToSession I am calling exists in a BasePage class from which every page will inherit. It looks like this:
public class BasePage : Page
{
[System.Web.Services.WebMethod]
[System.ServiceModel.Web.WebInvoke(Method="POST")]
public static void SaveToSession(string userName, string password)
{
HttpContext.Current.Session["TextValue"] = "Session says " + userName + " entered " + password;
}
}
If I call the first method (WCF's GetData) using JSON.stringify, my parameters come in as null. If I call the second method (WebMethod's SaveToSession) without using JSON.stringify, my method receives an Internal Server Error. Only by using the ajax calls above does it work for this solution.
EDIT
Why is JSON.stringify needed for the WCF service, and improper for the WebMethod?
Why is JSON.stringify improper for the WCF service, and needed for the WebMethod?
This started as a way to understand the communication more solidly between ASP.NET, Sessions, WCF, and static methods, and hopefully unravel the mystery of Web.config. It seems as if every step of the way I am wrestling with how it all works, and in the end nothing seems really all that convenient.
The WCF service is taking in parameters as objects, and the server is interpreting the inputs as they come in, "understanding" that the parameter name is the member name of the incoming JSON object.
Sending the entire object through by stringifying it is sending a gigantic string where server side code would need to parse the object into its respective parts. Kind of a serialize/deserialize deal. This would be used if someone wanted to simplify the signature of a service to just one parameter, which can be useful if you have objects whose values can be defaulted.
Pseudocode
GetData(string data)
{
EstablishedDataObject obj = DeserializeData(data);
DoSomething(obj);
}
This would be easier server side code than
GetData(int id, string name, bool likesBruceWillisAsASinger, int numberOfFelonies,
string streetName, int numberOfTattoos, bool dislikesTacosButLikesTheIdeaOfTacos)
The WebMethod, that one I am still stuck on. It may just end up being as simple as "That's how Microsoft programmed it, but good luck finding solid documentation on it."