Wednesday, July 18, 2012

Send uploaded file stream to a WCF service

Last week I accessed a WCF service from JQery and consumed a Json typed object. But this time, it is totally different. I wanted to send a file stream to the WCF service without using client side script to access the WCF service.

If I brief the scenario, first there should be a client side file upload to user to upload a file, then that file should pass to the WCF service. HttpHandler was the first thing came in to my mind when I thought about creating a bridge between client side upload and receiving file stream by WCF service. Following are the steps I carried out to successfully complete the solution.

First I will create the HttpHander which gets the file from the JQery file uploader and sends the stream to the WCF service,

Right click your web site and under "Add New Item" select "Generic Handler" then give the name as "AjaxFileUploadHandler.ashx" and add item to the web site. Then add following code block to the handler ("_client" public variable is the WCF service client).


 public class AjaxFileUploadHandler : IHttpHandler
    {
        Service1Client _client = new Service1Client();

        public void ProcessRequest(HttpContext context)
        {
            if (context.Request.Files.Count > 0)
            {
                var _file = context.Request.Files[0];
                Stream _stream = _file.InputStream;

                _client.GetFile(_stream);

                context.Response.Write("");
            }
        }

        public bool IsReusable
        {
            get
            {
                return false;
            }
        }
    }


Then we'll move to the file upload. There are many JQery plugins available for file upload so I decided to use one of them, besides implementing a new one. you can download the plugin I used from following link,
http://www.phpletter.com/Our-Projects/AjaxFileUpload/

File upload code will be something like following code block (Notice that "url" in ajax function "$.ajaxFileUpload" is the name of HttpHandler) ,


<div>
        <input id="fileToUpload" type="file" size="45" name="fileToUpload" class="input">
        <button id="buttonUpload" onclick="return ajaxFileUpload();">
            Upload</button>
    </div>



<script type="text/javascript">

        function ajaxFileUpload() {

            $.ajaxFileUpload
            (
            {
                url: 'AjaxFileUploadHandler.ashx',
                secureuri: false,
                fileElementId: 'fileToUpload',
                dataType: 'json',
                success: function (data, status) {
                    if (typeof (dataerror) != 'undefined') {
                        if (data.error != '') {
                            alert(data.error);
                        } else {
                            alert(data.msg);}}
                },
                error: function (data, status, e) {
                    alert(e);
                }
            })

            return false;
        }

    </script>


note that you have to add the file upload plugin to the web site and add a reference in the "aspx" file.

now all the hard work is done. Following code blocks shows theOperationContract and its implementation in the WCF service,


