/// <inheritdoc /> public void Apply(ApiOperationDescriptor descriptor) { var docs = descriptor.OperationType.GetXmlDocsElement(); if (docs == null) { return; } var exceptionElements = docs.Elements("exception"); foreach (var e in exceptionElements) { // The exception type is stored as T:[full name]. Strip the first two characters. var exceptionTypeText = e.Attribute("cref").Value.Substring(2); var exceptionType = Type.GetType(exceptionTypeText); if (exceptionType == null) { throw new InvalidOperationException( $"Could not find type {exceptionTypeText} as described by an exception tag in documentation for the operation {descriptor.OperationType.FullName}."); } var status = e.Attribute("status") == null?ToHttpStatus(exceptionType) : int.Parse(e.Attribute("status").Value); var description = e.Value; descriptor.AddResponse(new ResponseDescriptor( exceptionType, status, description, e.Attributes().ToDictionary(a => a.Name.LocalName, a => a.Value))); } }
private static void RegisterResponses(ApiOperationDescriptor descriptor) { var typedOperation = descriptor.OperationType .GetInterfaces() .SingleOrDefault(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IReturn <>)); if (typedOperation != null) { descriptor.AddResponse( new ResponseDescriptor(typedOperation.GetGenericArguments()[0], 200, "OK")); } descriptor.AddResponse( new ResponseDescriptor(typeof(UnhandledExceptionOperationResult), 500, "Unexpected error")); descriptor.AddResponse( new ResponseDescriptor(typeof(ValidationFailedOperationResult), 422, "Validation failure")); }
private static void RegisterResponses(ApiOperationDescriptor descriptor) { var typedOperation = descriptor.OperationType .GetInterfaces() .SingleOrDefault(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IReturn <>)); if (typedOperation != null) { var returnType = typedOperation.GetGenericArguments()[0]; // If we have a StatusCodeResult then we either // 1. Have a specific subclass and therefore know the expected response code and can therefore add a response // 2. Have the base class and therefore can not determine the actual expected response code so leave it open and do not add anything specific if (typeof(StatusCodeResult).IsAssignableFrom(returnType)) { var instanceProperty = returnType.GetField("Instance", BindingFlags.Public | BindingFlags.Static); if (instanceProperty != null) { // This is option 1, we have a specific subclass (see the .tt file that generates these, i.e. StatusCodeResult.Created) var statusCode = ((StatusCodeResult)instanceProperty.GetValue(null)).StatusCode; descriptor.AddResponse( new ResponseDescriptor((int)statusCode, statusCode.ToString())); } } else { descriptor.AddResponse( new ResponseDescriptor(returnType, (int)HttpStatusCode.OK, HttpStatusCode.OK.ToString())); } } descriptor.AddResponse( new ResponseDescriptor(typeof(UnhandledExceptionOperationResult), 500, "Unexpected error")); descriptor.AddResponse( new ResponseDescriptor(typeof(ValidationFailedOperationResult), 422, "Validation failure")); }
/// <inheritdoc /> public void Apply(ApiOperationDescriptor descriptor) { var staticFields = descriptor.OperationType.GetFields(BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public); foreach (var f in staticFields) { if (f.FieldType != typeof(ApiExceptionFactory)) { continue; } if (f.GetValue(null) is ApiExceptionFactory factory) { descriptor.AddResponse(new ResponseDescriptor( typeof(ApiException), factory.HttpStatus, factory.Title, new Dictionary <string, string> { ["type"] = factory.Type, })); } } }