Link to home
Start Free TrialLog in
Avatar of Derekhenderson
Derekhenderson

asked on

WCF ... Passing in Custom Objects

I have 2 WCF Services into which I wish to pass a dataobject (the same dataobject).

for examples if I have an object with two properties ; say X (int) and Y (string)

on client side i have

myDataObject objX = new myDataObject();
objX.X = 10
objX.Y = "Hello"

I want to pass this to two seperate WCF Services like :-

myService1 svc1 = new myService1();
myService2 svc2 = new myService2();

svc1.SomeMethod(objX)
svc2.OtherMethod(objX)

if i set up data contracts on the service side i keep getting cannot convert type objX to SVC.DataContract etc etc
even if the data contract matches my local object.

Can this be done ?
any help would be greatly appreciated.

Services :- DataContract class
 
using System;
using System.Data;
using System.ServiceModel;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.Xml.Serialization;
 
[DataContract(Name = "myDataObject")]
public class myDataObject
{
    public int intX;
    public string strX;
}
 
 
 
Service 1 Class
 
 
using System;
using System.ServiceModel;
 
 
[ServiceContract()]
public interface IDataService1
{
    [OperationContract]
    string MyOperation1(myDataObject objX);
}
 
public class DataService1 : IDataService1
{
    public string MyOperation1(myDataObject objX)
    {
        return "Service 1";
    }
}
 
 
Service 2 Class
 
 
using System;
using System.ServiceModel;
 
 
[ServiceContract()]
public interface IDataService2
{
	[OperationContract]
    string MyOperation1(myDataObject objX);
}
 
public class DataService2 : IDataService2
{
    public string MyOperation1(myDataObject objX)
	{
        return "Service 2";
    }
}
 
 
Client Side
 
DataObject class
 
    [DataContract(Name = "myDatCont")]
    [Serializable]
    public class myDataObject
    {
        [DataMember]
        public int Parameter1;
        [DataMember]
        public string Parameter2;
    }
 
 
running the services
 
            myDataObject dat1 = new myDataObject();
            svc1.DataService1Client service1 = new myWeb.svc1.DataService1Client();
            svc2.DataService2Client service2 = new myWeb.svc2.DataService2Client();
 
            TextBox3.Text = service1.MyOperation1(dat1);
            TextBox4.Text = service2.MyOperation1(dat1);
 
 
Error received at compile :-
 
Argument '1': cannot convert from 'myWeb.myDataObject' to 'myWeb.svc1.myDataObject'
 
 
This works (but its not what I want because it requires two seperate data objects):-
 
            svc1.DataService1Client service1 = new myWeb.svc1.DataService1Client();
            svc1.myDataObject dat1 = new myWeb.svc1.myDataObject();
            svc2.DataService2Client service2 = new myWeb.svc2.DataService2Client();
            svc2.myDataObject dat2 = new myWeb.svc2.myDataObject();
 
            TextBox3.Text = service1.MyOperation1(dat1);
            TextBox4.Text = service2.MyOperation1(dat2);

Open in new window

Avatar of p_davis
p_davis

if you want the object to be the exact same instance then pass by ref. now about the
message "cannot convert type objX to SVC.DataContract" you will have to cast the object as that datacontract type to be able to use it

(SVC.DataContract)objX
Avatar of Derekhenderson

ASKER

even using by ref I still get the compile error

using the cast you suggest ...

   myDataObject dat1 = new myDataObject();  // define on client machine as class:
    service1.MyOperation1((svc1.myDataObject)dat1)
    service2.MyOperation1((svc2.myDataObject)dat1)

Cannot convert type 'myDataObject' to 'svc1.myDataObject'
Cannot convert type 'myDataObject' to 'svc2.myDataObject'

why do you have the client side with a myDataObjectClass when you have that on the service side as well?

actually i guess it wouldn't matter but it doesn't appear that either of your datacontracts are doing anything. i believe that you need to setup your datamemebers with gets and sets.
Even when the datacontracts are done using gets and set as in

    [DataContract]
    [Serializable]
    public class myDataObject
    {
        private int param1;
        private string param2;

        [DataMember]
        public int Parameter1
        {
            get { return param1; }
            set { param1 = value; }
        }

        [DataMember]
        public string Parameter2
        {
            get { return param2; }
            set { param2 = value; }
        }
      
    }

i get exactly the same error.

Cannot convert type 'myDataObject' to 'svc1.myDataObject'
Cannot convert type 'myDataObject' to 'svc2.myDataObject'
what if, on your service you set the parameter to just be of type Object and then if you need to actually use the object (which i am assuming you do) try casting it after the service receives it to the dataobject that you need.
also, the ref suggestion was just if you wanted to work with one instance of the object and not copies.-- not as a solution to your errors.
As an object it compiles but now I get :

service is defined as

public class DataService1 : IDataService1
{
    public string MyOperation1(object objX)
    {
        myDataObject dat1 = (myDataObject)objX;   // dataobject defined service side
        return dat1.Parameter2;
    }
}

client side

            svc1.DataService1Client service1 = new myWeb.svc1.DataService1Client();

            myDataObject dat1 = new myDataObject();   // myDataObject defined client side
            dat1.Parameter2 = "Hello";

            TextBox3.Text = service1.MyOperation1(dat1);   // line causes error


{"Type 'myDataObject' with data contract name 'myDataObject' is not expected. Add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer."}
try casting dat1 as an object as well when passing in as a parameter.
As far as I can workout (and i could be wrong)... The only thing we've acheived now is to move the error from compile time ... to run time.  It appears to still have the same issue, in that it can't match a local object to a remote one.  

Am I really trying something that no one else has ever wanted to do, surely in OO programming someone will have wanted to pass an object to a number of web services!!!!

we use wcf and datacontracts for winforms here and when we want to create an object of that datacontract schema we insantiate the services datacontract type. not usually creating one on the client side to send back of the clients type.

what did it do at runtime, specifically?
it gave me the runtime error :

{"Type 'myDataObject' with data contract name 'myDataObject' is not expected. Add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer."}

Even if I insantiate the service datacontract, it works for that service but I then have no way of passing the object to another service, for the same reason it states the datacontracts cannot be converted.

Prehaps if I explain my thought process ... you may tell me I'm an idiot and should be doing it a different way.  I have an object ... lets say an purchase order object.  Lets say I have a number of WCF services, one that calculates total VAT, one that calculates total postage, and one that saves the Order to the database. I will need to pass the same populated object to each of the 3 services at different points of time. But each service should receive the same set of data. Thats the kind of thing I want to do, only not with purchase orders.
i would never call you an idiot.-- the documentation on this stuff is weak at best.
i would still say to have one datacontract on your service side and pass that by reference after instantiating on the client side. that way you are only working with one datacontract 'type' and one instance of it.

--does that make sense?
ASKER CERTIFIED SOLUTION
Avatar of alaran
alaran
Flag of Norway image

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
SOLUTION
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
Of course... if you donæt neen any of the more "generic" ways of converting one to the other, you could alway make a function like the one below, which will be a bit more effective. But then again since you're doing this on the client side, resource usage shouldn't be much of a problem, and if you have these needs for several contracts it's kind of boring to have to code a converter method for each of them...

 
Namespace1.MyClass1 mc1 = new Namespace1.MyClass1();
mc1.X = 100;
mc1.Y = 200;
Namespace2.MyClass1 mc2 = Convert(mc1);
 
public method Namespace2.MyClass1 Convert(Namespace1.MyClass1 in)
{
    Namespace2.MyClass1 out = new Namespace2.MyClass1();
    out.X = in.X;
    out.Y = in.Y;
    return out;
}

Open in new window