Skip to content

Annotation

Stanislav Molchanovskiy edited this page Nov 15, 2021 · 2 revisions

The interfaces of clients and controllers can be annotated with attributes to describe endpoints and add additional functionality. The following attributes can be used:

Base attributes

The HttpFacade attribute is an equivalent of the ApiControllerAttribute from ASP.NET Core.

[HttpFacade] public interface IMyController { ... }

The base URL route for API can be set by the PathAttribute.

[Path("api")] public interface IMyClient { ... }

A client interface can be annotated with optional the FacadeAttribute if no other NClient attributes are used in the client interface. It can be useful for improving code readability or for detecting client interfaces if it does not have any other NClient attribute.

[Facade] public interface IMyClient { ... }

HTTP methods

Each interface method must have an HTTP attribute that defines the HTTP method for request. There are seven types of such attributes: GetMethodAttribute, HeadMethodAttribute, PostMethodAttribute, PutMethodAttribute, PatchMethodAttribute, DeleteMethodAttribute, OptionsMethodAttribute.

public interface IMyClient { [GetMethod] Entity[] Get(); }

Optionally, you can specify a relative path by passing it to the constructor:

public interface IMyClient { [GetMethod("entities")] Entity[] Get(); }

HTTP parameters

By default, custom type parameters are passed in the request body and primitive type parameters are passed in a URL query. You can explicitly specify how to pass a parameter using attributes: QueryParamAttribute, BodyParamAttribute, HeaderParamAttribute, RouteParamAttribute.

public interface IMyClient { [PostMethod] void Post([QueryParam] Entity entity); }

It is also possible to change a parameter name:

public interface IMyClient { [PostMethod] void Post([QueryParam(Name = "myEntity")] Entity entity); }

Properties

In addition to its main purpose, the QueryParamAttribute allows you to change a property name of a custom object that is passed in URL query:

public class Entity { [QueryParam(Name = "id")] public int Id }

The same effect will occur if you use the FromQueryAttribute from ASP.NET Core. But in this case you will have a dependency on ASP.NET, which is probably unwanted for client assemblies.

The names of the properties of custom objects that are passed in the request body can be changed using the JsonPropertyNameAttribute:

public class Entity { [JsonPropertyName("id")] public int Id }

Static HTTP headers

Use the HeaderAttribute attribute to add a static header. Static headers can be added for all methods:

[Header(Name: "Common-Header", Value: "value")] public interface IMyClient { ... }

or for a specific method:

public interface IMyClient { [GetMethod, Header("Specific-Method-Header", Value: "value")] Entity[] Get(); }

Override

The interface methods can be overridden in the inheriting interfaces. Although this is not an override in the usual sense, because you can change the return type of the method:

public interface IMyController { [GetMethod] Task<int> GetAsync([RouteParam] long id); }
public interface IMyClient : IMyController { [Override] new Task<string> GetFileAsync(long id); }

Overridden methods inherit all method and parameters attributes from the method of the inherited interface. If necessary, you can replace the attributes or add new ones. It is worth noting that multiple inheritance is forbidden if you want to override the method.

Authorization

ASP.NET has two methods for configuring authentication: AuthorizeAttribute and AllowAnonymousAttribute attributes. There are two equivalents in the client: AuthorizedAttribute and AnonymousAttribute.

Response type

The ResponseAttribute is optional attribute that specifies the type of the value and status code returned by the method. This is the equivalent of the ProducesResponseTypeAttribute.

public interface IMyClient { [GetMethod, Response(typeof(Entity[]), HttpStatusCode.OK)] Entity[] Get(); }

Versioning

There are two attributes for API versioning: VersionAttribute and ToVersionAttribute. They are the equivalents of ApiVersionAttribute and MapToApiVersionAttribute from ASP.NET (see ASP.NET API Versioning). They are needed only for controllers and therefore will be ignored when generating the client. Here is an example of their use for the controller interface:

[Version("1.0"), Version("2.0"), Path("api/v{version:apiVersion}")]
public interface IMyController 
{
    [GetMethod] Entity[] Get(int id);                      // Available in versions 1.0 and 2.0
    [DeleteMethod, ToVersion("2.0")] void Delete(int id);  // Available in version 2.0
}

For the client, there is the UseVersionAttribute. You can add it to set the API version for a client:

[UseVersion("1.0"), Path("api/v{version:apiVersion}")]
public interface IMyClient
{ 
    [GetMethod] Entity[] Get(int id);                       // Uses version 1.0
    [DeleteMethod, UseVersion("2.0")] void Delete(int id);  // Uses version 2.0
}

The UseVersionAttribute can be used together with the attributes for API versioning, for example:

[UseVersion("1.0")] public interface IMyClient : IMyController { } 

Clone this wiki locally