public void Apply(ActionModel action) { Produces(action); if (action.Is(HttpMethod.Get)) { if (action.ActionName.Equals(Constants.GetById, StringComparison.OrdinalIgnoreCase)) { // invalid id: action.ProducesResponseType <ProblemDetails>(StatusCodes.Status400BadRequest); // resource not found: action.ProducesResponseType <ProblemDetails>(StatusCodes.Status404NotFound); if (action.Controller.ControllerType.IsGenericType && action.Controller.ControllerType.AsType().ImplementsGeneric(typeof(ResourceController <>))) { var controllerType = action.Controller.ControllerType.GetGenericArguments()[0]; // get resource by ID with return=representation: action.ProducesResponseType(controllerType, StatusCodes.Status200OK); } } if (action.ActionName.Equals(Constants.Get, StringComparison.OrdinalIgnoreCase) || action.ActionName.Equals(Constants.GetEmbedded, StringComparison.OrdinalIgnoreCase)) { if (action.Controller.ControllerType.IsGenericType && action.Controller.ControllerType.AsType().ImplementsGeneric(typeof(ResourceController <>))) { var controllerType = action.Controller.ControllerType.GetGenericArguments()[0]; // FIXME: @nextLink, @deltaLink, should be present, too var collectionType = typeof(Many <>).MakeGenericType(controllerType); // get resource collection with return=representation: action.ProducesResponseType(collectionType, StatusCodes.Status200OK); // get resource collection specifying a $top operator larger than the server maximum action.ProducesResponseType <ProblemDetails>(StatusCodes.Status413PayloadTooLarge); } } if (action.ActionName.Equals(Constants.GetNextPage, StringComparison.OrdinalIgnoreCase)) { if (action.Controller.ControllerType.IsGenericType && action.Controller.ControllerType.AsType().ImplementsGeneric(typeof(ResourceController <>))) { var controllerType = action.Controller.ControllerType.GetGenericArguments()[0]; // FIXME: @nextLink, @deltaLink, should be present, too var collectionType = typeof(Many <>).MakeGenericType(controllerType); // get resource collection with return=representation: action.ProducesResponseType(collectionType, StatusCodes.Status200OK); } } if (!action.HasAttribute <DoNotHttpCacheAttribute>()) { action.ProducesResponseType(StatusCodes.Status304NotModified); } } if (action.Is(HttpMethod.Post)) { Consumes(action); if (action.ActionName.Equals(Constants.Create, StringComparison.OrdinalIgnoreCase)) { // created resource with return=minimal: action.ProducesResponseType(StatusCodes.Status201Created); // tried to create a resource that already exists, and the supplied resource was equivalent: action.ProducesResponseType <ProblemDetails>(StatusCodes.Status303SeeOther); // client followed a redirect via 303 See Other, and retrieved the cacheable resource action.ProducesResponseType(StatusCodes.Status200OK); // invalid body // tried to create a resource that already exists, and the supplied resource was not equivalent action.ProducesResponseType <ProblemDetails>(StatusCodes.Status400BadRequest); // server failed to save resource: action.ProducesResponseType <ProblemDetails>(StatusCodes.Status500InternalServerError); } if (!action.HasAttribute <DoNotHttpCacheAttribute>()) { action.ProducesResponseType(StatusCodes.Status412PreconditionFailed); } } if (action.Is(HttpMethod.Put)) { Consumes(action); // updated resource with return=minimal: action.ProducesResponseType(StatusCodes.Status204NoContent); // successful update operation: action.ProducesResponseType(StatusCodes.Status200OK); } if (action.Is(HttpMethod.Patch)) { // successful patch operation: if (action.Controller.ControllerType.IsGenericType && action.Controller.ControllerType.AsType().ImplementsGeneric(typeof(ResourceController <>))) { var controllerType = action.Controller.ControllerType.GetGenericArguments()[0]; // patched resource by ID with return=representation: action.ProducesResponseType(controllerType, StatusCodes.Status200OK); } // patched resource by ID with return=minimal: action.ProducesResponseType(StatusCodes.Status204NoContent); // resource not found: action.ProducesResponseType <ProblemDetails>(StatusCodes.Status404NotFound); // invalid patch operation (tried to modify a read-only field, etc.): action.ProducesResponseType <ProblemDetails>(StatusCodes.Status400BadRequest); switch (_options.Value.ApiFormats) { case ApiSupportedMediaTypes.None: throw new NotSupportedException(_localizer.GetString("API must support at least one content format")); case ApiSupportedMediaTypes.ApplicationJson | ApiSupportedMediaTypes.ApplicationXml: action.Consumes(ApiMediaTypeNames.Application.JsonMergePatch, ApiMediaTypeNames.Application.XmlMergePatch, ApiMediaTypeNames.Application.JsonPatchJson, ApiMediaTypeNames.Application.JsonPatchXml); break; case ApiSupportedMediaTypes.ApplicationJson: action.Consumes(ApiMediaTypeNames.Application.JsonMergePatch, ApiMediaTypeNames.Application.JsonPatchJson); break; case ApiSupportedMediaTypes.ApplicationXml: action.Consumes(ApiMediaTypeNames.Application.XmlMergePatch, ApiMediaTypeNames.Application.JsonPatchXml); break; default: throw new ArgumentOutOfRangeException(); } } if (action.Is(HttpMethod.Delete)) { if (action.ActionName.Equals(Constants.DeleteById, StringComparison.OrdinalIgnoreCase)) { // deleted resource with return=minimal: action.ProducesResponseType(StatusCodes.Status204NoContent); // invalid id: action.ProducesResponseType <ProblemDetails>(StatusCodes.Status400BadRequest); // resource not found: action.ProducesResponseType <ProblemDetails>(StatusCodes.Status404NotFound); // resource already deleted: action.ProducesResponseType <ProblemDetails>(StatusCodes.Status410Gone); // server failed to delete resource: action.ProducesResponseType <ProblemDetails>(StatusCodes.Status500InternalServerError); if (action.Controller.ControllerType.IsGenericType && action.Controller.ControllerType.AsType().ImplementsGeneric(typeof(ResourceController <>))) { var controllerType = action.Controller.ControllerType.GetGenericArguments()[0]; // deleted resource by ID with return=representation: action.ProducesResponseType(controllerType, StatusCodes.Status200OK); } } if (!action.HasAttribute <DoNotHttpCacheAttribute>()) { action.ProducesResponseType(StatusCodes.Status412PreconditionFailed); } } foreach (var parameter in action.Parameters) { Apply(parameter); } }