Unable to pass parameter to REST/WCF service using JSONP - wcf

I want to invoke a WCF service using JSONP. There are two methods,
1. "Hello" method, it does not take any paramter. This works fine
2. "Hello1" methods takes a string paramter. This does not work properly. It should return the value which I am passing.
Following is the code snippet
Server code
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Web;
namespace WcfService1
{
[ServiceContract(Namespace = "JsonpAjaxService")]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class Service1
{
[WebGet(ResponseFormat = WebMessageFormat.Json)]
public string Hello()
{
return "I got the call";
}
[WebGet(ResponseFormat = WebMessageFormat.Json)]
public string Hello1(string str)
{
return "Hi, you passed me " + str;
}
}
}
Web config code
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
<authentication mode="None" />
</system.web>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
<standardEndpoints>
<webScriptEndpoint>
<standardEndpoint name="" crossDomainScriptAccessEnabled="true"/>
</webScriptEndpoint>
<webHttpEndpoint>
<standardEndpoint name="" helpEnabled="True"
automaticFormatSelectionEnabled="true" />
</webHttpEndpoint>
</standardEndpoints>
</system.serviceModel>
</configuration>
Client code
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<script src="JS/JQuery.js" type="text/javascript"></script>
<script type="text/javascript">
var Type;
var Url;
var Data;
var ContentType;
var DataType;
var ProcessData;
var method;
//Generic function to call WCF Service
function CallService() {
$.ajax({
type: Type, //GET or POST or PUT or DELETE verb
url: Url, // Location of the service
data: Data, //Data sent to server
contentType: ContentType, // content type sent to server
dataType: DataType, //Expected data format from server
processdata: ProcessData, //True or False
success: function (msg) {//On Successfull service call
ServiceSucceeded(msg);
},
error: ServiceFailed// When Service call fails
});
}
function ServiceFailed(result) {
alert('test');
alert('Service call failed: ' + result.status + '' + result.statusText);
Type = null;
Url = null;
Data = null;
ContentType = null;
DataType = null;
ProcessData = null;
}
function Hello() {
var uesrid = "1";
Type = "GET";
Url = "http://localhost:52136/Service1.svc/Hello";
DataType = "jsonp"; ProcessData = false;
method = "Hello";
//debugger;
CallService();
}
function Hello1() {
debugger;
var uesrid = "1";
Type = "GET";
ContentType = "application/json; charset=utf-8";
Url = "http://localhost:52136/Service1.svc/Hello1";
DataType = "jsonp"; //ProcessData = false;
method = "Hello1";
Data = "{'str':'abc'}"; //"{'Input':'a123'}";//"{'StringValue':'1234'}";
//debugger;
CallService();
}
function ServiceSucceeded(result) {
debugger;
if (DataType == "jsonp") {
alert(result); /* Problem, While calling 'Hello1' method I do not get the value in the return string*/
}
}
function ServiceFailed(xhr) {
alert(xhr.responseText);
if (xhr.responseText) {
var err = xhr.responseText;
if (err)
error(err);
else
error({ Message: "Unknown server error." })
}
return;
}
$(document).ready(
function () {
try {
//Hello();
Hello1();
} catch (exception) { }
}
);
</script>
</head>
<body>
<form id="form1" runat="server">
<h1>
JSONP Service Client Page</h1>
</form>
</body>
</html>
Can anybody tell me what is wrong in the code while calling Hello1 method
Atul Sureka

Try passing the data as an object, not as a string:
function Hello1() {
debugger;
var uesrid = "1";
Type = "GET";
ContentType = "application/json; charset=utf-8";
Url = "http://localhost:52136/Service1.svc/Hello1";
DataType = "jsonp"; //ProcessData = false;
method = "Hello1";
Data = {str : 'abc'};
//debugger;
CallService();
}

using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Web;
namespace WcfService1
{
[ServiceContract(Namespace = "JsonpAjaxService")]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class Service1
{
[WebGet(ResponseFormat = WebMessageFormat.Json)]
public string Hello()
{
return "I got the call";
}
[WebGet(BodyStyle = WebMessageBodyStyle.Bare,
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "SetQuoteEntities?str={str}")]
public string Hello1(string str)
{
return "Hi, you passed me " + str;
}
}
}
When I modified attribute webGet it worked for me.

