Link to home
Start Free TrialLog in
Avatar of muratkazanova
muratkazanova

asked on

How to pass complex object as a parameter to WCF Rest from Windows form application.

Hi;
I would like to pass a basic Employee class to WCF Rest service  via POST method. I've ALREADY achieved this by using the WCF REST Starter Kit's HTTPClient and Extension libraries.

My service script is:
<%@ServiceHost language="C#" Debug="true" Service="restfirst.first" Factory="System.ServiceModel.Activation.WebServiceHostFactory" %>

The class i would like pass is:

namespace UtilityClasses
{   
   
    [DataContract]
    public class Employee
    {
        [DataMember]
        public int Id { get; set; }
        [DataMember]
        public string Name { get; set; }

        public static List<Employee> getEmployeeList()
        {
            var xdoc = XDocument.Load(HttpContext.Current.Server.MapPath("~/Employee/Employee.xml"));
            return (from e in xdoc.Descendants("Employee")
                    select new Employee
                    {
                        Id = Convert.ToInt32(e.Element("Id").Value),
                        Name = e.Element("Name").Value
                    }).ToList<Employee>();
        }

        public static string addNew(int Id, string Name)
        {
            string returnValue = string.Empty;
            try
            {
                var xdoc = XDocument.Load(HttpContext.Current.Server.MapPath("~/Employee/Employee.xml"));
                xdoc.Root.Add(new XElement("Employee",
                      new XElement("Id", Id),
                      new XElement("Name", Name)
                      ));

                xdoc.Save(HttpContext.Current.Server.MapPath("~/Employee/Employee.xml"));
                returnValue = "Done!";
            }
            catch (Exception ex)
            {
                returnValue = ex.Message.ToString();
            }
            return returnValue;
        }
    }
}

Open in new window


My interface looks like this:

[ServiceContract]    
    public interface Ifirst
    {
        [OperationContract]
        [WebGet(UriTemplate = "Employee/{Id}")]
        List<Employee> getEmployeesById(string Id);

        [WebInvoke(UriTemplate = "Employee/Add")]
        Employee addNew(Employee emp);

        [WebInvoke(UriTemplate = "Employee/AddOld",BodyStyle=WebMessageBodyStyle.WrappedRequest, RequestFormat=WebMessageFormat.Xml)]
        string addNewOld(Stream Id);

        [WebInvoke(Method="POST", UriTemplate = "Employee/AddEntityOld",BodyStyle=WebMessageBodyStyle.Bare, RequestFormat=WebMessageFormat.Xml)]
        string addNewEntityOld(Stream emp);

Open in new window


Implementation is:

[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    public class first : Ifirst
    {

         public List<Employee> getEmployeesById(string Id)
         {
             int id = Convert.ToInt32(Id);
             var emplist = Employee.getEmployeeList();

             var filtered = (from e in emplist
                             where e.Id == id
                             select e).ToList<Employee>();

             return filtered;
         }

         public Employee addNew(Employee emp)
         {
             
             Employee returnValue = null;
             try
             {

                 string result =   Employee.addNew(emp.Id, emp.Name);
                 if (result.StartsWith("Done"))
                     returnValue = emp;
                
             }
             catch (Exception ex)
             {                
                 returnValue = null;
             }
             return returnValue;
         }

         public string addNewOld(Stream id)
         {
             string returnValue = string.Empty;
             StreamReader sr = new StreamReader(id);
             string res = sr.ReadToEnd();
             return res;
             System.Collections.Specialized.NameValueCollection coll = HttpUtility.ParseQueryString(res);
             return string.Format("{0} {1}", coll["Id"], "");
             

         }

         public string addNewEntityOld(Stream emp)
         {
             try
             {
                 XmlSerializer xs = new XmlSerializer(typeof(Employee));
                 Employee e = (Employee)xs.Deserialize(emp);
                 return string.Format("{0} {1}", e.Id, e.Name);
             }
             catch (Exception ex)
             {
                 return ex.Message.ToString();
             }
             
         }
    }

Open in new window


and here is the my web config's wcf section:
	<system.serviceModel>
    
		<behaviors>
			<serviceBehaviors>        
				<behavior>
					<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
					<serviceMetadata httpGetEnabled="true"/>
          
					<!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
					<serviceDebug includeExceptionDetailInFaults="true"/>
				</behavior>
			</serviceBehaviors>
		</behaviors>
    
		<serviceHostingEnvironment aspNetCompatibilityEnabled="True" multipleSiteBindingsEnabled="true"/>
   
	</system.serviceModel>

Open in new window


Ok, so if make the call from windows form button click action as its listed below the current implementation for AddEntityOld work fine with Stream work fine:

string endPoint = "http://localhost:1212/first.svc/Employee/AddEntityOld";
            var request = (HttpWebRequest)WebRequest.Create(endPoint);

            var populatedEndPoint = new Employee() { Id = 99, Name = "Still testing..." };

            XmlSerializer xs = new XmlSerializer(populatedEndPoint.GetType());
            MemoryStream ms = new MemoryStream();

            xs.Serialize(ms, populatedEndPoint);


            byte[] bytes = ms.ToArray();
            
            request.Method = "POST";
            request.ContentType = "test/xml";

            request.ContentLength = bytes.Length;
            
            var requestStream = request.GetRequestStream();

            requestStream.Write(bytes, 0, bytes.Length);
            requestStream.Close();

            using (var responsex = (HttpWebResponse)request.GetResponse())
            {
                string s = new System.IO.StreamReader(responsex.GetResponseStream()).ReadToEnd();
                MessageBox.Show(s);
                if (responsex.StatusCode != HttpStatusCode.OK)
                {
                    string message = String.Format("POST failed. Received HTTP {0}", responsex.StatusCode);
                    throw new ApplicationException(message);
                }
            }

Open in new window


FINALLY, what i'm trying to achieve here is, passing Employee emp as a parameter to AddEntityOld method instead of using Stream emp as a parameter and its implementation recieve the passed Employee object's properties with WebRequest Call.

[WebInvoke(Method = "POST", UriTemplate = "Employee/AddEntityOld2", BodyStyle = WebMessageBodyStyle.Bare, RequestFormat = WebMessageFormat.Xml)]
        string addNewEntityOld(Employee emp);

Open in new window


Thank you for your help in advance
Avatar of muratkazanova
muratkazanova

ASKER

Anyone?
In my recent attempt i used DataContractSerializer but still getting 400 Bad Request from server

string endPoint = "http://localhost:1212/first.svc/Employee/AddEntityOld";
            var request = (HttpWebRequest)WebRequest.Create(endPoint);

            var populatedEndPoint = new Employee() { Id = 99, Name = "Still testing..." };
            
            DataContractSerializer ser = new DataContractSerializer(typeof(Employee));
            MemoryStream ms = new MemoryStream();
            ser.WriteObject(ms, emp);

            request.Method = "POST";
            request.ContentType = "application/x-www-form-urlencoded";
            //request.ContentType = "test/html";

            request.ContentLength = ms.Length;
            
            var requestStream = request.GetRequestStream();

            requestStream.Write(ms.ToArray(), 0, (int)ms.Length);
            requestStream.Close();

            using (var responsex = (HttpWebResponse)request.GetResponse())
            {
                
                string s = new System.IO.StreamReader(responsex.GetResponseStream()).ReadToEnd();
                MessageBox.Show(s);
                if (responsex.StatusCode != HttpStatusCode.OK)
                {
                    string message = String.Format("POST failed. Received HTTP {0}", responsex.StatusCode);
                    throw new ApplicationException(message);
                }
            }

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of muratkazanova
muratkazanova

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial