none
Composite Types with WCF Applications RRS feed

  • Question

  • I've got a WCF service with a composite type defined within iService.vb as:

        <OperationContract()> _
        Function MainRegistration(ByVal value As String, ByVal value2 As String, ByVal value3 As String, ByVal value4 As String, ByVal value5 As String, ByVal value8() As Byte, Optional ByVal value6 As String = "", Optional ByVal value7 As String = "") As ActivationResponse
    
        ' TODO: Add your service operations here
    
    End Interface
    
    <DataContract()> _
    Public Class ActivationResponse
    
        Private freeformTxt As String
        Private signatureByts() As Byte
    
        <DataMember()> _
        Public Property freeformText As String
            Get
                Return Me.freeformTxt
            End Get
            Set(value As String)
                Me.freeformTxt = value
            End Set
        End Property
        <DataMember()> _
        Public Property signatureBytes As Byte()
            Get
                Return Me.signatureByts
            End Get
            Set(value As Byte())
                Me.signatureByts = value
            End Set
        End Property
    End Class

    And I've got the composite type defined within the client application as:

    Public Class ActivationResponse
    
        Private freeformTxt As String
        Private signatureByts() As Byte
    
        Public Property freeformText As String
            Get
                Return Me.freeformTxt
            End Get
            Set(value As String)
                Me.freeformTxt = value
            End Set
        End Property
        Public Property signatureBytes As Byte()
            Get
                Return Me.signatureByts
            End Get
            Set(value As Byte())
                Me.signatureByts = value
            End Set
        End Property
    End Class

    I am getting a compile error (Value of type 'SBR2015.LicenseService.ActivationResponse' cannot be converted to 'SBR2015.ActivationResponse'.) - so seemingly the service composite type definition is not compatible with the client composite type definition. I have updated the service reference after publishing the website again. The service is running.

    Any help gratefully received.

    Thanks

    John


    Cheers, John


    • Edited by j_dublevay Monday, August 17, 2015 11:09 PM
    Monday, August 17, 2015 11:07 PM