Related

WCF more than 50 concurent long running request

Hy, I have a WCF Test service, it does nothing only a thread.sleep(10000) and I call it from 200 clients.
The problem is the response time is greater and greater, after 10 minutes over 40 sec...
I have tired to change web.config and machine.config too.
We have Windows 2008 r2 and IIS 7.5
In my web.config
<serviceThrottling maxConcurrentCalls="100" maxConcurrentSessions="400" maxConcurrentInstances="2000" />
In my macine.config
<processModel autoConfig="false" logLevel="None" maxIoThreads="1000" maxWorkerThreads="1000" minIoThreads="100" minWorkerThreads="100" />
In my Aspnet.config
<applicationPool maxConcurrentRequestsPerCPU="5000" maxConcurrentThreadsPerCPU="0" requestQueueLimit="5000" />
The WCF Service:
public interface ISampleService
{
[OperationContractAttribute]
string SampleMethod(string msg);
}
public class SampleService : ISampleService
{
public string SampleMethod(string msg)
{
Thread.Sleep(10000);
return msg;
}
}
Here my solution:
[ServiceContract(Namespace = "http://microsoft.wcf.documentation")]
public interface ISampleService
{
[OperationContract]
Task<string> SampleMethod(string msg);
}
public class SampleService : ISampleService
{
async Task<string> ISampleService.SampleMethod(string msg)
{
var task = Task.Factory.StartNew((param) =>
{
return "Return from Server : " + msg;
}, TaskContinuationOptions.LongRunning);
await Task.Delay(10000);
return await task.ConfigureAwait(false);
}
}
And i need only the web.config changes:
<serviceThrottling maxConcurrentCalls="500" maxConcurrentSessions="1000" maxConcurrentInstances="2000" />

WCF REST can not parse Request Body

