So I want to send a custom object to an asp.net 4.0 Webservice.
I have been sending a bunch of individual parameters but i want to start reusing some code so I'd like to do something like
[WebMethod(Description = "Testing Sending Object In")]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public bool COT(CodeWithMessage CWM)
{
...
where the class for CodeWithMessage is
namespace UserSite
{
namespace General
{
public class CodeWithMessage
{
public int iCode { get; set; }
public string sMessage { get; set; }
public CodeWithMessage()
{
}
}
}
}
The webservice defines the input as
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<COT xmlns="http://localhost">
<CWM>
<iCode>int</iCode>
<sMessage>string</sMessage>
</CWM>
</COT>
</soap:Body>
</soap:Envelope>
I tried passing the webservice the following json
var postdata = { "iCode": -5, "sMessage": "BlogName " }
I get back an Internal Server Error [500]
{"Message":"Invalid JSON primitive: iCode."
Do I need to wrap this up somehow to indicate it is part of this object? I tried
{"__type":"UserSite.General.CodeWithMessage","iCode":-5,"sMessage":"Blog Name Already Exists"}
Which is what CodeWithMessage returns from another webservice that sends it instead of receiving it.
Your error says that you Json is wrong you need to check the json string you are passing to the webservice.
its may be like
var postdata = { 'iCode': '-5', 'sMessage': 'BlogName' }
check the jSon String example : http://www.json.org/js.html on jSon site........
Related
I have already spent two days trying to find a solution to my problem and no results, so I would appreciate any hints.
What I am trying to achieve:
Briefly, I have created and published a WCF service (RESTful web services) with one method GetUsers that should return something like this:
[{"Name":"John","Surname":"Dell","GroupName":"Operator"}, {"Name":"John1","Surname":"Hp","GroupName":"Operator"}, {"Name":"John2","Surname":"Apple","GroupName":"Operator"}]
Unfortunately, when I test this method in the browser (http://localhost:28099/TestAPI.svc/GetUsers?inputName=Company, I get the response which includes the escape backslash and the double quotes at the beginning and at the end of the result, like below:
"[{\"Name\":\"John\",\"Surname\":\"Dell\",\"GroupName\":\"Operator\"}, {\"Name\":\"John1\",\"Surname\":\"Hp\",\"GroupName\":\"Operator\"}, {\"Name\":\"John2\",\"Surname\":\"Apple\",\"GroupName\":\"Operator\"}]"
The application consuming this webservice is telling me that this is not a valid JSON format.
In my web service method, I am getting the initial data in XML format, passing it to a datatable object, and then trying to convert it to JSON using the JSON.NET.
Below is the source XML:
<Root>
<row Name ="John" Surname="Dell" GroupName="Operator"/>
<row Name ="John1" Surname="Hp" GroupName="Operator"/>
<row Name ="John1" Surname="Apple" GroupName="Operator"/>
</Root>
Below is a snippet from my WCF code:
[ServiceContract]
public interface IWebServiceTest
{
[OperationContract]
[WebGet(ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare)]
String GetUsers(string inputName);
}
public class TestWCF: IWebServiceTest
{
Public String GetUsers(string inputName)
{
...................
StringReader stringReader1 = new StringReader(responseXMLResult.ToString());
XmlReader reader = XmlReader.Create(stringReader1);
ds.ReadXml(reader);
string json = JsonConvert.SerializeObject(ds.Tables[0], Newtonsoft.Json.Formatting.None);
return json
}
As Evk said, WCF has serialized the value you return to JSON, we don't need to use JSON NET anymore. In WCF we use DataContract to serialize objects. Here is a demo:
[ServiceContract]
public interface IService
{
[OperationContract]
[WebGet(ResponseFormat =WebMessageFormat.Json,BodyStyle =WebMessageBodyStyle.Bare)]
Person GetUsers();
}
This is the service interface, we set ResponseFormat to json.
[DataContract]
public class Person
{
[DataMember]
public string Name { get; set; }
[DataMember]
public string Surname { get; set; }
[DataMember]
public string GroupName { get; set; }
}
This is the Person object we want to transfer, we use DataContract to serialize the object.
public class Service : IService
{
public Person GetUsers()
{
Person person = new Person();
person.Name = "wwww";
person.Surname = "Dell";
person.GroupName = "Operator";
return person;
}
}
This is the implementation class of the method, we return the person object directly, and WCF will help us serialize this object into json and return it to the client.
The XML serializer of the RestSharp request is set to DotNetXmlSerializer.
I make the following REST call with RestSharp :
var response = restClient.Execute<TokenReponse>(request);
This call yields the following response:
<?xml version="1.0" encoding="utf-8"?>
<lsvt_apiResult
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<result>true</result>
<data xsi:type="xsd:string">TokenStringValueHere</data>
</lsvt_apiResult>
TokenResponse is the following C# class:
internal class TokenReponse
{
[XmlElement("result")]
public string Result { get; set; }
[XmlElement("data")]
public string Token { get; set; }
}
When RestSharp deserializes the XML into an instance of TokenResponse, the 'Result' property is being correctly set; however, the 'Token' property is set to null. I have verified that the XML response has the data set to some token string value before deserialization. How do I correctly set the 'Token' property to the value of the 'data' XML element?
Furthermore, when changing the name of the 'Token' property to 'Value' the value is set to "trueTokenStringValueHere" when the above XML response is received.
I have a wcf restful service on a IIS server.
I have made some API, which can be called sending both xml or json.
I've made my C# classes and then, I'm testing it. With JSON is perfect, but I have still some issues with XML request.
I want to send the xml with a post and this is the xml I send:
<?xml version="1.0" encoding="utf-8" ?>
<SetClientiXML
xmlns="http://tempuri.org/">
<dati>
<ArrayOfWrapClienti
xmlns="http://schemas.datacontract.org/2004/07/MultipayOnline"
xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<WrapClienti>
<CODRETE>0018</CODRETE>
<CODICE>20685</CODICE>
<NOME>A.T.E.R. Azienda Territoriale</NOME>
<INDIRIZZO>PIAZZA POZZA</INDIRIZZO>
<CITTA>Verona</CITTA>
<CAP>37123</CAP>
<PROV>VR</PROV>
<CODICEFISCALE>00223640236</CODICEFISCALE>
<PIVA>223640236</PIVA>
<EMAIL/>
<ESPOSIZ_CONTABILE>937,02</ESPOSIZ_CONTABILE>
<STATO>FALSE</STATO>
</WrapClienti>
</ArrayOfWrapClienti>
</dati>
<retista>3303903</retista>
<hashedString>oklkokokokok</hashedString>
</SetClientiXML>
the wcf read well "retista" and "hashedString", but "dati" is empty (0 elements), while I expect it has got the "wrapClienti" object I sent.
This is the prototype of my API:
[OperationContract]
[WebInvoke(UriTemplate = "SetClienti.xml", Method = "POST", BodyStyle=WebMessageBodyStyle.Wrapped, RequestFormat = WebMessageFormat.Xml)]
GenericResponse SetClientiXML(List<WrapClienti> dati, string retista, string hashedString);
So, the problem is that the List is empty.. why? How can I write the xml to make readable the list?
Ask me if I can give to you more details.
UPDATE: More weird!!
With this xml:
<?xml version="1.0" encoding="utf-8" ?><SetClientiXML xmlns="http://tempuri.org/">
<dati>
<WrapClienti xmlns="http://schemas.datacontract.org/2004/07/MultipayOnline" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<CODRETE>0018</CODRETE>
<CODICE>20685</CODICE>
<NOME>A.T.E.R. Azienda Territoriale</NOME>
<INDIRIZZO>PIAZZA POZZA</INDIRIZZO>
<CITTA>Verona</CITTA>
<CAP>37123</CAP>
<PROV>VR</PROV>
<CODICEFISCALE>00223640236</CODICEFISCALE>
<PIVA>223640236</PIVA>
<EMAIL/>
<ESPOSIZ_CONTABILE>937,02</ESPOSIZ_CONTABILE>
<STATO>FALSE</STATO>
</WrapClienti>
</dati>
<retista>3303903</retista>
<hashedString>oklkokokokok</hashedString>
</SetClientiXML>
the wcf read some attributes of the List, and other.. are nul!!!
I my WrapClienti I have a lof of attributes. Two of them are:
private string p_CAP { get; set; }
public string CAP
{
get
{
if (model == null)
return p_CAP.ToSafeString();
else
return this.model.CAP.ToSafeString();
}
set { p_CAP = value; }
}
private string p_PROV { get; set; }
public string PROV
{
get
{
if (model == null)
return p_PROV.ToSafeString();
else
return this.model.PROV.ToSafeString();
}
set { p_PROV = value; }
}
the problem is, with the xml above and with two breakpoint on the two set methods, only the set of PROV is called and, the one of CAP, not!!! Why? Now I'm really getting crazy... why this behavior??
Solution here.
This has to do with the ordering of the fields in your XML. It sounds very strange, but WCF DataContractSerializer is really fussy about the order in which the fields are encountered in the XML, but even worse, also in comparison to how they are defined in the code.
You see, the serializer wants the fields to be defined in alphabetical order, and if you serialize an instance of your class, you will find that the resulting XML fields are in alphabetical order. However, on deserialization, the serializer finds that the type you want to deserialize to has the fields defined in the "wrong" order. In this situation the behavior can seem random, but I think it has something to do with the fact that CAP should be the first field encountered, whereas PROV should be the last field, alphabetically.
So you have two options:
Reorder your XML and the fields in your class to be in alphabetical order, or
Decorate your class members with the DataMemeber property, and define the order of serialization.
You can do 2 like this:
[DataContract]
public class WrapClienti
{
[DataMember(Order=1)]
public string CAP { get; set; }
[DataMember(Order=2)]
public string PROV { get; set; }
...etc
}
I have a asp.net webapi v2 running katana and using XmlSerializer with a very simple custom Serialization implementation:
config.Formatters.XmlFormatter.UseXmlSerializer = true;
config.Formatters.XmlFormatter.SetSerializer<SalesOrder>(new XmlSerializer<SalesOrder>());
XmlSerializer is just a simple implementation of the to System.Runtime.Serialization.XmlObjectSerializer abstract class
When calling a Post like this:
public HttpResponseMessage Post([FromBody]SalesOrder value)
{
return value == null || value.SignZoneCustomerNumber.IsNullOrEmpty()
? Request.CreateResponse(HttpStatusCode.BadRequest)
: Request.CreateResponse(HttpStatusCode.Accepted, _service.CreateOrder(value, Request.GetCorrelationId()));
}
The value is null when the xml contains a declaration like this
<?xml version="1.0" encoding="ISO-8859-15"?>
Strip out the declaration and send the post it desearilizes fine.
Any idea why the declaration causes deseriazation to fail?
The Model is defined like this:
[XmlRoot("Order")]
[Serializable]
public class SalesOrder : BaseOrder<SalesOrderLineItem>
{
public string PoNumber { get; set; }
public DateTime? PoDate { get; set; }
...more properties...
}
Thanks
UPDATE
Turns out it was the encoding that caused the problem
this header works:
<?xml version="1.0" encoding="UTF-8"?>
other values like UTF-16 and ISO-8859-1 fail
any idea why?
I need to return xml from my mvc 4 web api, it should look like this:
<?xml version="1.0" encoding="UTF-8" ?>
<response>
<success/>
</response>
My code currently looks like this:
Request.CreateResponse<string>(HttpStatusCode.OK, "success", Configuration.Formatters.XmlFormatter);
And the xml it returns looks like this, which doesn't meet the client's requirements:
<string>success</string>
Is there a way to achieve my desired result?
Thank you!
Try defining a Reponse class and have your web api return a CreateResponse<Response> instead:
[System.Xml.Serialization.XmlRootAttribute(ElementName="response")]
public class Response
{
[System.Xml.Serialization.XmlElement(IsNullable = true)]
public string success { get; set; }
}