[ServiceContract]
    public interface IService1
    {
        [OperationContract]
        void GetFile(Stream fileStream);



public class Service1 : IService1
    {
        public void GetFile(Stream fileStream)
        {
            StreamReader _reader = new StreamReader(fileStream);
            string _content = _reader.ReadToEnd();
        }


We are done. Enjoy..!!

Sunday, July 15, 2012

Access WCF service from JQuery and get a JSON typed object

I recently wanted to access wcf service from client side, so I browse through internet and found the following article extremely useful.
http://www.codeproject.com/Articles/132809/Calling-WCF-Services-using-jQuery

I have followed the steps listed in the article and the solution functioned well in IE but not in firefox because of a cross domain issue. However I was able to overcome that issue. This blog post will include all steps  to create a solution which calls a wcf service from client side and gets a JSON typed object, works in any browser.


First create a basic WCF Service Application,


Set "AspNetCompatibilityRequirementsMode" to "Allowed" in Service1.svc.cs,




[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    public class Service1 : IService1
    {


Add a method named 'GetUser' which returns a String array to the "IService1" interface. Set "WebInvoke" attributed to given values as in the following code block,


[ServiceContract]
    public interface IService1
    {

        [OperationContract]
        [WebInvoke(Method = "POST",
         BodyStyle = WebMessageBodyStyle.Wrapped,
         ResponseFormat = WebMessageFormat.Json)]
        string[] GetUser(string Id);



Add a public class named "User" and insert a method to return a string array of users according to the Id as following,



public class User
    {

        Dictionary<int, string> users = null;
        public User()
        {
            users = new Dictionary<int, string>();
            users.Add(1, "pranay");
            users.Add(2, "Krunal");
            users.Add(3, "Aditya");
            users.Add(4, "Samir");
        }

        public string[] GetUser(int Id)
        {
            var user = from u in users
                       where u.Key == Id
                       select u.Value;

            return user.ToArray<string>();
        }

    }



Implement the "GetUser" method in the Service1.svc.cs to return a User according to ID as following,



[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    public class Service1 : IService1
    {
        public string[] GetUser(string Id)
        {
            return new User().GetUser(Convert.ToInt32(Id));
        }



Now we have to edit the configuration file. First add following "ServiceBehavior" and "EndBehavior" under behaviors,


<behaviors>
   <serviceBehaviors>
    <behavior name="ServiceBehavior">
     <serviceMetadata httpGetEnabled="true"/>
     <serviceDebug includeExceptionDetailInFaults="true"/>
    </behavior>
   </serviceBehaviors>
   <endpointBehaviors>
    <behavior name="EndBehavior">
     <webHttp/>
    </behavior>
   </endpointBehaviors>
  </behaviors>


then add following "service" and "endpoint" under Service,



<services>
   <service behaviorConfiguration="ServiceBehavior" name="Service1">
    <endpoint address="" binding="webHttpBinding" 
        contract="IService1" behaviorConfiguration="EndBehavior"/>
   </service>
  </services>



Edited entire web.config will be something like following,



<?xml version="1.0"?>
<configuration>

  <system.web>
    <compilation debug="true" targetFramework="4.0" />
  </system.web>
  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior name="ServiceBehavior">
          <serviceMetadata httpGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="false"/>
        </behavior>
      </serviceBehaviors>
      <endpointBehaviors>
        <behavior name="EndpBehavior">
          <webHttp/>
        </behavior>
      </endpointBehaviors>
    </behaviors>
    <services>
      <service behaviorConfiguration="ServiceBehavior" name="WcfServiceDan.Service1">
        <endpoint address="" binding="webHttpBinding"
            contract="WcfServiceDan.IService1" behaviorConfiguration="EndpBehavior"/>
      </service>
    </services>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
  </system.webServer>

</configuration>


WCF service is ready to go. Now add following JQuery code block to your client application,


<script type="text/javascript">

        function WCFJSON() {

            $.ajax({
                type: "POST", //GET or POST or PUT or DELETE verb
                url: "http://localhost:58055/Service1.svc/GetUser", // Location of the hosted service
                crossDomain: true,
                data: '{"Id": "3"}',
                contentType: "application/json; charset=utf-8", // content type sent to server
                dataType: "json", //Expected data format from server
                processdata: true, //True or False
                success: function (msg) {//On Successfull service call
                    alert(msg.GetUserResult[0]);
                },
                error: function (msg) {//On Successfull service call
                    console.log(msg);
                }
            });
        }

        $(document).ready(
         function () {
             WCFJSON();
         }
         );

    </script>


Now application will be working in IE but not in Mozilla since the cross domain issue. Add "Global.asax" file to the WCF service and insert following code block under the "Application_BeginRequest" method to overcome the issue,


protected void Application_BeginRequest(object sender, EventArgs e)
        {
            HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");

            if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
            {

                HttpContext.Current.Response.AddHeader("Cache-Control", "no-cache");

                HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST");

                HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");

                HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");

                HttpContext.Current.Response.End();

            }
        }


If you followed the steps correctly, you will get the following alert as the output,


Enjoy..!!

Wednesday, January 4, 2012

Writing a SOAP request programmatically in C# to call WCF web service.

I recently asked to write a SOAP request programmatically in C# to call a WCF Web service. It's pretty straight forward. I wrote it using the HttpWebRequest object which is available in .Net. You just have to pass the xml string and provide some properties to the HttpWebRequest object. Following is the code I used...



Tuesday, November 8, 2011

ASP.NET server control properties behavior...

Hi all this is my first blog in the web. So please excuse me for any drawbacks.

I recently requested to do some server controls. So I read MSDN and go head with coding. Everything was working fine as described in MSDN but I encountered a problem when I deal with properties of the control. Here what I initially did..

I created some public properties and I tried to use the values of them in the




[CreateChildControls] method.


Property localisation
Then only I realized that Public properties are not assigned in the [CreateChildControls] method. So I shifted the code to [OnLoad] method and then the control is working fine. Following is the code I implemented. Hope it will helpfull.
















[OnLoad] method








Hope this is useful....