in src/Microsoft.OpenApi.CSharpAnnotations.DocumentGeneration/OperationFilters/ResponseToResponseFilter.cs [39:210]
public IList<GenerationError> Apply(
OpenApiOperation operation,
XElement element,
OperationFilterSettings settings)
{
var generationErrors = new List<GenerationError>();
try
{
var responseElements = element.Elements()
.Where(
p => p.Name == KnownXmlStrings.Response ||
p.Name == KnownXmlStrings.ResponseType);
var generationContext = settings.GenerationContext;
foreach (var responseElement in responseElements)
{
var code = responseElement.Attribute(KnownXmlStrings.Code)?.Value;
if (string.IsNullOrWhiteSpace(code))
{
// Most APIs only document responses for a successful operation, so if code is not specified,
// we will assume it is for a successful operation. This also allows us to comply with OpenAPI spec:
// The Responses Object MUST contain at least one response code,
// and it SHOULD be the response for a successful operation call.
code = "200";
}
var mediaType = responseElement.Attribute(KnownXmlStrings.Type)?.Value ?? "application/json";
var description = responseElement.GetDescriptionTextFromLastTextNode();
var allListedTypes = responseElement.GetListedTypes();
var crefKey = allListedTypes.ToCrefKey();
OpenApiSchema schema = null;
if (generationContext.CrefToSchemaMap.ContainsKey(crefKey))
{
var schemaInfo = generationContext.CrefToSchemaMap[crefKey];
if (schemaInfo.Error != null)
{
generationErrors.Add(schemaInfo.Error);
return generationErrors;
}
schema = new OpenApiSchema();
schemaInfo.Schema.CopyInto(schema);
}
var examples = responseElement.ToOpenApiExamples(
generationContext.CrefToFieldValueMap,
generationErrors);
var headers = responseElement.ToOpenApiHeaders(generationContext.CrefToSchemaMap, generationErrors);
var schemaReferenceDefaultVariant = generationContext
.VariantSchemaReferenceMap[DocumentVariantInfo.Default];
if (schema != null)
{
if (examples.Count > 0)
{
var firstExample = examples.First().Value?.Value;
if (firstExample != null)
{
if (schema.Reference != null)
{
if (schemaReferenceDefaultVariant.ContainsKey(schema.Reference.Id))
{
schemaReferenceDefaultVariant[schema.Reference.Id].Example = firstExample;
}
}
else
{
schema.Example = firstExample;
}
}
}
}
if (operation.Responses.ContainsKey(code))
{
if (string.IsNullOrWhiteSpace(operation.Responses[code].Description))
{
operation.Responses[code].Description = description.RemoveBlankLines();
}
if (schema != null)
{
if (!operation.Responses[code].Content.ContainsKey(mediaType))
{
operation.Responses[code].Content[mediaType] = new OpenApiMediaType
{
Schema = schema
};
}
else
{
// If the existing schema is just a single schema (not a list of AnyOf), then
// we create a new schema and add that schema to AnyOf to allow us to add
// more schemas to it later.
if (!operation.Responses[code].Content[mediaType].Schema.AnyOf.Any())
{
var existingSchema = operation.Responses[code].Content[mediaType].Schema;
var newSchema = new OpenApiSchema();
newSchema.AnyOf.Add(existingSchema);
operation.Responses[code].Content[mediaType].Schema = newSchema;
}
operation.Responses[code].Content[mediaType].Schema.AnyOf.Add(schema);
}
}
}
else
{
var response = new OpenApiResponse
{
Description = description.RemoveBlankLines(),
};
if (schema != null)
{
response.Content[mediaType] = new OpenApiMediaType { Schema = schema };
}
if (headers != null && headers.Any())
{
response.Headers = headers;
}
operation.Responses.Add(code, response);
}
if (examples.Count > 0)
{
if (operation.Responses[code].Content[mediaType].Examples.Any())
{
examples.CopyInto(operation.Responses[code].Content[mediaType].Examples);
}
else
{
operation.Responses[code].Content[mediaType].Examples = examples;
}
}
}
if (!operation.Responses.Any())
{
operation.Responses.Add(
"default",
new OpenApiResponse { Description = "Responses cannot be located for this operation." });
}
}
catch(Exception ex)
{
generationErrors.Add(
new GenerationError
{
Message = ex.Message,
ExceptionType = ex.GetType().Name
});
}
return generationErrors;
}