Friday, November 4, 2011

Building a REST Service using WCF

The below code gives a server implementation of building a REST Service using WCF.


[ServiceContract]
public interface IService1
{
[WebGet]
string GetData();    
 
[WebGet]
string GetDataFromValue(int value);    
 
[WebInvoke]
CompositeType GetDataUsingDataContract(SampleItem sample);
 
[WebInvoke]
XElement GetDataFromString(XElement xmlString);
 
[WebInvoke]
string GetDataFromStringAsString(string xmlString);        
}


public class SampleItem
{
    public int Id { get; set; }
    public string StringValue { get; set; }
    public Child MyChild { get; set; }
}
 
public class Child
{
    public string ChildInfo { get; set; }
}

 
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
[KnownType(typeof(CompositeType))]
public class Service1 : IService1
{
public string GetData()
{
return "Welcome to server";
}
 
public string GetDataFromValue(int value)
{
return string.Format("You entered: {0}", value);
}    
 
public SampleItem GetDataUsingDataContract(SampleItem sample)
{
if (sample == null)
{
throw new ArgumentNullException("sample");
}
if (sample.BoolValue)
{
sample.StringValue += "Suffix";
}
return sample;
}
 
public XElement GetDataFromString(XElement xmlString)
{
xmlString.Name = xmlString.Name + "_modified";
return xmlString;
}
 
public string GetDataFromStringAsString(string xmlString)
{
if (xmlString.Length > 0)
return "Hello World";
return "No String";
}
 
public string GetDataFromStrings()
{
string xmlString = HttpContext.Current.Request.Form["xmlString"];
string strXml = HttpContext.Current.Request.Form["strXml"];
if (xmlString.Length > 0 && strXml.Length > 0)
return xmlString + strXml + " appended from server";
return "Either of the string is empty";
}
}

The AspNetCompatiblity mode is set to access the HttpContext. in the GetDataFromStrings() method.

Also we can build the same Rest service in an MVC style as shown below:


[ServiceContract]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
public class RestService
{
// TODO: Implement the collection resource that will contain the SampleItem instances
private static List<SampleItem> sampleCollection = new List<SampleItem>();
[WebGet]
public List<SampleItem> GetCollection()
{
// TODO: Replace the current implementation to return a collection of SampleItem instances
if (sampleCollection.Count == 0)
{
sampleCollection = new List<SampleItem>();
sampleCollection.Add(new SampleItem() { Id = 1, StringValue = "Hello 1" });
sampleCollection.Add(new SampleItem() { Id = 2, StringValue = "Hello 2" });
sampleCollection.Add(new SampleItem() { Id = 3, StringValue = "Hello 3" });
sampleCollection.Add(new SampleItem() { Id = 4, StringValue = "Hello 4" });
sampleCollection.Add(new SampleItem() { Id = 5, StringValue = "Hello 5" });
}
return sampleCollection;
}
 
[WebInvoke]
public SampleItem Create(SampleItem instance)
{   
sampleCollection.Add(instance);
return instance;
}
 
[WebGet(UriTemplate = "{id}")]
public SampleItem Get(string id)
 
{
// TODO: Return the instance of SampleItem with the given id
return sampleCollection.Where(i => i.Id == Convert.ToInt32(id)) as SampleItem;
}
 
[WebInvoke(UriTemplate = "{id}", Method = "PUT")]
public SampleItem Update(string id, SampleItem instance)
{
SampleItem objSample = sampleCollection.Where(i => i.Id == Convert.ToInt32(id)) as SampleItem;
objSample = instance;
return objSample;
}
 
[WebInvoke(UriTemplate = "{id}", Method = "DELETE")]
public void Delete(string id)
{
sampleCollection.Remove(sampleCollection.Where(i => i.Id == Convert.ToInt32(id)) as SampleItem);
}
 
[WebInvoke]
public string InsertSampleItemFromXml(XElement xmlString)
{
if(!String.IsNullOrEmpty(xmlString.ToString()))
{
return "Got this xml on server -----> " + xmlString.ToString();
}
else
{
return "Excpetion";
}
}
}

You then have to register this in the Global.asax as shown below:


public class Global : HttpApplication
{
void Application_Start(object sender, EventArgs e)
{
RegisterRoutes();
}
 
private void RegisterRoutes()
{
// Edit the base address of Service1 by replacing the "Service1" string below
RouteTable.Routes.Add(new ServiceRoute("RestService", new WebServiceHostFactory(), typeof(RestService)));
}
}

Once you do this you would have the URL for the service as shown when hosted in IIS:


http://localhost/RestVirtualDirectory/RestService/Create or
http://localhost/RestVirtualDirectory/RestService/GetCollection or
http://localhost/RestVirtualDirectory/RestService/Update

2 comments:

Vaibhav said...

What is sampleItem in your blog when i am try to implement your solutions i am getting error.

Rajesh S V said...

SampleItem can be any simple POCO. But I am going to include the one i have used in my sample soon.