The EntitySpaces Community

Share and learn about the EntitySpaces Architecture.
Welcome to The EntitySpaces Community Sign in | Join | Help
in
Home Forums Photos

WCF Client Problem (Missing Copy Constructor?)

Last post 02-19-2008, 7:36 AM by msyoung. 9 replies.
Sort Posts: Previous Next
  •  12-17-2007, 2:55 PM 7233

    WCF Client Problem (Missing Copy Constructor?)

    I am testing ES with WCF and tried to follow the example per this blog:

    http://www.entityspaces.net/blog/2007/11/10/EntitySpacesPureWCFClientSideProxies.aspx

     If you scroll down to the example involving a simulation between client and server, there are lines similar to these:

    Employees employee = new Employees();
    if (employee.LoadByPrimaryKey(employeeId)) {
       
    Client.EmployeesProxyStub stub = new Client.EmployeesProxyStub( <<<<< I CAN'T PASS IN employee per the example!!  <<<<

    In my generated client output, there are no constructors with parameters, so...

    Is there a change I need to know about?

    Is something not working for my client generated classes?

    In other words, how do I fill the client proxy? Also, there are no examples for a collection. I assume I would need to fill a List<EmployeeProxyStub>. How would I do that too?

    TIA

  •  12-17-2007, 3:09 PM 7234 in reply to 7233

    Re: WCF Client Problem (Missing Copy Constructor?)

    btw: I would really like the client proxy/stub implementations to inherit from interfaces.

     For example IEmployee

    Where the interface declares all the same properties as the client proxy/stub implementation, then the copy constructors could take an interface as a parameter versus the implementation and this way a server-side object, or a client-side object, or any that implments the inetrface could be supplied. Further, it eases testing and allows for interaction with business logic where clutter can be removed (I.e all the extra stuff on the server-side objects are unecessary for most business logc as well.)

    NOTE: I already have a great deal of business logic that take interfaces as paremeters and most already match the database tables and the above would be really helful.

    Also, I am assuming that I could implement more intricate interfaces (those that do not match table names and simultaneaouly declare all properties of the table) by implementing them manually on the custom generated classes???

    For example, many, many classes implement IGLTransaction. I certainly want to use one common method and not have to declare a method for each implementation.

    Sorry, if this turned into multiple issues :)

     

  •  12-17-2007, 3:19 PM 7235 in reply to 7234

    Re: WCF Client Problem (Missing Copy Constructor?)

    Okay, on the first post if you look at the sample code in the post

     

    Notice that I am using the "Server" stub, generated by the "Generated Master" template (see the proxy/stub tab). The server stub classes will be in the generated file as is all of your other classes. That is the one that takes the Employee object in the constructor then you then deserialize it on the Client, the "client" proxy stubs can't know about the real entities or you would need those assemblies on the client. I hope this helps, if not, follow up with another post ...

     Also, regarding interfaces, yes, we agree, we realize the importance of this. Not only should our entities implement the interface, but even the proxy/stubs too. Finally, this could be very useful for folks who want to do mock testing.
     

     

     


    EntitySpaces | Twitter | BLOG | Please honor our Software License
  •  12-17-2007, 3:55 PM 7237 in reply to 7235

    Re: WCF Client Problem (Missing Copy Constructor?)

    No, I didn't notice the server-side proxy, but now I am wondering... are you expecting the service to share a string after manually serializing the objects(s) rather than the object?

    Understand my view: For me, WCF requires interface declaration for each "contract" like this:

        [ServiceContract(

           Namespace = "http://NSurePro.WcfLibrary",

           CallbackContract = typeof(IServiceCallback),

           SessionMode = SessionMode.Required)]

        public interface INSureProService {

     

                  [OperationContract(

                         IsOneWay = true,

                         IsInitiating = false,

                         Action = "http://NSurePro.WcfLibrary/GetEmployeeById")]

                  void GetEmployeeById(Guid requestId, int employeeId);

     

        }

     

     

        [ServiceContract(

            Namespace = "http://NSurePro.WcfLibrary",

            SessionMode = SessionMode.Required)]

        public interface IServiceCallback {

     

                  [NetDataContract]

                  [OperationContract(IsOneWay = true, Action = "http://NSurePro.WcfLibrary/SendEmployee")]

                  void SendEmployee(Guid requestId, Client.EmployeesProxyStub employee);

     

        }

    I prefer asynchronous communication and use dual bindings (send and forget a request, send and forget responses). So, My Client side app would call the first service contract method which would be proxied over to WCF via this method:

    void GetEmployeeById(Guid requestId, int employeeId);

    The client is registered with WCF after logging in to receive callbacks and thus the second contract shows the method to return an employee instance via the registered callback:

    void SendEmployee(Guid requestId, Client.EmployeesProxyStub employee);

     

    Thus, I expect pseudo code like this for WCF on the server-side within the GetEmployeeById method:

    I need to send the client stub because the client has no knowledge about the server stub. So, the client stub needs an IEmployee copy constructor to do that.

    If I am understanding and I use the method shown in the console sample, I would have to manually serialize the server proxy stub and send a string rather than an object to the client. Then I would have to manually deserialize the object on the client. Normally, I would expect WCF to serialize objects on its own. urther, I am not sure how big a string can be; there might be issues with that; especially with large collections.

    Before I write anymore, am I making any sense to you? Am I missing something?

  •  12-17-2007, 4:00 PM 7238 in reply to 7237

    Re: WCF Client Problem (Missing Copy Constructor?)

    Hmmm... twice my pseudo code was cut from post. Hopefully it will show up here:

     

    /// check security-authorization and if approved:
    Employees employee = new Employees();
    if (employee.LoadByPrimaryKey(employeeId)) {
        Client.
    EmployeesProxyStub stub = new EmployeesProxyStub(employee);
        callback.SendEmployee(stub);
    }

  •  12-17-2007, 6:04 PM 7241 in reply to 7238

    Re: WCF Client Problem (Missing Copy Constructor?)

    Yes, currently the transport is a string, however, it is well defined xml of course. What I should have done was put this code:

     

    Code:
    EmployeesProxyStub proxy = new EmployeesProxyStub(emp);

    XmlSerializer sf = new XmlSerializer(typeof(EmployeesProxyStub));
    StringWriter sw = new StringWriter();
    sf.Serialize(sw, proxy);

    return sw.ToString();

    in the ToString() method like this:

     

    Code:
    [XmlType(TypeName="EmployeesCollectionProxyStub")]	
    [Serializable]
    public partial class EmployeesCollectionProxyStub : esEntityCollectionProxyStub
    {
    public override string ToString()
    {
    XmlSerializer sf = new XmlSerializer(typeof(EmployeesCollectionProxyStub));
    StringWriter sw = new StringWriter();
    sf.Serialize(sw, this);
    return sw.ToString();
    }

    // more ....
    }

     

    Then the code would be as sample as ... (pardon the webmethod)

     

    Code:
    [WebMethod]
    public string GetEmployee(int i)
    {
    Employees emp = new Employees();
    if (emp.LoadByPrimaryKey(i))
    {
    EmployeesProxyStub proxy = new EmployeesProxyStub(emp);
    return proxy.ToString();
    }
    else
    return null
    ;
    }

    I cannot simulate what I need to to try it in an WCF app, I don't have one created right now. But you could try sending and receiving the client side proxy, but you would have to put something like this in your Server side collection proxy to implicitly cast it into the client side proxy:

     

    Code:
    public static implicit operator Client.EmployeesCollectionProxyStub(Server.EmployeesCollectionProxyStub coll)
    {
    // using our new string operator
    string s = coll.ToString();

    XmlSerializer xs = new XmlSerializer(typeof(Client.EmployeesCollectionProxyStub));
    StringReader sr = new StringReader(s);

    Client.EmployeesCollectionProxyStub ps = xs.Deserialize(sr) as Client.EmployeesCollectionProxyStub;
    return ps;
    }

    Then (pardon the webmethod) the get would look like this:

     

    Code:
    [WebMethod]
    public Client.EmployeesProxyStub GetEmployee(int i)
    {
    Employees emp = new Employees();
    if (emp.LoadByPrimaryKey(i))
    {
    return new Server.EmployeesProxyStub(emp);
    }
    else
    return null
    ;
    }



    Given your ealier statement in another thread that stated you should choose an architecture based on what it currently supports I'll risk this statement Stick out tongue

    This is an area that really interests me. I would like to make sure EntitySpaces is the best in the industry in this area (in all area's really). So I am willing to work with you to make this easier. I think the above shows a progression on how we can easily take this to simple one liners, with no changes to the core either. I could just change the templates so that you can use the above syntax, but you would have to put those methods and your objects and test it first and make sure it works, or perhaps interfaces solves all of this? I'm open to your thoughts. 

     


    EntitySpaces | Twitter | BLOG | Please honor our Software License
  •  12-17-2007, 6:59 PM 7242 in reply to 7241

    Re: WCF Client Problem (Missing Copy Constructor?)

    First, I would prefer to reply to a client with a method like this:

        void SendEmployee(Guid requestId, Client.EmployeesProxyStub employee);

    versus this:

        void SendEmployee(Guid requestId, string employee);

    My reasons are somewhat complex. WCF has constraints for bindings such as maxBufferPoolSize, maxBufferSize, maxConnections, maxReceivedMessageSize, maxArrayLength, maxBytesPerRead, maxNameTableCharCount, maxStringContentLength, etc.

    These constraints have defaults that can severely restrict sending strings. So, I suspect many users would hit these limits and have no idea why the service is crashing. I, personally, think its better to feed in objects versus a string because of this. Also note: If IIS is used as a service host, it can further restrict these values. Within WCF, the MaxStringContentLength defaults to 8K to 128K depending on the binding. These constraints are put in place to discourage successful DoS (denial of service) attacks.

    So, its not just the lines of code, it is issues with default WCF values and the way the designers expect WCF to be used. In my case, I can override these values and I can use a string, so its not a show stopper and, of course - yes, fewer lines of code would always be better. However, in the long run, my suggestion would be something like this for the generated code:

    Imagine a simple class with a few properties as an example (psuedo code):

    public class CustomerProxyStub: ICustomer {

        public CustomerProxyStub();

        public CustomerProxyStub (ICustomer customer) {
            this._name = customer.Name;
            this._phone = customer.Phone;
            // etc etc the properties are copied
        }

        public string Name {
            get { return this._name; }
            set { this._name = value; }
        }
        // etc more properties
    }

    Also NOTE: my personal preference, would to to call the classes CustomerDTO rather than proxy stub, but hey:  tom(ay)to - to(mah)to (* maybe a place for me to override the naming logic?)

    This way there is no serialization in the code. You may or may not be aware, WCF is designed to transfer objects directly and expects either the Serializable attribute or the DataContract attribute to serialize/deserialize - ON ITS OWN (I know you are aware of the attributes). The advantage sending objects is that the WCF framework expects objects to be large and has much greater defaults for objects and collections, but WCF defaults to very small transfer sizes for a string value. Your customers that experiment with WCF would have fewer problems using objects than using a string (based on my experience of having WCF crash once I sent more than a few records and realizing its not intuitive to figure out why).

    Also, as you mentioned, interfaces are great for testing and for interacting with business object libraries - so its just handy anyway.

    If you are going to implement any the suggestions I made in one form or another (It seems like you are and I also expect it would take some time), then I am fine just having the client-side use the full server-side code and include the .dlls within the client until a later update. I use click-once deployment and its not that big a deal for me because I don't need a true web-service or soa exposure. For me, I control the client AND service and third parties, currently,  are not significantly involved.

    So, if you are going that direction, I have patience and would glad to provide feedback.

  •  12-18-2007, 9:12 AM 7253 in reply to 7242

    Re: WCF Client Problem (Missing Copy Constructor?)

    Let me do some investigation and re-read this thread in full. We are putting together the roadmap for ES2008 and WFC is very important to us, give me a day or so.

    EntitySpaces | Twitter | BLOG | Please honor our Software License
  •  12-19-2007, 12:58 PM 7277 in reply to 7253

    Re: WCF Client Problem (Missing Copy Constructor?)

    I'll be looking forward to your response, thanks for the consideration.
  •  02-19-2008, 7:36 AM 8135 in reply to 7277

    Re: WCF Client Problem (Missing Copy Constructor?)

    I am reading this thread and I agree with you that you need to return the proxy object in your wcf operations, not a string.  This is exactly what I am doing with the server proxy genererated with the "generated master" template.  (The generated proxy is really more of a dataContract, and perhaps it should be called as such.  Let WCF create the "proxy" thru the creation of a service reference.).  I think ES is confusing the issue with their "client side proxy" classes, and passing strings instead of objects is not the preferred method these days for WCF.  I have a WCF sample, in vs2008, that I can send to you if you like.
View as RSS news feed in XML