How to post data to RESTful WCF service
Last post I wrote about getting data from RESTful service. And this post is about uploading / posting data to a RESTful service. In this I am modifying the same interface, and adding a method which accepts a stream parameter, for getting the data in the service side.
[OperationContract] [WebInvoke(Method = "POST", UriTemplate = "update")] void UpdateTime(Stream data);
And in the implementation side, I am display the contents to Service host window.
public void UpdateTime(Stream data)
{
using (var sr = new StreamReader(data))
{
Console.WriteLine(sr.ReadToEnd());
}
}
And the I am using this code to POST DATA USING HTTPWEBREQUEST IN C# to send data to the service.
How to create RESTful WCF services
In the current project, I am working with WCF services in .Net 4.0. Few days back I got a question like how can we make a WCF service RESTful. Yesterday I played around it and I could figure out how it works.
In this post I am posting how to create a RESTful time service, which will give the current system time,
http://localhost:8080/TimeService/
and the next method give current time with specified format.
http://localhost:8080/TimeService/ddMMMyyyy
As usual for creating a WCF service you need a service contract. For making WCF services you need special attributes. And you need to add reference of System.ServiceModel.Web. And if you want use custom POCO classes, you need to add the reference of System.Runtime.Serialization.
Here is the Service interface
[ServiceContract]
interface ITimeService
{
[OperationContract]
[WebGet(UriTemplate = "/")]
string GetTime();
[OperationContract]
[WebGet(UriTemplate = "/{timeformat}")]
string GetFormattedTime(string timeformat);
}
The WebGet attribute is enables the GET method in the service. The UriTemplate specifies the address. And all the parameters should be string, and parameter name should be match. It also support POST and PUT protocols.
And here is the implementation
class TimeService : ITimeService
{
public string GetTime()
{
return DateTime.Now.ToString();
}
public string GetFormattedTime(string timeformat)
{
return DateTime.Now.ToString(timeformat);
}
}
I am using Self Hosting for this. And here is this Service Host implementation.
static void Main(string[] args)
{
using (ServiceHost serviceHost =
new ServiceHost(typeof(TimeService)))
{
string baseUri =
string.Format("http://{0}:8080/TimeService",
Environment.MachineName);
ServiceEndpoint serviceEndPoint =
serviceHost.AddServiceEndpoint(typeof(ITimeService),
new WebHttpBinding(), baseUri);
serviceEndPoint.Behaviors.Add(new WebHttpBehavior());
serviceHost.Open();
Console.WriteLine(
string.Format("Server available on the url - {0}",
baseUri));
Console.WriteLine("Press <ENTER> to stop listening.");
Console.ReadLine();
serviceHost.Close();
}
}
Here is the screen shot RESTful service running.
And here is the the screenshot of the RESTful service accessing via Internet Explorer.
This following code snippet to how to access WCF RESTful service with WebClient.
using (WebClient webClient = new WebClient())
{
using(StreamReader sr =
new StreamReader(
webClient.OpenRead("http://localhost:8080/TimeService/")))
{
Console.WriteLine(sr.ReadToEnd());
}
}
WCF Test Client
While working in a WCF Project, I got a nice link talking about WCF Test Client, its a cool application to Test WCF Services. From WCFTestClient Help
Windows Communication Foundation (WCF) Test Client (svcTestClient.exe) is a GUI tool that allows users to input test parameters, submit that input to the service, and view the response that the service sends back. It provides a seamless service testing experience when combined with WCF Service Host.
You can invoke the WCFTestClient from Visual Studio command prompt. Either using wcftestclient.exe or providing the WCFTestclient.exe with the URL of the service as the commandline parameter.
You can get more details about WCFTestClient from MSDN
Deploying WCF Service in IIS : no svc MIME Type
Few days back I developed a Silverlight application, which uses a WCF Service to communicate to Database. After the development when I tried to deploy the WCF Service on my IIS, it was displaying some error like
Server Error in Application “Default Web Site/SampleApp”
HTTP Error 404.3 – Not Found
Description: The page you are requesting cannot be served because of the Multipurpose Internet Mail Extensions (MIME) map policy that is configured on the Web server. The page you requested has a file name extension that is not recognized, and is not allowed.
Error Code: 0×80070032
Notification: ExecuteRequestHandler
Module: StaticFileModule
Requested URL: http://localhost:80/SampleApp/CoreService.svc
Physical Path: C:\Users\Documents\Visual Studio 2005\Projects\SampleApp\SampleApp\CoreService.svc
Logon User: Anonymous
Logon Method: Anonymous
Handler: StaticFile
I tried IIS MimeTypes and I couldn’t found an application mapping for SVC file. After doing some searching I found the fix. It is happening because of not registering the WCF in IIS. You can resolve this using WCF Installation utility which comes with .Net Framework 3.0. Run the command prompt as Administrator, go to the Windows Communication Foundation folder in c:\Windows\Microsoft.NET\Framework\v3.0\ folder. Execute the servicemodelreg.exe with -i or /i switch. After the installation try reloading the Page. It will fix this issue.
File Uploader using Silverlight and WCF
From Silverlight 2 onwards it supports Open File Dialog, which helps developers to implement upload file logic, with the help of WCF services. Silverlight Open File Dialog offers better control over the existing HTML FileUpload control, like File Filter, File Sizes etc, and it can be managed from client side. Here is a simple implementation of Silverlight uploader with WCF.
Silverlight UI – XAML
<Canvas x:Name="LayoutRoot">
<StackPanel Margin="10" Background="White" Orientation="Horizontal">
<TextBlock Text="Select File :" />
<TextBox Name="txtFileName" Width="200" />
<Button Name="cmdBrowse" Content="Browse" Click="cmdBrowse_Click" />
<Button Name="cmdUpload" Content="Upload" Click="cmdUpload_Click" />
</StackPanel>
</Canvas>
And the code behind
FileInfo fi;
private void cmdBrowse_Click(object sender, RoutedEventArgs e)
{
//Open File Dialog
OpenFileDialog dlg = new OpenFileDialog();
//The _FilterText variable used to control file extentions
//supported by the Upload control
dlg.Filter = this._FilterText;
bool? result = dlg.ShowDialog();
if (result.HasValue && result.Value)
{
this.fi = dlg.File;
//The _FileSize variable used to control the
//Maximum Size supported by the control.
if (this.fi.Length > this._FileSize)
{
//Control will fire a FileSizeError event, if the
//Uploading File Size greater than the specified.
if (this._onFileSizeError != null)
{
this._onFileSizeError(this, EventArgs.Empty);
}
return;
}
this.txtFileName.Text = this.fi.Name;
}
}
private void cmdUpload_Click(object sender, RoutedEventArgs e)
{
//Uploading part.
if (this.fi != null)
{
byte[] buffer = new byte[this.fi.Length];
using (Stream s = this.fi.OpenRead())
{
//Reading the File Content to the Stream.
//It is using a WCF Service with Upload File method
s.Read(buffer, 0, buffer.Length);
ServiceReference1.Service1Client client = new ServiceReference1.Service1Client();
client.UploadFileCompleted += new EventHandler<System.ComponentModel.AsyncCompletedEventArgs>(client_UploadFileCompleted);
client.UploadFileAsync(this.fi.Name, buffer);
}
}
}
private void client_UploadFileCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
{
//Application will raise another Event
//after the completion of the File Upload.
if (this._onFileUploadCompleted != null)
{
this._onFileUploadCompleted(this, EventArgs.Empty);
}
}
And here is the WCF Service with Upload File method.
//IService1 Interface
[ServiceContract]
public interface IService1
{
[OperationContract]
void UploadFile(string fileName, byte[] content);
}
//IService1 Interface implementation
public class Service1 : IService1
{
public void UploadFile(string fileName, byte[] content)
{
using (FileStream sw = File.OpenWrite(Path.Combine(@"C:\Uploads", fileName)))
{
sw.Write(content, 0, content.Length);
}
}
}
To enable communication between Silverlight and Javascript the “System.Windows.Browser” namespace is used. Which supports various attributes and methods, will expose the properties and events of the silverlight application to the Javascript.
public MainPage()
{
InitializeComponent();
//This method enables the scripting support to the Application.
//From Javascript developer can access the Properties and events
//like SilverlightObj.Content.Page.Property
HtmlPage.RegisterScriptableObject("Page", this);
}
private string _FilterText = "Text Files|*.txt";
private int _FileSize = 1000;
private event EventHandler _onFileSizeError;
private event EventHandler _onFileUploadCompleted;
//This attribute used to expose the Property to Client side.
//From Javascript : ctrl.Content.Page.FileSize = 2000;
[ScriptableMember]
public int FileSize
{
get
{
return this._FileSize;
}
set
{
this._FileSize = value;
}
}
[ScriptableMember]
public string Filter
{
get
{
return this._FilterText;
}
set
{
this._FilterText = value;
}
}
[ScriptableMemberAttribute]
public EventHandler OnFileSizeError
{
get
{
return this._onFileSizeError;
}
set
{
this._onFileSizeError = value;
}
}
[ScriptableMemberAttribute]
public EventHandler OnFileUploadCompleted
{
get
{
return this._onFileUploadCompleted;
}
set
{
this._onFileUploadCompleted = value;
}
}
And in the Javascript, the property can access and can modify it.
function onPluginLoaded() {
var ctrl = document.getElementById("silverlightControlHost1");
ctrl.Content.Page.Filter = "Image Files|*.jpg;*.gif;*.png|All Files(*.*)|*.*";
ctrl.Content.Page.FileSize = 20000;
ctrl.Content.Page.OnFileSizeError = function () {
alert("File Size should be less than 2 KB");
};
ctrl.Content.Page.OnFileUploadCompleted = function () {
alert("Uploaded successfully !");
};
}
And the HTML Part – Here the onLoad parameter will assign the Javascript to execute on loading of the silverlight application.
<object id="silverlightControlHost1" data="data:application/x-silverlight-2," type="application/x-silverlight-2"
width="100%" height="100%">
<param name="onLoad" value="onPluginLoaded" />
</object>
And here is the screen shot, of the same running on my Windows 7 machine.
Please let me know your comments and feedbacks. Happy Programming.



