none
Design Question: Global Data Object to return API responses to callers RRS feed

  • Question

  • I inherited a single tier of WCF services that use various different methods to returning data to the caller from a boolean to indicate success/failure to status codes enumeration. There is a need to create a common, reusable object that contains the API specific response (e.g. data to display, flag to indicate update was successful, etc.) with a generic response object that provides transparency into the caller's request. The generic response object would allow the API to return information, validation, exception, etc. messages with the high majority being error-based. For example, the caller (internal front end system) would know that the data does not exist and would be able to display it to the screen rather including any specific details rather than just guessing why the data is null.

    The initial implementation uses dependency injection to create the API-specific response interface and the idea is to combine responses from the various methods that are executed during the work flow. For example, if the request is to retrieve some data, the API might call 3-5 methods including other services (NOTE: I inherited this...) that ALL might have responses that need to be returned. The goal is to 'combine' the responses back into the API-specific response and back to the call. And, here where I am having some second guessing as to finalizing the design.

    1) Should the API-specific response interface inherit from the common response object's interface? Currently, the API-specific response inherits from the common response NOT at the interface level.

    2) The majority of the methods are shared for the various APIs and I don't see any easy way to have them return common response information back. These shared methods could create a local instance of the common response so it can be returned back but you can't create an interface directly. You could create the interface from the underlying instantiated object? But, that seems funny.

    Friday, October 25, 2019 1:24 PM

Answers

All replies

  • I fundamentally disagree that you should be using a generic response object for different data. Types are there to make it easier to write correct code. Using a generic response completely defeats that purpose. As an example HTTP uses a standard response object (e.g. HttpResponseMessage) yet if you look at almost every place somebody uses it they immediately convert it to the actual type they want. This is undo work just to have a "generic" object.

    Each method should return the exact data expected by that method, for WCF. The only thing you might want to do is have all the objects return data that is shared amongst them (e.g. error message like you mentioned) in a consistent format. For errors themselves just use FaultException. That is what it is designed for. However if you wanted to return additional information like validation warnings or whatnot then you have 2 approaches. The first approach is good old OOP, use a base class.

    public class CommonData
    {
       //Common stuff goes here
    }
    
    public class Method1Data : CommonData
    {
       //Method1 specific stuff
    }
    
    public class Method2Data : CommonData
    {
       //Method2 specific stuff
    }

    This works well if the common data is actually part of the data being calculated and not metadata or auto-generated after the underlying "method" work is done (e.g. validation).

    The alternative approach is to use a wrapper class.

    public class CommonData<T>
    {
       //Common stuff goes here

    public T Data { get; set; } } CommonData<Method1Data> Method1 () ... CommonData<Method2Data> Method2 () ...
    The advantage of this approach is that you can wrap any data, not just those that are aware of the common data. This is great for extending existing data with new information. For example paging metadata can be added without impacting the underlying data. This also works with more types as there is no issue with the common data conflicting (in name) with the core data. If a caller doesn't care about the common data then it just works with the core data.


    Michael Taylor http://www.michaeltaylorp3.net

    Friday, October 25, 2019 1:46 PM
  • I fundamentally disagree that you should be using a generic response object for different data. Types are there to make it easier to write correct code. Using a generic response completely defeats that purpose. As an example HTTP uses a standard response object (e.g. HttpResponseMessage) yet if you look at almost every place somebody uses it they immediately convert it to the actual type they want. This is undo work just to have a "generic" object.

    Each method should return the exact data expected by that method, for WCF. The only thing you might want to do is have all the objects return data that is shared amongst them (e.g. error message like you mentioned) in a consistent format. For errors themselves just use FaultException. That is what it is designed for. However if you wanted to return additional information like validation warnings or whatnot then you have 2 approaches. The first approach is good old OOP, use a base class.

    public class CommonData
    {
       //Common stuff goes here
    }
    
    public class Method1Data : CommonData
    {
       //Method1 specific stuff
    }
    
    public class Method2Data : CommonData
    {
       //Method2 specific stuff
    }

    This works well if the common data is actually part of the data being calculated and not metadata or auto-generated after the underlying "method" work is done (e.g. validation).

    The alternative approach is to use a wrapper class.

    public class CommonData<T>
    {
       //Common stuff goes here

    public T Data { get; set; } } CommonData<Method1Data> Method1 () ... CommonData<Method2Data> Method2 () ...
    The advantage of this approach is that you can wrap any data, not just those that are aware of the common data. This is great for extending existing data with new information. For example paging metadata can be added without impacting the underlying data. This also works with more types as there is no issue with the common data conflicting (in name) with the core data. If a caller doesn't care about the common data then it just works with the core data.


    Michael Taylor http://www.michaeltaylorp3.net

    The application framework has a common message system with various enums that is used for troubleshooting. This is common across the APIs so it makes sense to have a common/generic structure to return this data.

    Friday, October 25, 2019 2:21 PM
  • Hi SAgosto,

    Thank you for posting here.

    Since this thread is not related to C#, I don't suggest that you post it here. Therefore, I will move it to  where is forum for forum to redirect it to the correct forum.

    The Visual C# forum discusses and asks questions about the C# programming language, IDE, libraries, samples, and tools.

    Best regards,
    Timon


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.


    Monday, October 28, 2019 8:58 AM
  • Monday, October 28, 2019 10:34 AM
    Moderator
  • Also try asking for help over here.

    https://social.msdn.microsoft.com/Forums/vstudio/en-US/home?forum=wcf

     

     



    Regards, Dave Patrick ....
    Microsoft Certified Professional
    Microsoft MVP [Windows Server] Datacenter Management

    Disclaimer: This posting is provided "AS IS" with no warranties or guarantees, and confers no rights.

    Tuesday, October 29, 2019 1:13 PM
    Moderator