Kwaliteit code
De code gebruikt standaarden die gebruikelijk zijn een C#, bijvoorbeeld globale objecten. Omdat programmes en courses hetzelfde zijn binnen de OU database (alleen met een andere type), heb ik een globaal object gemaakt, namelijk ProductService. Deze kan ik bij courses en programmes gebruiken om alle producten op te halen die ik nodig heb. Ik kan bijvoorbeeld ProductService.GetProducts(query, 4) doen, en dan krijg ik de informatie die ik nodig heb. Dit wordt ook gebruikt bij de database.
Dit betekent dat ik dus dit kan doen:
ListResponse<CourseDto> listResponse = await _productService.GetProducts<CourseDto>(0, query);
En dan kan ik de ListResponse meteen terug geven. Voor de programmes gaat dit bijna precies hetzelfde:
ListResponse<ProgrammeDto> listResponse = await _productService.GetProducts<ProgrammeDto>(4, query);
ListResponse is een speciaal object gemaakt voor de OOAPI. De OOAPI verwacht de payload:
{
"pageSize": number,
"pageNumber": number,
"hasPreviousPage": boolean,
"hasNextPage": boolean,
"totalPages": number,
"items": Array (object),
"ext": any
}
En ListResponse ziet er zo uit:
public class ListResponse<T>
{
public ListResponse() { }
[JsonPropertyName("pageSize")]
public int PageSize { get; set; }
[JsonPropertyName("pageNumber")]
public int PageNumber { get; set; }
[JsonPropertyName("hasPreviousPage")]
public bool HasPreviousPage { get; set; }
[JsonPropertyName("hasNextPage")]
public bool HasNextPage { get; set; }
[JsonPropertyName("totalPages")]
public int TotalPages { get; set; }
[JsonPropertyName("items")]
public IEnumerable<T> Items { get; set; }
[JsonPropertyName("ext")]
public object Ext { get; set; }
}
Dit geeft dan precies terug wat de OOAPI verwacht.
Ook de code zelf kan snel hergebruikt worden. Ik houd een strict structuur aan per endpoint die gemakkelijk veranderd kan worden als dat nodig is. Dit is bijvoorbeeld de organisations function:
[OpenApiOperation(
operationId: "GetOrganisations",
tags: ["OOAPI"],
Visibility = OpenApiVisibilityType.Important,
Description = "Get a list of organisations.")]
[OpenApiParameter(
name: "pageSize",
In = ParameterLocation.Query,
Required = false,
Type = typeof(PageSize))]
[OpenApiParameter(
name: "pageNumber",
In = ParameterLocation.Query,
Required = false,
Type = typeof(int))]
[OpenApiParameter(
name: "primaryCode",
In = ParameterLocation.Query,
Required = false,
Type = typeof(int))]
[OpenApiResponseWithBody(
HttpStatusCode.OK,
"application/json",
typeof(ListResponse<OrganisationDto>))]
[Function("GetOrganisations")]
[Authorize("Reader")]
public async Task<HttpResponseData> GetOrganisations(
[HttpTrigger(AuthorizationLevel.Function, "get", Route = "organisations")]
HttpRequestData req)
{
_logger.LogInformation("C# HTTP trigger function processed a request.");
try
{
...
}
catch (Exception e)
{
_logger.LogError(
$"C# HTTPTriggered GetOrganisations executed "
+ e.Message
);
return req.CreateResponse(HttpStatusCode.InternalServerError);
}
}
Als een nieuw endpoint aangemaakt moet worden, kan al deze code makkelijk veranderd worden. Dit zorgt er ook voor dat er automatisch een swagger wordt aangemaakt in verband met documentatie. Hierdoor blijft documentatie en de code altijd gelijk.
Via [Authorize("Reader")] kun je er voor zorgen dat het endpoint gevalideerd moet worden. Binnen de haakjes kun je aangeven welke rol er nodig is om bij dit endpoint te komen. Je kunt maar 1 rol doorgeven.
Door try te gebruiken vang het errors op, en geeft het ook een foutcode terug.