Uploading File to server from ASP.Net client using WCF REST Service

Very often I see one question flooding in all forums, “How to upload a File using WCF REST Service? “, so I thought let me write a post on the same.

Essentially, there is nothing specific to do to upload file, but the below steps

1. Create a service with Post operation

2. Pass file data as Input Stream

3. Pass name of the File

4. Host the service in console application [Note : You can host wherever you want though]

Let us first create Service Contract.

clip_image002

If you notice above Service contract is creating a REST resource with POST method. One of the input parameter is Stream.

For your reference, contract interface would look like as below, [You can copyJ]

IService1.cs


using System.ServiceModel;
using System.ServiceModel.Web;
using System.IO;
namespace RESTImageUpload
{
[ServiceContract]
public interface IImageUpload
{
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "FileUpload/{fileName}")]
void FileUpload(string fileName, Stream fileStream);

}
}

Once Contract is defined we need to implement service to save a file on sever location.

clip_image004

You need to make sure you have a folder FileUpload created on D drive of your server else you would get “Device not ready “exception.

Since Write () method takes byte array as input to write data in a file and input parameter of our service is Stream , so we need to do a conversion between Stream to Bye Array

clip_image006

Final Service implementation would look like below [You can CopyJ]

Service1.svc.cs


using System.IO;
namespace RESTImageUpload
{

public class ImageUploadService : IImageUpload
{

public void FileUpload(string fileName, Stream fileStream)
{

FileStream fileToupload = new FileStream("D:\\FileUpload\\" + fileName, FileMode.Create);

byte[] bytearray = new byte[10000];
int bytesRead, totalBytesRead = 0;
do
{
bytesRead = fileStream.Read(bytearray, 0, bytearray.Length);
totalBytesRead += bytesRead;
} while (bytesRead > 0);

fileToupload.Write(bytearray, 0, bytearray.Length);
fileToupload.Close();
fileToupload.Dispose();

}

}
}

So far we are done with Service definition and implementation and now we need to host the service. I am going to host service in a console application. Host program would have reference of System.ServiceModel and System.ServiceModel.Web. If you are not able to find System.ServiceModel.Web reference to add in your console application then change the target framework to .Net Framework 4.0 from .Net Framework 4.0 client profile.

Program.cs


using System;
using System.ServiceModel;
using RESTImageUpload;
using System.ServiceModel.Description;

namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
ServiceHost host = new ServiceHost(typeof(ImageUploadService), new Uri(baseAddress));
host.AddServiceEndpoint(typeof(IImageUpload), new WebHttpBinding(), "").Behaviors.Add(new WebHttpBehavior());
host.Open();
Console.WriteLine("Host opened");
Console.ReadKey(true);
}
}
}

Press F5 to run the service hosted in console application.

clip_image008

Service is up and running so let us call this service to upload the file.

I am creating a simple ASP.Net Web Application with File Upload control and a button. ASPX page looks like below

Default.aspx


u<%@ Page Title="Home Page" Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true"
CodeBehind="Default.aspx.cs" Inherits="WebApplication1._Default" %>

<asp:Content ID="HeaderContent" runat="server" ContentPlaceHolderID="HeadContent">
</asp:Content>
<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
<h2>
Welcome to ASP.NET!
</h2>
<p>
To learn more about ASP.NET visit <a href="<a href="http://www.asp.net">http://www.asp.net</a>" title="ASP.NET Website">www.asp.net</a>.
</p>
<p>
You can also find <a href="<a href="http://go.microsoft.com/fwlink/?LinkID=152368&amp;clcid=0x409">http://go.microsoft.com/fwlink/?LinkID=152368&amp;clcid=0x409</a>"
title="MSDN ASP.NET Docs">documentation on ASP.NET at MSDN</a>.
</p>
<asp:FileUpload ID="FileUpload1" runat="server" />
<asp:Button ID="Button1" runat="server"
Text="Upload File" />
</asp:Content>

On click event of button we need to make a call to the service to upload the file.

clip_image010

In above code, I am making a HTTP Web Request and explicitly specifying method is POST and content type is text/plain. We need to get the Request Stream and write the byte array in that. As HTTP response you can get the status code.

For your reference client code would look like as below,

Default.aspx.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.IO;
using System.Web.UI.WebControls;
using System.Net;

namespace WebApplication1
{
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
Button1.Click += new EventHandler(Button1_Click);
}

