What are the ApiMember Best Practices?

What are the best practices for implementing the ApiMember tags? We’re building documentation off of them using T4 templates but we also have the Swagger API plugin installed and want to ensure the most ‘developer friendly API’ possible by providing as much information straight from our code to their eyes.

For instance, I have an AccountModel class (a DTO class inherits this to get the properties) so I set the following ApiMember tags on two of the properties:

#region IHaveAParentBaseModel<IAccountModel>
// Related Objects
[ApiMember(Name = "ParentID", IsRequired = false, DataType = "int?", ParameterType = "body", Description = "Parent Account ID, optional")]
public int? ParentID { get; set; }
[ApiMember(Name = "Parent", IsRequired = false, DataType = "AccountModel", ParameterType = "body", Description = "Parent Account information (read-only)")]
public AccountModel Parent { get; set; }
IAccountModel IHaveAParentBaseModel<IAccountModel>.Parent { get { return Parent; } set { Parent = (AccountModel)value; } }
// Associated Objects
[ApiMember(Name = "Children", IsRequired = false, DataType = "List<AccountModel>", ParameterType = "body", Description = "Child Account(s)")]
public List<AccountModel> Children { get; set; }
List<IAccountModel> IHaveAParentBaseModel<IAccountModel>.Children { get { return Children?.ToList<IAccountModel>(); } set { Children = value?.Cast<AccountModel>().ToList(); } }
#endregion

You can see that we’re setting almost every property and providing some information about availability and requirements to pass data in/out. A big question is what would be the best way to write out the DataType property? Consumers are primarily TypeScript (that’s what our front end is written in) so should i write ‘number?’ instead of ‘int?’? Should I write List, Array or AccountModel[]? Does it matter so long as the consumer gets the gist or does it actually affect Swagger and other API consumers?

Swagger Data Types are listed here but this only supports a limited set of data types and is otherwise primarily for documentation purposes.

For your TypeScript clients I’d recommend getting the typed TypeScript DTO’s from the Add TypeScript ServiceStack Reference feature which they can access from the following routes directly, e.g:

We’re using a service stack typescript code generator that a previous dev (no longer works here) found online somewhere and have just been improving upon it over time. It generates a single huge api and dto file for reference. For instance, the CreateAccount endpoint gets generated in TS like this:

/**
  * C# Type:  Clarity.Ecommerce.Framework.Accounts.CreateAccount
  * Path: /Account/Create
  * Verbs: POST
  * Summary:  Use to create a new account
*/
CreateAccount = (routeParams : CreateAccountDto) => {
    return this.$http<AccountModel>({
        url:  [this.rootUrl, "Account", "Create"].join('/'),
        method: 'POST',
        data:  routeParams
    });
}

and then we can use it like:
service.accounts.CreateAccount(<dtoContent>).success(result => doSomething(result));

That’s been very successful for us so far but we’re looking to new options with the Angular 2.0 upgrade later this year, we’ll keep that page you referenced in mind for then.

Thanks for the response mythz!

1 Like