All replies

  • I am getting a compile error (Value of type 'SBR2015.LicenseService.ActivationResponse' cannot be converted to 'SBR2015.ActivationResponse'.) - so seemingly the service composite type definition is not compatible with the client composite type definition. I have updated the service reference after publishing the website again.

    The problem is that an object cannot be cast across namespaces even if the object is the same object in both namespaces. SBR2015.LicenseService and SBR2015 are two different namespaces.

    .NET is not going to allow it.

    You create a classlib project in the solution call it Entities, you put the object in the Entities classlib project, and the object is only in one namespace called Entities.

    You set reference to the Entities project in both the WCF client project and WCF service project so that both projects know about the object in Entities. The object is the datacontract that is in the Entities project,  and the name of the object should be DTOSomething or SomethingDTO, because it is a DTO that is traveling between the WCF service process and the WCF client process. 

    https://en.wikipedia.org/wiki/Data_transfer_object

    You should get rid of the private backing variable for the public properties in the object and use auto properties, because VB.NET will take care of creating the private backing variable for the auto property. 

    https://msdn.microsoft.com/en-us/library/dd293589.aspx?f=255&MSPPError=-2147217396

    Tuesday, August 18, 2015 1:40 AM
  • Thanks for the advice. It makes perfect sense, and I have implemented it on the WCF client side. However, although I have added the Entities reference to the WCF service project, I do not seem able to utilise the object within the service code itself - i.e. Entities does not appear as a selectable object in Intellisense.

    I note, however, that the MSDN advice on DTOs suggests that it is no longer maintained. Is there a newer way of achieving this (I'm using VS2013).


    Cheers, John

    Tuesday, August 18, 2015 9:48 AM
  • I note, however, that the MSDN advice on DTOs suggests that it is no longer maintained. Is there a newer way of achieving this (I'm using VS2013).

    No that is not correct that DTO(s) are not being used and are being phased out. That is not happening.  It is at the developers digression to use a DTO or not to use one, just like it's a developer's choice not to use the salad bowl datasets and datatable, which are still widely being used.   The DTO is just a simple object a container that is being used widely throughout the industry to send data between two processes.  You make the DTO a datacontract so that it is serializable so it can travel between the WCF service and client.

    https://visualstudiogallery.msdn.microsoft.com/655aa6d4-4461-42ea-aeec-64cdb1313de7

    The only other way is to use XML and a XML document to transport the data between the WCF client and service. But that would mean you will need a lot of understanding of how to use XML. But on the other hand, when you serialize an object like you have your complex type or the DTO that is a datacontract, it is XML serialization being used to send the object that is turn back into a concrete object in code when it hits the client or service side code.

    Thanks for the advice. It makes perfect sense, and I have implemented it on the WCF client side. However, although I have added the Entities reference to the WCF service project, I do not seem able to utilise the object within the service code itself - i.e. Entities does not appear as a selectable object in Intellisense.

    Most likely the namespace/reference to the DTO is under may be jacked as to why you cannot see the DTO in the project that has reference to the Entities project. If you can see it in the client side code, you should be able to see the object in the service code too. You'll have to figure it out.

    Stick with the DTO man, because it is not going away,  and it is a viable solution widely being used in .NET solutions.

    Tuesday, August 18, 2015 3:31 PM
  • I note, however, that the MSDN advice on DTOs suggests that it is no longer maintained. Is there a newer way of achieving this (I'm using VS2013).

    No that is not correct that DTO(s) are not being used and are being phased out. That is not happening.  It is at the developers digression to use a DTO or not to use one, just like it's a developer's choice not to use the salad bowl datasets and datatable, which are still widely being used.   The DTO is just a simple object a container that is being used widely throughout the industry to send data between two processes.  You make the DTO a datacontract so that it is serializable so it can travel between the WCF service and client.

    https://visualstudiogallery.msdn.microsoft.com/655aa6d4-4461-42ea-aeec-64cdb1313de7

    The only other way is to use XML and a XML document to transport the data between the WCF client and service. But that would mean you will need a lot of understanding of how to use XML. But on the other hand, when you serialize an object like you have your complex type or the DTO that is a datacontract, it is XML serialization being used to send the object that is turn back into a concrete object in code when it hits the client or service side code.

    Thanks for the advice. It makes perfect sense, and I have implemented it on the WCF client side. However, although I have added the Entities reference to the WCF service project, I do not seem able to utilise the object within the service code itself - i.e. Entities does not appear as a selectable object in Intellisense.

    Most likely the namespace/reference to the DTO is under may be jacked as to why you cannot see the DTO in the project that has reference to the Entities project. If you can see it in the client side code, you should be able to see the object in the service code too. You'll have to figure it out.

    Stick with the DTO man, because it is not going away,  and it is a viable solution widely being used in .NET solutions.

    OK - thank you. I guess I am still not really understanding this DTO concept. I did exactly (I think) as you said, creating a new Entity class, and placing the Composite Type within it - removing the internal private backing variables.

    Public Class DTOActivationResponse
        Public Property freeformText As String
        Public Property signatureBytes As Byte()
    End Class

    You mentioned making the DTO a datacontract - but none of those keywords are available to me within the class. And the EntityToDTO add-in has confused me even more, as that seems to want some form of XML as the input.

    Sorry for the deluge of questions...


    Cheers, John

    Tuesday, August 18, 2015 5:33 PM
  • http://www.mindscapehq.com/documentation/lightspeed/Building-Distributed-Applications-/Building-WCF-Services-using-Data-Transfer-Objects

    There has to be a using statement in the DTO/class, and the Entities project must have reference to the System.Runtime.Serialization dll

    https://msdn.microsoft.com/en-us/library/system.runtime.serialization.datacontractattribute%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396

    Tuesday, August 18, 2015 7:17 PM
  • And also take note on this. The WCF client and service are two different processes, which is most likely both programs are setting on the same machine your development machine.

    But in the reality, the DTO(s) are traveling between client machine hosting the WCF client software and the hosting machine that is hosting the WCF service software. And the two machines are on a network. It can be a network like the Wide Area Network WAN/Internet or the network can a Local Area Network LAN like a p2p or a corporation's network.

    The DTO could be sent to the moon and back if two computers were in communications with each other one machine on the Earth, and other machine on the moon. :)  

    This is the purpose of WCF.

    https://en.wikipedia.org/wiki/Service-oriented_architecture

    http://www.codeproject.com/Articles/515253/Service-Oriented-Architecture-and-WCF
    Tuesday, August 18, 2015 7:38 PM
  • And also take note on this. The WCF client and service are two different processes, which is most likely both programs are setting on the same machine your development machine.

    Thanks - I understand the concept of WCF. The client is on my own development machine. The server process is running on my virtual web server with webhosts 1&1, probably in Germany. It's just that before hitting Composite Types, my main issue had been getting the X509 crypto working between the instances. Will check your other response re: the using statement.


    Cheers, John

    Tuesday, August 18, 2015 8:30 PM
  • I'm afraid I just couldn't grasp the DTO concept - a shame, as it probably should have been fairly simple. I searched a lot online for detailed help, but couldn't quite crack it. In the end, I have decided to send the server response back as pure binary data, with some length fields embedded to break it down. As you can probably deduce from my Composite Type definition, the vast majority of the return data is binary anyway.

    Thanks anyway for trying to help.


    Cheers, John

    Thursday, August 20, 2015 12:05 AM
  • I have used it countless times in N-tier applications and with WCF too to send DTO through the tiers. And seen it used countless times in solutions I only maintenance. 

    Presentation Layer project

    Business Logic Layer  project

    Data Access Layer project

    If WCF is involved the Service Layer project      ---   all projects ref  to Entities project

    WCF service

    and the BLL and DAL behind the WCF service

    I said using statement C# namespace reference,  but that should have been Imports for VB Serialization Runtime namespace.

    It's a simple thing to do.

    http://www.codeproject.com/Articles/474212/Zombie-Explorer-An-n-tier-application-from-top-to

    Thursday, August 20, 2015 12:56 AM
  • Understood - thanks. But I just got to the point where I needed to progress quickly with this software, and although I am a sucker for elegant ways of doing things (and thus your method is probably right up my street), I didn't have the time to sit and work it out when I could just revert to a pure binary response from the WCF server app (much of the example code was, as you say, C# - and whilst most times I can work a translation between the two - I fell short here). In the end, I have simply gone for:

    • <overall msg length> - 4 bytes
    • <freeform msg length> - 4 bytes
    • <freeform msg> - var bytes
    • <return data length> - 4 bytes
    • <return msg> - var bytes
    • <return sig length> - 4 bytes
    • <return sig> - var bytes

    I realise this is not quite as easy to modify in the future - but I am writing purely as a one-man band - this is just something I'm trying to release prior to a significant event in the related industry. When I have more time in the future (and when my wife is not badgering me to finish decorating the hall and my two year-old son is not vying for my attention), then I will have another go at the Entities/DTO method. I will list it down as a Technical Debt for now! ;-)

    Thanks again.

    John


    Cheers, John

    Thursday, August 20, 2015 10:40 PM
    • <overall msg length> - 4 bytes
    • <freeform msg length> - 4 bytes
    • <freeform msg> - var bytes
    • <return data length> - 4 bytes
    • <return msg> - var bytes
    • <return sig length> - 4 bytes
    • <return sig> - var bytes

    The next time you just send XML. It is XML is just string and WCF should have no problem. :)

    Friday, August 21, 2015 1:22 AM
  • Lol. Thanks for the 'suggestion'. To be honest, converting byte arrays into display hex/strings, putting them into an XML string, then unpacking them again in the client back into a byte array seems rather an unnecessary overhead to me for a proprietary solution. The majority of my data is byte() anyway, being data going to/coming from from RsaCryptoProvider - and XML just increases processing overhead and transmission data sizes. If I could have been bothered, then as much of my application already uses BER-TLV, then it would have made even more sense to make this response BER-TLV compliant - but again, it's just not necessary.

    Don't forget - there is more than one way to skin a cat! :)


    Cheers, John

    Friday, August 21, 2015 12:52 PM