I have a struggling time with WCF REST to parse request body.
My problem:
POST method https://{Service}/X/Y? Z= 0000000
Body Request: {"id":"id"}
My code:
[ServiceContract]
public interface IService
{
[OperationContract]
[WebInvoke(Method = "POST",
BodyStyle = WebMessageBodyStyle.Bare,
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "/X/{y}?Z={z}")
]
string GetRequest(string y, string z, Request request);
}
public class Service : IService
{
public string GetRequest(string y, string z, Request request)
{
//Do sth
}
[DataContract]
public class Request
{
[DataMember]
[JsonProperty("id")]
public String Id { get; set; }
}
The problem that I have is that y and z has data and they are correct BUT id in request is null. I expected to be "id".
I searched a lot in the internet and I found Stream solution which is not easily to follow in this case.
I am wondering if anyone has a clever idea to do this.
Take a look on this version
The Service
namespace ServiceTest
{
internal class Program
{
private static WebServiceHost _service;
private static void Main()
{
_service = new WebServiceHost(typeof (Service));
Console.WriteLine("The service has started");
_service.Open();
Console.ReadKey();
}
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
public sealed class Service : IService
{
public string GetRequest(string y, string z, Request request)
{
Console.WriteLine("Y: {0}, Z: {1}, request: {2}", y, z, request);
return "Ok";
}
}
[ServiceContract]
public interface IService
{
[OperationContract]
[WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.Bare, RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json, UriTemplate = "/X/{y}?Z={z}")]
string GetRequest(string y, string z, Request request);
}
[DataContract]
public sealed class Request
{
[DataMember]
public string Id { get; set; }
public override string ToString()
{
return string.Format("Id: {0}", Id);
}
}
}
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<services>
<service name="ServiceTest.Service">
<host>
<baseAddresses>
<add baseAddress="http://localhost:9090/webhost" />
</baseAddresses>
</host>
<endpoint binding="webHttpBinding" contract="ServiceTest.IService" />
</service>
</services>
</system.serviceModel>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
</configuration>
The Client
internal class Program
{
private static void Main(string[] args)
{
var client = new HttpClient();
var request = new Request {Id = "Nelibur"};
var result = client.PostAsync("http://localhost:9090/webhost/X/Y?Z=2000", CreateContent(request)).Result;
Console.WriteLine(result.Content.ReadAsStringAsync().Result);
Console.ReadKey();
}
private static StringContent CreateContent<T>(T value)
{
using (var stream = new MemoryStream())
{
var serializer = new DataContractJsonSerializer(typeof (T));
serializer.WriteObject(stream, value);
string content = Encoding.UTF8.GetString(stream.ToArray());
return new StringContent(content, Encoding.UTF8, "application/json");
}
}
}
Raw request:
POST http://localhost:9090/webhost/X/Y?Z=2000 HTTP/1.1
Content-Type: application/json; charset=utf-8
Host: localhost:9090
Content-Length: 16
Expect: 100-continue
Connection: Keep-Alive
{"Id":"Nelibur"}
You can try to use the request in for example Fiddler

asp.net mvc My Form action is empty

I have define my routeconfig as :
routes.MapRoute(
"addcomments",
"addcomments/{urlLanguage}",
new { controller = "Home", action = "addcomments", urlLanguage = "h" }
);
and in Homecontroller :
public ActionResult addcomments(string urlLanguage)
{
return View();
}
[AcceptVerbs(HttpVerbs.Post)]
public string addcommentssave(int id, string yourName, string youremail, string website, string yourComment)
{
string message = " Thanks for sharing your comment! If your comment doesn't appear right away, please be patient as it may take a few minutes to publish or may require moderation.";
DateTime WishDateTime = DateTime.UtcNow;
string szRemoteAddr = System.Web.HttpContext.Current.Request.UserHostAddress;
Comments commit = new Comments();
commit.comdate = WishDateTime;
commit.comments = yourComment;
commit.email = youremail;
commit.Name = yourName;
commit.Website = website;
commit.IpAddress = szRemoteAddr;
commit.PostId = id;
commit.IsVisible = 0;
_session.Comment.Add(commit);
_session.SaveChanges();
//ViewBag.result= "<div class='message success'>" + message + "</div>";
// return View();
return "<div class='message success'>" + message + "</div>";
}
in addcomments view
#using (Ajax.BeginForm("addcommentssave", "home", null,
new AjaxOptions {
HttpMethod = "POST",
UpdateTargetId = "commentmessage",
OnBegin = "wait()",
OnSuccess = "success()",
LoadingElementId = "updating" },
new { id = "_commitForm" }))
{
}
but when i run it my form action become empty like
form action="" ....`
how to i solve it, help me
I created a simple test site to try and see if I could replicate your issue.
Here is my route config:
namespace Comments
{
// Note: For instructions on enabling IIS6 or IIS7 classic mode,
// visit http://go.microsoft.com/?LinkId=9394801
public class MvcApplication : System.Web.HttpApplication
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
}
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
}
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
// Use LocalDB for Entity Framework by default
Database.DefaultConnectionFactory = new SqlConnectionFactory(#"Data Source=(localdb)\v11.0; Integrated Security=True; MultipleActiveResultSets=True");
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
}
}
Here is my HomeController.cs:
namespace Comments.Controllers
{
public class HomeController : Controller
{
//
// GET: /Home/
public ActionResult Index()
{
return RedirectToAction("AddComment");
}
[HttpGet]
public ActionResult AddComment()
{
return View();
}
[HttpPost]
public ActionResult AddComment(int id, string yourName, string youremail, string website, string yourComment)
{
return Content(String.Format("Got a comment, id = {0}, yourName = {1}, youremail = {2}, website = {3}, yourComment = {4}",
id,
yourName,
youremail,
website,
yourComment));
}
}
}
Here is my AddComment.cshtml:
#{
ViewBag.Title = "Add Comment";
}
<h2>Add Comment</h2>
#using (Ajax.BeginForm("AddComment", "Home", null, new AjaxOptions { HttpMethod = "POST", UpdateTargetId = "commentmessage", OnBegin = "wait()", OnSuccess = "success()", LoadingElementId = "updating" }, new { id = "_commitForm" }))
{
<b>Form Here</b>
}
Here is the view source:
<DOCTYPE html>
<html>
<head>
<title>Add Comment</title>
<link href="/Content/Site.css" rel="stylesheet" type="text/css" />
<script src="/Scripts/jquery-1.7.1.min.js" type="text/javascript"></script>
</head>
<body>
<h2>Add Comment</h2>
<form action="/Home/AddComment" data-ajax="true" data-ajax-begin="wait()" data-ajax-loading="#updating" data-ajax-method="POST" data-ajax-mode="replace" data-ajax-success="success()" data-ajax-update="#commentmessage" id="_commitForm" method="post"> <b>Form Here</b>
</form>
</body>
</html>
So you can see the form path rendering. Try simplifying your route config (I didn't do anything special).

WCF Rest - no elemnt found error

I designed a WCF REST service and try to consume it via JQuery in html page. When I added the html page in the solution where WCF service was created, I was getting the result as per the need. But when I created the HTML Page in a different solution I started getting errors such as no element found and the returned result is null.
I put a debugger in the service and I noticed that even if the the Consumer html page is kept in a different solution it still hits the global.asax file when service is called, But its not hitting any of the Method.
I even put "crossDomain:true," and "jQuery.support.cors = true;" in script for enabling Cross Domain problem as well as I have made changes in Global.asax file too but of no use.
Please provide me the solution for the same asap.
I am placing the actual code with configuration files and DataContracts along with the HTML code here :
ICouponService.cs :
[ServiceContract]
public interface ICouponService
{
[OperationContract]
[WebInvoke(UriTemplate = "/GenerateCoupon",
Method = "POST",
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json)]
CouponData GenerateCoupon(CouponData objCustomerData);
[OperationContract]
[WebInvoke(UriTemplate = "/UpdateGeneratedCoupon",
Method = "POST",
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json)]
ResponseMessage UpdateGeneratedCoupon(CouponData objCustomerData);
}
CouponService.cs :
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
[ServiceBehavior(AddressFilterMode = AddressFilterMode.Any)]
public class CouponService : ICouponService
{
public CouponData GenerateCoupon(CouponData objCustomerData)
{
return objCouponData;
}
public ResponseMessage UpdateGeneratedCoupon(CouponData objCustomerData)
{
return objResponseMessage;
}
}
CouponData.cs :
[DataContract]
public class CouponData
{
[DataMember(EmitDefaultValue = false)]
public string Email { get; set; }
[DataMember(EmitDefaultValue = false)]
public string Points { get; set; }
[DataMember(EmitDefaultValue = false)]
public string ActiveFlag { get; set; }
[DataMember(EmitDefaultValue = false)]
public string CouponCode { get; set; }
[DataMember(EmitDefaultValue = false)]
public string RequestID { get; set; }
[DataMember(EmitDefaultValue = false)]
public string LoyaltyID { get; set; }
[DataMember(EmitDefaultValue = false)]
public string Result { get; set; }
[DataMember(EmitDefaultValue = false)]
public string ReturnFlag { get; set; }
[DataMember(EmitDefaultValue = false)]
public string UserName { get; set; }
[DataMember(EmitDefaultValue = false)]
public string Password { get; set; }
}
ResponseMessage.cs :
[DataContract]
public class ResponseMessage
{
[DataMember(EmitDefaultValue = false)]
public string Response { get; set; }
}
Global.asax :
First I thought there might be some Header problem so I added the same in Global file as shown below :
protected void Session_Start(object sender, EventArgs e)
{
string sessionId = Session.SessionID;
}
protected void Application_BeginRequest(object sender, EventArgs e)
{
HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
HttpContext.Current.Response.Cache.SetNoStore();
EnableCrossDomainAjaxCall();
}
private void EnableCrossDomainAjaxCall()
{
if (!string.IsNullOrEmpty(Request.ServerVariables["HTTP_ORIGIN"]))
{
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", Request.ServerVariables["HTTP_ORIGIN"]);
if (!string.IsNullOrEmpty(HttpContext.Current.Request.HttpMethod))
{
if (HttpContext.Current.Request.HttpMethod == "OPTIONS" || HttpContext.Current.Request.HttpMethod == "POST" || HttpContext.Current.Request.HttpMethod == "GET")
{
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
//HttpContext.Current.Response.End();
}
}
}
}
Web.config :
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<services>
<service behaviorConfiguration="ServiceBehaviour" name="SAM_STORE_LoyaltyProgram_WCFLibrary.CouponService">
<endpoint address="" behaviorConfiguration="web" binding="webHttpBinding"
contract="SAM_STORE_LoyaltyProgram_WCFLibrary.ICouponService" />
</service>
<service name="SAM_STORE_LoyaltyProgram_WCFServices.qqq">
<endpoint address="" behaviorConfiguration="SAM_STORE_LoyaltyProgram_WCFServices.qqqAspNetAjaxBehavior"
binding="webHttpBinding" contract="SAM_STORE_LoyaltyProgram_WCFServices.qqq" />
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="web">
<webHttp />
</behavior>
<behavior name="SAM_STORE_LoyaltyProgram_WCFServices.qqqAspNetAjaxBehavior">
<enableWebScript />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="ServiceBehaviour">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
<dataContractSerializer maxItemsInObjectGraph="5000" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"
multipleSiteBindingsEnabled="true" />
<bindings>
<webHttpBinding>
<binding maxBufferSize="5000" maxReceivedMessageSize="5000"
transferMode="Streamed">
<readerQuotas maxDepth="5000" maxStringContentLength="5000"
maxArrayLength="5000" maxBytesPerRead="5000" maxNameTableCharCount="5000" />
<security mode="None" />
</binding>
</webHttpBinding>
</bindings>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
Index.html (script used to call service):
<script src="js/jquery-1.7.min.js" type="text/javascript"></script>
<script type="text/javascript">
var Type;
var Url;
var Data;
var ContentType;
var DataType;
var ProcessData;
var method;
var eMail;
var points;
var requestId;
var couponCode;
var returnFlag;
var userName;
var password;
//Generic function to call Service
function CallService() {
$.ajax({
type: Type,
url: Url,
data: Data,
contentType: ContentType,
dataType: DataType,
//crossDomain:true, --This is not working
processdata: ProcessData,
success: function (msg) {
ServiceSucceeded(msg);
},
error: function (msg) {
alert("Service Failed");
ServiceFailed(msg);
}
});
}
function SetGenerateCouponValues() {
eMail = $("#txtEmail").val();
points = $("#txtPoints").val();
requestId = $("#txtRequestId").val();
userName = 'username';
password = 'JEBtJHVu';
}
function DestroyGenerateCouponValues() {
eMail = null;
points = null;
requestId = null;
userName = null;
password = null;
}
function SetUpdateCouponValues() {
couponCode = $("#txtCode").val();
returnFlag = $("#txtFlag").val();
userName = 'username';
password = 'JEBtJHVu';
}
function DestroyUpdateCouponValues() {
couponCode = null;
returnFlag = null;
userName = null;
password = null;
}
function ServiceFailed(result) {
alert('Service call failed: ' + result.status + '' + result.statusText);
Type = null; Url = null; Data = null; ContentType = null; DataType = null; ProcessData = null;
}
function GenerateCoupon() {
SetGenerateCouponValues();
Type = "POST";
Url = "ServiceURL";
Data = '{ "Email": "' + eMail + '", "Points": "' + points + '", "UserName": "' + userName + '", "Password": "' + password + '", "RequestID": "' + requestId + '"}';
ContentType = "application/json; charset=utf-8";
DataType = "json";
ProcessData = true;
method = "GenerateCoupon";
CallService();
DestroyGenerateCouponValues();
}
function UpdateGeneratedCoupon() {
SetUpdateCouponValues();
Type = "POST";
Url = "ServiceURL";
Data = '{ "CouponCode": "' + couponCode + '", "ReturnFlag": "' + returnFlag + '", "UserName": "' + userName + '", "Password": "' + password + '"}';
ContentType = "application/json; charset=utf-8";
DataType = "json";
ProcessData = true;
method = "UpdateGeneratedCoupon";
CallService();
DestroyUpdateCouponValues();
}
function ServiceSucceeded(result) {
if (DataType == "json") {
if (method == "GenerateCoupon") {
var string = "Coupon Code : " + result.CouponCode + "<br/>" + "Points : " + result.Points + "<br/>" + "Result : " + result.Result;
$("#resultCreate").html(string);
$("#lblCouponCode").text(result.CouponCode);
$("#lblPoints").text(result.Points);
$("#lblResult").text(result.Result);
}
else if (method == "UpdateGeneratedCoupon") {
var string = "Response : " + result.Response;
$("#resultDelete").html(string);
$("#lblResponse").text(result.Response);
}
}
}
/*function ServiceFailed(xhr) {
alert("FAIL" + xhr.responseText);
if (xhr.responseText) {
var err = xhr.responseText;
if (err)
error(err);
else
error({ Message: "Unknown server error." })
}
return;
}*/
$(document).ready(
function () {
//jQuery.support.cors = true; --This is not working
$("#btnsubmit").click(function () {
GenerateCoupon();
});
$("#btnUpdateGeneratedCoupon").click(function () {
UpdateGeneratedCoupon();
});
});
</script>
Please provide me the solution for the same asap.
Is it calling ServiceSucceeded method??
If ServiceSucceeded called try to put $.support.cors = true; in CallService() starting and then check it
Try enabling WCF tracing and ETW tracing to see what is happening at the server side while invoking the service operation.

Passing JSON data to WCF (.Net 4) Web Service

I have a very simple [OperationContract] called TestClass that gets called like this:
var person = { "Name": "Dave", "City":"HB", "State": "CA", "Zip":"92649" };
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
dataType: "json",
data: JSON.stringify(person),
url: "MyService.svc/TestClass",
success: function (data) {
$("#output").text("[ " + data + "]");
}
});
What I'm not understanding, and can't seem to find, is the preferred way of using these services. I've been searching everywhere for the past few days and I feel really overwhelmed with what I've found so far. I read one post where somebody said not to use Message but to create their own DataContract which I tried.
Here is my Operation Contract:
[OperationContract]
[WebInvoke(Method = "POST", ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)]
public Message TestClass(Message m)
{ return WebOperationContext.Current.CreateTextResponse(JsonConvert.SerializeObject("Ok"));}
Besides having 4 input values to TestClass, I would prefer just one. Message is the only thing that seems to work. I tried using just a string and that value is always null.
I've tried creating a [DataContract] for the data and use that as the parameter in the TestClass call but that also is null.
I'm new to using these service types so any pointers for a beginner is greatly appreciated.
Thank you in advance.
UPDATE
IService.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
namespace WcfTest
{
[System.ServiceModel.ServiceContractAttribute()]
public interface IService
{
[System.ServiceModel.Web.WebInvokeAttribute(BodyStyle = System.ServiceModel.Web.WebMessageBodyStyle.Bare,
RequestFormat = System.ServiceModel.Web.WebMessageFormat.Json,
ResponseFormat = System.ServiceModel.Web.WebMessageFormat.Json)]
[System.ServiceModel.OperationContractAttribute()]
void ProcessData(RootClass input);
}
[System.Runtime.Serialization.DataContractAttribute()]
public partial class RootClass
{
[System.Runtime.Serialization.DataMemberAttribute()]
public string Name;
[System.Runtime.Serialization.DataMemberAttribute()]
public string City;
[System.Runtime.Serialization.DataMemberAttribute()]
public string State;
[System.Runtime.Serialization.DataMemberAttribute()]
public string Zip;
}
}
ServiceZ.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using Newtonsoft.Json;
namespace WcfTest
{
public class ServiceZ : IService
{
public void ProcessData(RootClass input)
{
int i = 6; // used for a breakpoint
}
}
}
Index.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script src="Scripts/jquery-1.6.2.min.js" type="text/javascript"></script>
<script src="Scripts/json2.js" type="text/javascript"></script>
<script type="text/javascript">
$().ready(function () {
var person = { "Name": "Dave", "City": "HB", "State": "CA", "Zip": "92649" };
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
dataType: "json",
data: JSON.stringify(person),
url: "ServiceZ.svc/ProcessData",
success: function (data) {
$("#output").text("OK!");
},
error: function (jqXHR, textStatus, errorThrown) {
debugger;
}
});
});
</script>
</head>
<body>
<div id="output" style="background: lightgreen;">--></div>
</body>
You can use a the data contract for your data. The tool at http://carlosfigueira.me/JsonUtilities/JsonToContract.htm (more information about it at http://blogs.msdn.com/b/carlosfigueira/archive/2011/01/11/inferring-schemas-for-json.aspx) can give you a data contract which is compatible with the JSON data. By running it with your input I got the code below.
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:v4.0.30319
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
[System.ServiceModel.ServiceContractAttribute()]
public interface IService
{
[System.ServiceModel.Web.WebInvokeAttribute(BodyStyle = System.ServiceModel.Web.WebMessageBodyStyle.Bare, RequestFormat = System.ServiceModel.Web.WebMessageFormat.Json, ResponseFormat = System.ServiceModel.Web.WebMessageFormat.Json)]
[System.ServiceModel.OperationContractAttribute()]
void ProcessData(RootClass input);
}
[System.Runtime.Serialization.DataContractAttribute()]
public partial class RootClass
{
[System.Runtime.Serialization.DataMemberAttribute()]
public string Name;
[System.Runtime.Serialization.DataMemberAttribute()]
public string City;
[System.Runtime.Serialization.DataMemberAttribute()]
public string State;
[System.Runtime.Serialization.DataMemberAttribute()]
public string Zip;
}
Update: I created a new project (empty web application), and added the following files - the client received the correct response. Try comparing with what you have to see if there is anything different. And the 415 error you're getting usually indicates which you don't have the appropriate binding / behavior on this endpoint. To enable REST endpoints (which can accept JSON), the endpoint needs to have the webHttpBinding and a behavior with the <webHttp/> on it. Or another alternative (which is what I used) is to use the WebServiceHostFactory on the .svc file, in which case you don't need anything on web.config.
ServiceZ.svc
<%# ServiceHost Language="C#" Debug="true"
Service="StackOverflow_7141298.ServiceZ"
CodeBehind="ServiceZ.svc.cs"
Factory="System.ServiceModel.Activation.WebServiceHostFactory" %>
IServiceZ.cs
namespace StackOverflow_7141298
{
[System.ServiceModel.ServiceContractAttribute()]
public interface IService
{
[System.ServiceModel.Web.WebInvokeAttribute(BodyStyle = System.ServiceModel.Web.WebMessageBodyStyle.Bare, RequestFormat = System.ServiceModel.Web.WebMessageFormat.Json, ResponseFormat = System.ServiceModel.Web.WebMessageFormat.Json)]
[System.ServiceModel.OperationContractAttribute()]
string ProcessData(RootClass input);
}
[System.Runtime.Serialization.DataContractAttribute()]
public partial class RootClass
{
[System.Runtime.Serialization.DataMemberAttribute()]
public string Name;
[System.Runtime.Serialization.DataMemberAttribute()]
public string City;
[System.Runtime.Serialization.DataMemberAttribute()]
public string State;
[System.Runtime.Serialization.DataMemberAttribute()]
public string Zip;
}
}
ServiceZ.svc.cs
namespace StackOverflow_7141298
{
public class ServiceZ : IService
{
public string ProcessData(RootClass input)
{
if (input == null) return "NULL!!!";
StringBuilder sb = new StringBuilder();
return string.Format("Name={0},City={1},State={2},Zip={3}",
input.Name ?? "<<null>>",
input.City ?? "<<null>>",
input.State ?? "<<null>>",
input.Zip ?? "<<null>>");
}
}
}
HTMLPage1.htm
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script type="text/javascript" src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.6.2.min.js"></script>
<script type="text/javascript" src="json2.js"></script>
<script type="text/javascript">
$().ready(function () {
var person = { "Name": "Dave", "City": "HB", "State": "CA", "Zip": "92649" };
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
dataType: "json",
data: JSON.stringify(person),
url: "ServiceZ.svc/ProcessData",
success: function (data) {
$("#output").text(data);
},
error: function (jqXHR, textStatus, errorThrown) {
//debugger;
$("#output").text("Error!");
}
});
});
</script>
</head>
<body>
<div id="output"></div>
</body>
</html>