Search code examples
c#.netdtocomposition

How can I ensure a generic payload in a .Net API Dto?


I have a DTO for creating a client organisation.

public record clientDto(string legalname, string name, string country, australianClientData payload);

public record australianClientData(int abn);

These attributes in australianClientData are specific to Australian organisations. Organisations from other countries will have their own specific attributes.

How do I ensure that payload is of a type that allows different child types (i.e. usaClientData, chinaClientData)?

Failed attempt #1 - Use a base class

I have already tried making australianClientData inherit from a base class parentPayload. The problem with this is that my Controller assumed the payload was of base class (empty) so it ignored it entirely.

Failed attempt #2 - Use a generic class

@stuartd Here is what I've come up with.

    public record clientDto(string legalname, string name, string country);
    public record clientDto<TCountry>(string legalname, string name, string country, TCountry? payload) where TCountry : parentPayload;

    public abstract record parentPayload();
    public record payloadAustraliaClientData(int abn, string aciclabel, string acicofficecode) : parentPayload;
[HttpPost]
        public clientDto Post([FromBody] clientDto clientObject)
        {
            return clientObject;
        }

Problem is that I'm having difficulty returning the correct type from my API. I understand that clientDto<TCountry> is different from clientDto (and my data can be either), but my API accepts and returns clientDto. I am inexperienced enough in C# that I don't know how to expect or return the appropriate type.


Solution

  • An alternative is to use optional properties:

    public record clientData(int? abn, int? ssn);
    

    Then have the API implicitly figure out the underlying DTO. You could also strongly type the request via an enum:

    public record clientData(ClientType type, int? abn, int? ssn);
    

    This way the API knows which properties to pluck and fail the request when they are missing.