I have a WCF Rest service with a method that takes in multiple parameters:
[OperationContract]
[WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.WrappedRequest, RequestFormat = WebMessageFormat.Json)]
StatusMessage DoSomeWork(short myId, decimal latitude, decimal longitude, string someData);
The JSON data which is serialized on the client side serializes correctly, and this method receives that data. The problem is that the longitudeparameter always comes back as 0, no matter what value the value is when it gets serialized. All the other parameters are deserialized correctly. Any idea as to why this is happening, and a possible fix?
Make sure that the name of the property in the JSON object matches the name of the parameter longitude. The code below shows your exact operation contract, and the longitude is correctly received by the service.
public class StackOverflow_23529686
{
[ServiceContract]
public class Service
{
[OperationContract]
[WebInvoke(
Method = "POST",
BodyStyle = WebMessageBodyStyle.WrappedRequest,
RequestFormat = WebMessageFormat.Json)]
public StatusMessage DoSomeWork(short myId, decimal latitude, decimal longitude, string someData)
{
return new StatusMessage
{
Text = string.Format("id={0}, lat={1}, lon={2}, data={3}", myId, latitude, longitude, someData)
};
}
}
public class StatusMessage
{
public string Text { get; set; }
}
public static void Test()
{
string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
WebServiceHost host = new WebServiceHost(typeof(Service), new Uri(baseAddress));
host.Open();
Console.WriteLine("Host opened");
WebClient c = new WebClient();
c.Headers.Add(HttpRequestHeader.ContentType, "application/json");
var json =
"{'someData':'hello','longitude':-56.78,'latitude':12.34,'myId':1}"
.Replace('\'', '\"');
Console.WriteLine(c.UploadString(baseAddress + "/DoSomeWork", json));
Console.Write("Press ENTER to close the host");
Console.ReadLine();
host.Close();
}
}
Related
I have this contract :
[ServiceContract]
public interface IServiceJsonContract
{
[WebInvoke(UriTemplate = "/MyMethod", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, Method = "POST")]
Message MyMethod(Message input);
}
And the definition for MyMethod is :
Message MyMethod(Message input)
{
...
Message response = Message.CreateMessage(
MessageVersion.None,
"*",
"{\"bla\": 2 }",
new DataContractJsonSerializer(typeof(string)));
response.Properties.Add( WebBodyFormatMessageProperty.Name,new
WebBodyFormatMessageProperty(WebContentFormat.Json));
var contextOutgoingResponse = WebOperationContext.Current.OutgoingResponse;
contextOutgoingResponse.ContentType = "application/json;charset=utf-8";
return response;
}
When calling the method I got the Json escaped:
"{\"bla\": 2 }"
instead of unescaped one (below):
"{"bla": 2 }"
Any idea how to get the unescaped Json ( "{"bla": 2 }" ) ?
Thanks
The DataContractJsonSerializer is serializing your string and escaping the quotation marks. Create a class to hold your data and pass that instead of the string.
public class MyData
{
public string Bla { get; set; }
}
// create an instance
MyData myData = new MyData()
{
Bla = "the value";
};
// then use it
Message response = Message.CreateMessage(
MessageVersion.None,
"*",
myData,
new DataContractJsonSerializer(typeof(MyData)));
you can use Stream as your out put. this way you can send back uncapped string:
[ServiceContract]
public interface IServiceJsonContract
{
[WebInvoke(UriTemplate = "/MyMethod", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, Method = "POST")]
Stream MyMethod(Message input);
}
Stream MyMethod(Message input)
{
..
return new MemoryStream(Encoding.UTF8.GetBytes("{\"bla\": 2 }"));
}
I'm developer C# .Net
I Now programming a Wcf restful service for communication mobile with my server. But a problem in send json request using post method with parameter. After send request from client, server display error:
400 Bad Request...
My service contract:
[WebInvoke(Method = "POST", ResponseFormat = WebMessageFormat.Json,
RequestFormat = WebMessageFormat.Json, UriTemplate = "login", BodyStyle = WebMessageBodyStyle.WrappedRequest)]
[OperationContract]
string login(string username, string password);
And implement service:
public string login(string username, string password)
{
string str = String.Empty;
if (username == "admin" && password == "admin")
str = "Success";
else
str = "Invalid";
return str;
}
Edit:
My host is:
public void Start()
{
Stop();
//string strAdrHTTP = "http://localhost:" + HttpPort + "/WcfMobileService";
string strAdrHTTP = "http://192.168.1.190:" + HttpPort + "/WcfMobileService";
Uri[] adrbase = { new Uri(strAdrHTTP) };
m_svcHost = new ServiceHost(typeof(TWcfMobileService), adrbase);
WebServiceHost webServiceHost =
new WebServiceHost(typeof(TWcfMobileService), adrbase);
ServiceMetadataBehavior mBehave = new ServiceMetadataBehavior();
m_svcHost.Description.Behaviors.Add(mBehave);
mBehave.HttpsGetEnabled = true;
mBehave.HttpGetEnabled = true;
WebHttpBinding webBinding = new WebHttpBinding();
webServiceHost.AddServiceEndpoint(typeof(IWcfMobileServiceContract), webBinding, "rest");
WebHttpBinding restBinding = new WebHttpBinding();
ServiceEndpoint restSEP =
m_svcHost.AddServiceEndpoint(typeof(IWcfMobileServiceContract),
restBinding, "rest");
restSEP.Behaviors.Add(new WebHttpBehavior());
EndpointAddress myEndpointAdd = new EndpointAddress(new Uri(strAdrHTTP),
EndpointIdentity.CreateDnsIdentity("localhost"));
restSEP.Address = myEndpointAdd;
m_svcHost.AddServiceEndpoint(typeof(IMetadataExchange),
MetadataExchangeBindings.CreateMexHttpBinding(), "mex");
ServiceDebugBehavior debug = new ServiceDebugBehavior();
debug.IncludeExceptionDetailInFaults = true;
m_svcHost.Open();
}
This is an working example -
[OperationContract]
[WebInvoke(
Method = "POST",
BodyStyle = WebMessageBodyStyle.WrappedRequest,
UriTemplate = "login")]
string login(CompositeType request);
Where -
[DataContract]
public class CompositeType
{
[DataMember]
public string username { get; set; }
[DataMember]
public string password { get; set; }
}
Sample request -
{"request":{"username":"test","password":"test"}}
And it works -
I created a WCF service and I am not able to call any method from my angular js script.
namespace jSonTest2.Service
{
[AspNetCompatibilityRequirements(
RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class service:IService1
{
public DB obj = new DB();//object class which return string
[WebInvoke(Method = "POST",
BodyStyle = WebMessageBodyStyle.WrappedRequest,
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json)]
string IService1.JsonCall()
{
return obj.JsonCall();
throw new NotImplementedException();
}
}
}
//---------------------------------------
namespace jSonTest2.DB_provider
{
class DB//class
{
public string JsonCall()
{
string str = "{name: 'Amit', marks: 97, distinction: true}";
return str;
}
}
}
//I created a WCF service and I am not able to call any method from my angular
I have a serializable polymorphic type, and a service contract.
[DataContract]
[KnownType(typeof(SomethingA))]
[KnownType(typeof(SomethingB))]
public class Something
{
[DataMember]
public int Item1 { get; set; }
[DataMember]
public string Item2 { get; set; }
}
[DataContract]
public class SomethingA : Something
{ }
[DataContract]
public class SomethingB : Something
{ }
[ServiceContract]
[ServiceKnownType(typeof(SomethingA))]
[ServiceKnownType(typeof(SomethingB))]
public interface ITesting
{
[OperationContract]
[WebInvoke(
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Bare,
UriTemplate = "use-something",
Method = "POST")]
Something UseSomething();
[OperationContract]
[WebInvoke(
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Bare,
UriTemplate = "use-polymorphic-somethings",
Method = "POST")]
List<Something> UsePolymorphicSomethings();
[OperationContract]
[WebInvoke(
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Bare,
UriTemplate = "throw-web-exception",
Method = "POST")]
void ThrowServerException();
}
...and an implementation of that contract.
using System.Net;
using System.ServiceModel.Web;
public class Testing : ITesting
{
public Something UseSomething()
{
SomethingA a = new SomethingA();
a.Item1 = 2;
a.Item2 = "b";
return a;
}
public List<Something> UsePolymorphicSomethings()
{
List<Something> retVal = new List<Something>();
retVal.Add(new SomethingA { Item1 = 1, Item2 = "1" });
retVal.Add(new SomethingB { Item1 = 1, Item2 = "1" });
return retVal;
}
public void ThrowServerException()
{
try
{
throw new ApplicationException("Bad news.");
}
catch (ApplicationException e)
{
throw new WebFaultException<ApplicationException>(e, HttpStatusCode.InternalServerError);
}
}
}
I have some functional tests in another assembly.
using System.Net;
using System.Net.Http;
using System.Runtime.Serialization.Json;
[TestMethod]
public void UseSomething_WebTest()
{
using (HttpClient http = new HttpClient())
{
http.BaseAddress = TestUtil.TestsBaseAddress;
HttpResponseMessage response = http.PostAsJsonAsync("use-something",
new StringContent(string.Empty)).Result;
string ret1 = response.Content.ReadAsStringAsync().Result;
// Deserializes SomethingA as Something.
Stream stream = response.Content.ReadAsStreamAsync().Result;
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(Something));
Something ret = (Something)serializer.ReadObject(stream);
// FAILS.
Assert.AreEqual(typeof(SomethingA), ret.GetType());
}
}
[TestMethod]
public void UsePolymorphicSomethings_WebTest()
{
using (HttpClient http = new HttpClient())
{
http.BaseAddress = TestUtil.TestsBaseAddress;
HttpResponseMessage response = http.PostAsJsonAsync("use-polymorphic-somethings",
new StringContent(string.Empty)).Result;
string ret2 = response.Content.ReadAsStringAsync().Result;
// Deserializes SomethingA and SomethingB correctly.
Stream stream = response.Content.ReadAsStreamAsync().Result;
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(List<Something>));
List<Something> somethings = (List<Something>)serializer.ReadObject(stream);
// SUCCEEDS.
Assert.AreEqual(typeof(SomethingA), somethings[0].GetType());
Assert.AreEqual(typeof(SomethingB), somethings[1].GetType());
}
}
[TestMethod]
public void ThrowServerException1_WebTest()
{
using (HttpClient http = new HttpClient())
{
http.BaseAddress = TestUtil.TestsBaseAddress;
HttpResponseMessage response = http.PostAsync("throw-web-exception",
new StringContent(string.Empty)).Result;
Assert.AreEqual(HttpStatusCode.InternalServerError, response.StatusCode);
string ret3 = response.Content.ReadAsStringAsync().Result;
// Deserializes ApplicationException as Exception.
Stream stream = response.Content.ReadAsStreamAsync().Result;
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(Exception));
Exception e = (Exception)serializer.ReadObject(stream);
// FAILS.
Assert.AreEqual(typeof(ApplicationException), e.GetType());
}
}
In UseSomething_WebTest ret1 is:
"{\"Item1\":2,\"Item2\":\"b\"}"
...with no type information embedded unsurprisingly the DataContractJsonSerializer fails to deserialize the correct type of the object that was returned.
In UsePolymorphicSomethings_WebTest ret2 is:
"[{\"__type\":\"SomethingA:#InSite8WebServiceLib\",\"Item1\":1,\"Item2\":\"1\"},{\"__type\":\"SomethingB:#InSite8WebServiceLib\",\"Item1\":1,\"Item2\":\"1\"}]"
...with type information embedded in the form of __type entries which the DataContractJsonSerializer correctly deserializes.
In ThrowServerException1_WebTest ret3 is:
"{\"ClassName\":\"System.ApplicationException\",\"Message\":\"Bad news.\",\"Data\":null,\"InnerException\":null,\"HelpURL\":null,\"StackTraceString\":\" at InSite8WebServiceLib.Testing.ThrowServerException() in d:\\\\SvnSource\\\\Hammersmith\\\\trunk\\\\VisualStudioProjects\\\\InSite8WebService\\\\InSite8WebServiceLib\\\\Testing\\\\Testing.cs:line 74\",\"RemoteStackTraceString\":null,\"RemoteStackIndex\":0,\"ExceptionMethod\":\"8\\u000aThrowServerException\\u000aInSite8WebServiceLib, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null\\u000aInSite8WebServiceLib.Testing\\u000aVoid ThrowServerException()\",\"HResult\":-2146232832,\"Source\":\"InSite8WebServiceLib\",\"WatsonBuckets\":null}"
...with type information embedded in the form of a ClassName entry which the DataContractJsonSerializer fails to deserialize correctly.
So my question is this. Why for a single WCF WebHttp endpoint do several WebInvoke attributed methods return several different formats of JSON only one of which the DataContractJsonSerializer can actually deserialize, and how do I fix it so that it works properly?
You can force the DataContractJsonSerializer to always emit type information by overloading the constructor. Then you set the alwaysEmitTypeInformation argument to True.
Some more information on MSDN
I am having a real difficult time figuring out why I am getting a 400 bad request from my POST method on my client side. My other POST methods work fine for this service and client. Yet this one isnt working? I was hoping a fresh pair of eyes might find the problem?
My Service looks like this:
[OperationContract]
[WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.Bare, RequestFormat = WebMessageFormat.Xml, ResponseFormat = WebMessageFormat.Xml, UriTemplate = "/Message")]
void AddMessage(Message message);
//Post Method for Message
[DataContract(Name = "Message")]
public class Message
{
[DataMember(Name = "MessageID")]
public string MessageID { get; set; }
[DataMember(Name = "GroupMessage")]
public string GroupMessage { get; set; }
//DataContracts for Message
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class RawDataService : IReceiveData
{
List<Message> messages = new List<Message>();
int eCount = 0;
public void AddMessage(Message message)
{
message.MessageID = (++eCount).ToString();
messages.Add(message);
}
// add message method, increment MessageID
Client Code to Post which gives the 400 bad request on marked line:
private void button15_Click(object sender, EventArgs e)
{
string uriMessage = "http://localhost:8000/Service/Message";
StringBuilder sb1 = new StringBuilder();
sb1.AppendLine("</Message>");
sb1.AppendLine("<GroupMessage>" + this.textBox22.Text + "</GroupMessage>");
sb1.AppendLine("</Message>");
string GroupMessage = sb1.ToString();
byte[] arr1 = Encoding.UTF8.GetBytes(GroupMessage);
HttpWebRequest req1 = (HttpWebRequest)WebRequest.Create(uriMessage);
req1.Method = "POST";
req1.ContentType = "application/xml";
req1.ContentLength = arr1.Length;
Stream reqStrm1 = req1.GetRequestStream();
reqStrm1.Write(arr1, 0, arr1.Length);
reqStrm1.Close();
HttpWebResponse resp1 = (HttpWebResponse)req1.GetResponse(); //400 bad request?
MessageBox.Show(resp1.StatusDescription);
reqStrm1.Close();
resp1.Close();
}
This might be it.
sb1.AppendLine("</Message>");
sb1.AppendLine("<GroupMessage>" + this.textBox22.Text + "</GroupMessage>");
sb1.AppendLine("</Message>");
The opening Message element is actually a closing element.