Over the last couple of weeks, I have had to upgrade some function apps which were written about 6 years ago. These function apps were triggered by logic apps and in most cases, the original implementation invoked the function apps via http connectors.
It got me thinking about using http connectors but incorporating swagger definitions. Incorporating swagger definitions provide a better UX for integrating with function app.
To start off, the function app code has to be annotated with openApi attributes and for c# projects the nugget package must be added. The nugget package to use is Microsoft.Azure.Functions.Worker.Extensions.OpenApi":Version="1.5.1"
In the scenario been discussed, a shipping notice will be created. The shipping notice request will be defined by a ShippingNoticeDTO.
Define the ShippingNoticeDTO
namespace Deltastateonline.Dtos
{
public class ShippingNoticeDto
{
[Required]
public string ShipmentId { get; set; }
public DateTime ExpectedArrival { get; set; }
public List<ProductDto> Products { get; set; }
public string CarrierName { get; set; }
public string TrackingNumber { get; set; }
}
public class ProductDto
{
[Required]
public string ProductCode { get; set; }
public string Description { get; set; }
[Required]
public int Quantity { get; set; }
}
}
Implementation
The function code can then be annotated with the attributes as shown below.
[OpenApiOperation(operationId: "CreateShippingNotice", tags: new[] { "Shipping-Notice" }, Summary = "Create Shipping Notice", Description = "This creates a Shipping Notice.", Visibility = OpenApiVisibilityType.Important)]
[OpenApiParameter(name: "x-functions-key",In = ParameterLocation.Header,Required = true,Type = typeof(string),Summary = "function auth key",Description = "Auth key.")]
[OpenApiSecurity("function_key", SecuritySchemeType.ApiKey, Name = "code", In = OpenApiSecurityLocationType.Query)]
[OpenApiSecurity("x-functions-key", SecuritySchemeType.ApiKey, Name = "code", In = OpenApiSecurityLocationType.Header)]
[OpenApiRequestBody(contentType: "application/json", bodyType: typeof(ShippingNoticeDto), Description = "Shipping Notice Details", Required = true)]
[OpenApiResponseWithBody(statusCode: HttpStatusCode.OK, contentType: "application/json", bodyType: typeof(ResponseObj), CustomHeaderType =typeof(CustomResponseHeader),Summary = "Success", Description = "This returns the response")]
[OpenApiResponseWithoutBody(statusCode: HttpStatusCode.BadRequest, Description = "Bad Request")]
[OpenApiResponseWithoutBody(statusCode: HttpStatusCode.InternalServerError, Description = "Internal server error")]
[Function("ShippingNotice")]
public async Task<MultipleOutputs<ShippingNoticeDto>> RunAsync([HttpTrigger(AuthorizationLevel.Function, "post")] HttpRequestData req , FunctionContext context)
{
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
HttpResponseData response = req.CreateResponse();
ShippingNoticeDto inputRequest = null;
try
{
inputRequest = JsonConvert.DeserializeObject<ShippingNoticeDto>(requestBody)?? throw new ArgumentNullException(nameof(ShippingNoticeDto));
var validationResults = new List<ValidationResult>();
var validationContext = new ValidationContext(inputRequest, null, null);
bool isValid = Validator.TryValidateObject(inputRequest, validationContext, validationResults, true);
if (!isValid)
{
return new MultipleOutputs<ShippingNoticeDto>{ServiceBusMessage = null,HttpResponse = response};
}
}
catch (System.Exception ex)
{
response.StatusCode = HttpStatusCode.InternalServerError;
return new MultipleOutputs<ShippingNoticeDto>{ServiceBusMessage = null,HttpResponse = response};
}
response.StatusCode = HttpStatusCode.OK;
await response.WriteAsJsonAsync(new ResponseObj{Message = "Request Created" , correlationid = context.InvocationId});
return new MultipleOutputs<ShippingNoticeDto>{ServiceBusMessage = inputRequest,HttpResponse = response};
}
Logic App Configuration.
The swagger definition for the function app can be used in the logic app as follows
Top comments (0)