void Button1_Click(object sender, EventArgs e)
{
byte[] bytearray=null ;
string name = "";
//throw new NotImplementedException();
if (FileUpload1.HasFile)
{
name = FileUpload1.FileName;
Stream stream = FileUpload1.FileContent;
stream.Seek(0, SeekOrigin.Begin);
bytearray = new byte[stream.Length];
int count = 0;
while (count < stream.Length)
{
bytearray[count++] = Convert.ToByte(stream.ReadByte());
}

}

string baseAddress = "http://" + Environment.MachineName + ":8000/Service/FileUpload/";
HttpWebRequest request = (HttpWebRequest) HttpWebRequest.Create(baseAddress+name);
request.Method = "POST";
request.ContentType = "text/plain";
Stream serverStream  = request.GetRequestStream();
serverStream.Write(bytearray, 0, bytearray.Length);
serverStream.Close();
using ( HttpWebResponse response = request.GetResponse() as HttpWebResponse )
{
int statusCode =(int) response.StatusCode;
StreamReader reader = new StreamReader( response.GetResponseStream() );

}

}
}
}

I hope this post was useful and saved your time to upload a file. In next post I will show you how to upload an image from Silverlight client.

About these ads

20 thoughts on “Uploading File to server from ASP.Net client using WCF REST Service

  1. Thanks..very useful, it would really helpful for me to upload image file on server…. Thanks lot.. I will implement this….

  2. Pingback: Dew Drop – May 2, 2011 | Alvin Ashcraft's Morning Dew

  3. Why so much code?

    public void FileUpload(string fileName, Stream fileStream)
    {
    using(var fileToupload =
    new FileStream(
    string.Concat(“D:\\FileUpload\\”, fileName),
    FileMode.Create))
    {
    fileStream.CopyTo(fileToupload);
    }
    }
    :-)

  4. Hi Daniel ,

    was that coded not needed ? please share if you have lesser code to share

  5. I tried to implement this, and received an error: “For request in operation to be a stream, the operation must have a single parameter whose type is Stream.”

    And looking at all the MSDN documents, they state that to use a stream, the only parameter can be the stream.

    Can you tell me how you are able to send a string parameter as well?

  6. I don’t understand. I can only get 1 parameter when using streaming. It won’t let me add the fileName parameter.

    How do I fix this?

  7. Pingback: Monthly Report May 2011: Total Posts 16 « debug mode……

  8. Anyone knows why I can’t upload files bigger than 4 Mo ? I’ve setup both asp.net and wcf web config to accept about 2 Go

    Here’s the asp

    Here’s the WCF on the binding used by myservice

    And here’s the standard endpoint

    I’m stuck on that issue for 3 days, can anyone help me ?

    Thanks

  9. Thanks for the great article. However, I keep getting this Error with your (unmodified) code:

    “The remote server returned an error: (400) Bad Request.” at Default.aspx.cs at line 47:

    (line 47:)
    using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)

    Checking the Server Trace, I see:

    http://msdn.microsoft.com/en-US/library/System.ServiceModel.Diagnostics.TraceHandledException.aspxHandling an exception.6be8a0e4-1-129737975619047947System.InvalidOperationException, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089

    The service operation ‘Post’ expected a value assignable to type ‘Stream’ for input parameter ‘fileStream’ but received a value of type ‘HttpRequestMessage`1′.

    at Microsoft.ApplicationServer.Http.Dispatcher.OperationHandlerPipelineInfo.ServiceOperationHandler.ValidateAndConvertInput(Object[] values)
    at Microsoft.ApplicationServer.Http.Dispatcher.OperationHandlerPipelineInfo.GetInputValuesForHandler(Int32 handlerIndex, Object[] pipelineValues)
    at Microsoft.ApplicationServer.Http.Dispatcher.OperationHandlerPipeline.ExecuteRequestPipeline(HttpRequestMessage request, Object[] parameters)
    at Microsoft.ApplicationServer.Http.Dispatcher.OperationHandlerFormatter.OnDeserializeRequest(HttpRequestMessage request, Object[] parameters)
    at Microsoft.ApplicationServer.Http.Dispatcher.HttpMessageFormatter.DeserializeRequest(HttpRequestMessage request, Object[] parameters)
    at … (etc.)

    any idea how I can fix this? I’m stuck with this problem for a few days now.

    Thanks,
    Arie

  10. I think Mr. Fisher’s idea to use fileStream.CopyTo to save the incoming stream is good. I just tried his idea out on my own code and it seemed to work for me.

    BTW (Rant): It would be nice if this site supported Windows Live Authentication. I’m getting tired of being forced to lug my Google Credentials around when I mostly use Microsoft Products. For one, Google asked me to supply the month and day of my birthday for everyone on Google Plus to see. There is no need for people to see my birthday. That’s just one more piece of information hackers can use to steal my identity. I’ll be glad when Microsoft obliterates Google and Apple off the face of this planet!!!

  11. I tried to implement this, and received an error: “For request in operation to be a stream, the operation must have a single parameter whose type is Stream.”

    And looking at all the MSDN documents, they state that to use a stream, the only parameter can be the stream.

    Can you tell me how you are able to send a string parameter as well?

    And I also removed the filename parameter, still getting error “The remote server returned an error: (400) Bad Request.” at webform1.aspx.cs at :
    using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)

    Please help me fix these.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s