Files
mixtape/zero.Api/Filters/ApiResponseFilter.cs
T

189 lines
5.7 KiB
C#
Raw Normal View History

using Microsoft.AspNetCore.Http;
2021-12-14 01:23:03 +01:00
using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.AspNetCore.Mvc;
2021-11-30 14:32:10 +01:00
using Microsoft.AspNetCore.Mvc.Filters;
namespace zero.Api.Filters;
public class ApiResponseFilterAttribute : ResultFilterAttribute
{
public override void OnResultExecuting(ResultExecutingContext context)
{
2021-12-13 16:11:52 +01:00
if (context.Result is ObjectResult result)
2021-11-30 14:32:10 +01:00
{
2021-12-14 01:23:03 +01:00
// format paged results
2021-12-13 16:11:52 +01:00
if (result.Value is Paged paged)
2021-11-30 14:32:10 +01:00
{
2021-12-14 01:23:03 +01:00
result.Value = new PagedDataApiResponse()
{
Success = true,
Status = result.StatusCode.Value,
2021-12-14 11:54:36 +01:00
Paging = new()
{
Page = paged.Page,
PageSize = paged.PageSize,
TotalPages = paged.TotalPages,
TotalItems = paged.TotalItems
},
2021-12-14 01:23:03 +01:00
Data = paged.GetItems()
};
2021-11-30 14:32:10 +01:00
}
2021-12-13 16:11:52 +01:00
2021-12-14 01:23:03 +01:00
// format patch results
2021-12-14 11:25:32 +01:00
else if (result.Value is Result model)
2021-11-30 14:32:10 +01:00
{
2021-12-14 01:23:03 +01:00
ApiResponse response = new DataApiResponse();
2021-12-13 16:11:52 +01:00
2021-12-14 01:23:03 +01:00
if (!model.IsSuccess)
{
response = new ErrorApiResponse()
{
Errors = model.Errors.Select(x => new ErrorApiResponseError()
{
Category = ApiErrorCodes.Categories.Validation,
Code = "// TODO",
Property = x.Property,
Message = x.Message
}).ToList()
2021-12-14 11:25:32 +01:00
};
2021-12-14 01:23:03 +01:00
}
else if (context.HttpContext.Items.TryGetValue(ApiConstants.ChangeToken, out object tokenObj) && tokenObj is string token)
{
2021-12-14 11:25:32 +01:00
response = new TokenizedDataApiResponse()
{
2021-12-14 01:23:03 +01:00
Data = model.GetModel(),
2021-12-14 11:25:32 +01:00
ChangeToken = token
2021-12-14 01:23:03 +01:00
};
}
else
{
response = new DataApiResponse()
{
Data = model.GetModel()
};
}
response.Success = model.IsSuccess;
2021-12-14 11:25:32 +01:00
response.Status = !model.IsSuccess ? StatusCodes.Status400BadRequest : result.StatusCode.Value;
2021-12-14 01:23:03 +01:00
result.StatusCode = response.Status;
result.Value = response;
2021-12-13 16:11:52 +01:00
}
2021-12-16 16:59:27 +01:00
// format bulk patch results
else if (result.Value is IEnumerable<Result<string>> list)
{
int countSucceeded = list.Count(x => x.IsSuccess);
int countFailed = list.Count() - countSucceeded;
BulkOperationApiResponse response = countFailed > 0 ? new BulkOperationWithErrorsApiResponse() : new BulkOperationApiResponse();
response.CountSucceeded = countSucceeded;
response.CountFailed = countFailed;
if (countFailed > 0 && response is BulkOperationWithErrorsApiResponse errorResponse)
{
errorResponse.Errors = list.Where(x => !x.IsSuccess).SelectMany(x => x.Errors.Select(e => new BulkOperationErrorApiResponseError()
{
AffectedId = x.Model,
Category = ApiErrorCodes.Categories.Validation,
Code = "// TODO",
Property = e.Property,
Message = e.Message
})).ToList();
}
response.Success = countSucceeded > 0;
response.Status = countSucceeded < 1 ? StatusCodes.Status400BadRequest : result.StatusCode.Value;
result.StatusCode = response.Status;
result.Value = response;
}
2021-12-14 11:25:32 +01:00
// format model results
else
{
DataApiResponse response = new();
if (context.HttpContext.Items.TryGetValue(ApiConstants.ChangeToken, out object tokenObj) && tokenObj is string token)
{
response = new TokenizedDataApiResponse() { ChangeToken = token };
}
2021-12-14 11:54:36 +01:00
response.Success = result.StatusCode.Value >= 200 && result.StatusCode.Value <= 299;
2021-12-14 11:25:32 +01:00
response.Status = result.StatusCode.Value;
response.Data = result.Value;
result.Value = response;
}
2021-12-14 01:23:03 +01:00
// append metadata
2021-12-13 16:11:52 +01:00
if (result.Value is ApiResponse apiResponse)
{
apiResponse.Metadata = GetMetadata(context);
2021-12-14 11:25:32 +01:00
context.HttpContext.Response.Headers["X-Variant"] = "api-response";
2021-11-30 14:32:10 +01:00
}
}
}
2021-12-13 16:11:52 +01:00
ApiResponseMetadata GetMetadata(ResultExecutingContext context)
{
2021-12-18 16:24:07 +01:00
if (!context.HttpContext.Items.ContainsKey("zero.action.started"))
{
return new();
}
2021-12-13 16:11:52 +01:00
DateTimeOffset started = (DateTimeOffset)context.HttpContext.Items["zero.action.started"];
TimeSpan duration = DateTimeOffset.Now - started;
return new()
{
Duration = duration,
RequestDate = started
};
}
//if (context.Result is ObjectResult result && result.StatusCode.HasValue)
//{
// if (typeof(ZeroIdEntity).IsAssignableFrom(result.DeclaredType))
// {
// result.Value = new ModelApiResponse()
// {
// Model = result.Value,
// Success = true,
// Status = result.StatusCode.Value,
// ChangeToken = context.HttpContext.Items[ApiConstants.ChangeToken] as string,
// Metadata = new ModelApiResponseMetadata()
// {
// RequestDate = started,
// Duration = duration,
// Token = IdGenerator.Create(32)
// }
// };
// }
// else if (typeof(Paged).IsAssignableFrom(result.DeclaredType))
// {
// Paged paged = result.Value as Paged;
// result.Value = new PagedApiResponse()
// {
// Items = paged.GetItems(),
// Paging = new()
// {
// Page = paged.Page,
// PageSize = paged.PageSize,
// TotalItems = paged.TotalItems,
// TotalPages = paged.TotalPages,
// HasMore = paged.HasMore
// },
// Success = true,
// Status = result.StatusCode.Value,
// Metadata = new ModelApiResponseMetadata()
// {
// RequestDate = started,
// Duration = duration,
// Token = IdGenerator.Create(32)
// }
// };
// }
//}
2021-11-30 14:32:10 +01:00
}