How to Configure Openapirequestbody in Azure Function?
I Want to Decorate My Azure C# Function with Openapi Annotations. the Function Accept Json Schema as Parameters. How to Mention That in the Annotation. Want to...
I want to decorate my azure c# function with OpenApi annotations. The function accept JSON schema as parameters. How to mention that in the annotation.
Want to know how to configure below annotation
[OpenApiRequestBody(contentType: "json", bodyType: typeof(System.Text.Json.JsonDocument), Description = "Parameters",Example =typeof(Parameters))]
public class ModifyOrder
{
[FunctionName("ModifyOrder")]
[OpenApiOperation(operationId: "run", tags: new[] { "Modify Order" })]
[OpenApiSecurity("function_key", SecuritySchemeType.ApiKey, Name = "code", In = OpenApiSecurityLocationType.Query)]
[OpenApiRequestBody(contentType: "json", bodyType: typeof(System.Text.Json.JsonDocument), Description = "Parameters",Example =typeof(Parameters))]
[OpenApiResponseWithBody(statusCode: HttpStatusCode.OK, contentType: "text/plain", bodyType: typeof(string), Description = "The OK response")]
public static async Task<IActionResult> run(
[HttpTrigger(AuthorizationLevel.Function, "put", Route = null )] HttpRequest req,
ILogger log)
{
log.LogInformation($"C# HTTP trigger function processed a request.");
string ordernumber;
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
dynamic data = JsonConvert.DeserializeObject(requestBody);
ordernumber = data?.orderno;
string responseMessage = $"Order:{ordernumber}";
return new OkObjectResult(responseMessage);
}
}
[OpenApiExample(typeof(Parameters))]
public class Parameters
{
/// <summary>The id of the customer in the context. This is also called payer, sub_account_id.</summary>
[Newtonsoft.Json.JsonProperty("customerId", Required = Newtonsoft.Json.Required.Always)]
[System.ComponentModel.DataAnnotations.Required(AllowEmptyStrings = true)]
public string CustomerId { get; set; }
/// <summary>The order number. Used to uniquely identify a group of order lines.</summary>
[Newtonsoft.Json.JsonProperty("orderNumber", Required = Newtonsoft.Json.Required.Always)]
[System.ComponentModel.DataAnnotations.Required(AllowEmptyStrings = true)]
public string OrderNumber { get; set; }
}
1 Answer
The main parameter of OpenApiRequestBody to focus on in your example is bodyType. Parameter Example can be omitted here and configured in a different way (explained later on). Instead of using JsonDocument rather use your Parameters class for the bodyType - this will then expose the characteristics of the Parameters class in the Swagger definition.
You can't use the Parameters class itself to represent a valid example and should instead create a dedicated class that inherits OpenApiExample<T> or in your case OpenApiExample<Parameters> then within this class override the Build method to construct your example instance of Parameters. You can then expose your example by decorating the Parameters class with the attribute [OpenApiExample<T>] (as you've done, but using an example class type!).
A couple of things worth noting about OpenApiRequestBody and this library more generally- the Description property of OpenApiRequestBody doesn't currently work as intended; the description text isn't rendered out in the Swagger requestBody definition. This leads on to my next point which is to note that (at the time of writing) this library - Microsoft.Azure.WebJobs.Extensions.OpenApi - is in a pre-release state (0.7.2) and accordingly does seem to contain some bugs, as I've discovered myself.
I've amended your ModifyOrder class below; this version I hope will help with answering your questions!
public static class ModifyOrder
{
[FunctionName("ModifyOrder")]
[OpenApiOperation(operationId: "run", tags: new[] { "Modify Order" })]
[OpenApiSecurity("function_key", SecuritySchemeType.ApiKey, Name = "code", In = OpenApiSecurityLocationType.Query)]
[OpenApiRequestBody(contentType: "application/json", bodyType: typeof(Parameters), Description = "Parameters", Required = true)]
[OpenApiResponseWithBody(statusCode: HttpStatusCode.OK, contentType: "text/plain", bodyType: typeof(string), Description = "The OK response")]
public static async Task<IActionResult> run(
[HttpTrigger(AuthorizationLevel.Function, "PUT", Route = null)] HttpRequest req,
ILogger log)
{
log.LogInformation($"C# HTTP trigger function processed a request.");
string ordernumber;
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
dynamic data = JsonConvert.DeserializeObject(requestBody);
ordernumber = data?.orderno;
string responseMessage = $"Order:{ordernumber}";
return new OkObjectResult(responseMessage);
}
}
[OpenApiExample(typeof(ParametersExample))]
public class Parameters
{
/// <summary>The id of the customer in the context. This is also called payer, sub_account_id.</summary>
[OpenApiPropertyDescription("The id of the customer in the context. This is also called payer, sub_account_id.")]
[Newtonsoft.Json.JsonProperty("customerId", Required = Newtonsoft.Json.Required.Always)]
[System.ComponentModel.DataAnnotations.Required(AllowEmptyStrings = true)]
public string CustomerId { get; set; }
/// <summary>The order number. Used to uniquely identify a group of order lines.</summary>
[OpenApiPropertyDescription("The order number. Used to uniquely identify a group of order lines.")]
[Newtonsoft.Json.JsonProperty("orderNumber", Required = Newtonsoft.Json.Required.Always)]
[System.ComponentModel.DataAnnotations.Required(AllowEmptyStrings = true)]
public string OrderNumber { get; set; }
}
public class ParametersExample : OpenApiExample<Parameters>
{
public override IOpenApiExample<Parameters> Build(NamingStrategy namingStrategy = null)
{
this.Examples.Add(
OpenApiExampleResolver.Resolve(
"ParametersExample",
new Parameters()
{
CustomerId = "CUST12345",
OrderNumber = "ORD001"
},
namingStrategy
));
return this;
}
}