WCF – Service using WebInvoke
Most services are more complicated than the simple service I just described.
Most services require you to send in XML or an object (an object which has been serialized to XML).
This means we need an object to pass in.
I created the PersonObject for this.
The object being sent in must have a DataContract. The DataContract specifies what properties are seen by the webservice, and which properties are required.
In this simple example, there are no required properties (or DataMembers).
namespace SandboxObjects
{
[DataContract]
public class PersonObject
{
[DataMember]
public string lastName;
[DataMember]
public string firstName;
}
}
The Interface become more complex than the Simple Example.
We use the 'WebInvoke' attribute instead of 'WebGet'.
We specify the Method as POST.
The UriTemplate is Hello2 (same as the method name.. for now... more on that later)
We also specify the request and the response format as XML (Json is another posibility but not discussed here)
Lastly the input and output types are both PersonObject.
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "Hello2", RequestFormat = WebMessageFormat.Xml, ResponseFormat = WebMessageFormat.Xml, BodyStyle = WebMessageBodyStyle.Bare)]
SandboxObjects.PersonObject Hello2(SandboxObjects.PersonObject person);
I am just returning the object sent in to make it simple:
public SandboxObjects.PersonObject Hello3(SandboxObjects.PersonObject person)
{
return person;
}
The Web.config setting are identical to for this method as they are for the Simple Service example.
Calling this service is different. You can't call it from the browser. If you do, you get the error 'Method not allowed'
http://localhost:3041/SandboxWebsite/TestService.svc/Web/Hello3
Before calling the service, the object must be serialized:
SandboxObjects.PersonObject p = new SandboxObjects.PersonObject(); p.firstName = "Joe"; p.lastName = "Smith"; Stream xmlStream = ObjectToXml(p); XmlDocument xDoc = new XmlDocument(); xDoc.Load(xmlStream); string xmlString = xDoc.InnerXml;
Simple method to serialize an object:
public static Stream ObjectToXml(Object obj)
{
MemoryStream memoryStream = new MemoryStream();
DataContractSerializer dcSerializer = new DataContractSerializer(obj.GetType());
XmlWriterSettings xmlWriterSettings = new XmlWriterSettings();
xmlWriterSettings.Encoding = new UTF8Encoding(false);
xmlWriterSettings.ConformanceLevel = ConformanceLevel.Document;
xmlWriterSettings.Indent = true;
//xmlWriterSettings.OmitXmlDeclaration = true;
using (XmlWriter xWriter = XmlWriter.Create(memoryStream, xmlWriterSettings))
{
dcSerializer.WriteObject(xWriter, obj);
xWriter.Flush();
//return Encoding.UTF8.GetString(memoryStream.ToArray());
memoryStream.Position = 0;
return memoryStream;
}
}
No that you have the serialized object, you can call the servie. This simple example does so using the WebClient object:
string url = "http://localhost:3041/SandboxWebsite/TestService.svc/Web/Hello3";
var webClient = new WebClient();
webClient.Headers.Add("Content-Type", "application/xml; charset=utf-8");
string p1 = webClient.UploadString(url, "POST", xmlString);
More comple, but more useful method using HttpWebRequest:
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "POST";
byte[] bytes = Encoding.UTF8.GetBytes(xmlString);
request.ContentLength = bytes.Length;
request.ContentType = "text/xml; encoding='utf-8'";
Stream requestStream = request.GetRequestStream();
requestStream.Write(bytes, 0, bytes.Length);
requestStream.Close();
// get response
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
// process response
XmlDocument xmlResponse = new XmlDocument();
if (response.StatusCode == HttpStatusCode.OK)
{
Stream responseStream = response.GetResponseStream();
XmlTextReader xmlReader = new XmlTextReader(responseStream);
xmlResponse.Load(xmlReader);
responseStream.Close(); // close connections
xmlReader.Close(); // close connections
xmlReader = null; // release the objects
responseStream = null; // release the objects
}
response.Close(); // close connections
requestStream = null; // release the objects
response = null; // release the objects
request = null; // release the objects
return XMLResponse; // return the XML response!