DEV Community

Omo Agbagbara
Omo Agbagbara

Posted on

Logic App Http Connector with Swagger + C# Function App

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; }
    }
}
Enter fullscreen mode Exit fullscreen mode

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};        
   }
Enter fullscreen mode Exit fullscreen mode

Logic App Configuration.

The swagger definition for the function app can be used in the logic app as follows

  1. Add a http connector and choose the HTTP + swagger option.
    Image description

  2. This selection allows a swagger endpoint to be configured.
    Image description

  3. In this scenario, the swagger definition used can be obtained from the function app OpenApi Document UI.
    Image description

  4. Enter the url into the endpoint box.
    Image description

  5. This will provide a list of all the possible operations which are available in the swagger definition. For this scenario, the "Create Shipping Notice" is selected.
    Image description

  6. The UX now allows the required parameters to be configured.
    Image description

  7. Configured Payload.
    Image description

Top comments (0)