You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
198 lines
5.8 KiB
C#
198 lines
5.8 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
using Microsoft.AspNetCore.Http;
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
namespace Haoliang.Core.Services
|
|
{
|
|
// 中间件和过滤器
|
|
public class ExceptionMiddleware
|
|
{
|
|
private readonly RequestDelegate _next;
|
|
private readonly ILogger<ExceptionMiddleware> _logger;
|
|
|
|
public ExceptionMiddleware(RequestDelegate next, ILogger<ExceptionMiddleware> logger)
|
|
{
|
|
_next = next;
|
|
_logger = logger;
|
|
}
|
|
|
|
public async Task InvokeAsync(HttpContext context)
|
|
{
|
|
try
|
|
{
|
|
await _next(context);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "An unhandled exception occurred");
|
|
await HandleExceptionAsync(context, ex);
|
|
}
|
|
}
|
|
|
|
private static Task HandleExceptionAsync(HttpContext context, Exception exception)
|
|
{
|
|
context.Response.ContentType = "application/json";
|
|
|
|
var response = new
|
|
{
|
|
success = false,
|
|
message = "Internal server error",
|
|
timestamp = DateTime.Now,
|
|
error = exception.Message
|
|
};
|
|
|
|
context.Response.StatusCode = 500;
|
|
return context.Response.WriteAsJsonAsync(response);
|
|
}
|
|
}
|
|
|
|
public class LoggingMiddleware
|
|
{
|
|
private readonly RequestDelegate _next;
|
|
private readonly ILogger<LoggingMiddleware> _logger;
|
|
|
|
public LoggingMiddleware(RequestDelegate next, ILogger<LoggingMiddleware> logger)
|
|
{
|
|
_next = next;
|
|
_logger = logger;
|
|
}
|
|
|
|
public async Task InvokeAsync(HttpContext context)
|
|
{
|
|
var startTime = DateTime.Now;
|
|
|
|
// 记录请求信息
|
|
_logger.LogInformation($"Request: {context.Request.Method} {context.Request.Path}");
|
|
|
|
try
|
|
{
|
|
await _next(context);
|
|
}
|
|
finally
|
|
{
|
|
var duration = DateTime.Now - startTime;
|
|
_logger.LogInformation($"Response: {context.Response.StatusCode} - Duration: {duration.TotalMilliseconds}ms");
|
|
}
|
|
}
|
|
}
|
|
|
|
public class CORSMiddleware
|
|
{
|
|
private readonly RequestDelegate _next;
|
|
|
|
public CORSMiddleware(RequestDelegate next)
|
|
{
|
|
_next = next;
|
|
}
|
|
|
|
public async Task InvokeAsync(HttpContext context)
|
|
{
|
|
context.Response.Headers.Add("Access-Control-Allow-Origin", "*");
|
|
context.Response.Headers.Add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
|
|
context.Response.Headers.Add("Access-Control-Allow-Headers", "Content-Type, Authorization, X-Requested-With");
|
|
|
|
if (context.Request.Method == "OPTIONS")
|
|
{
|
|
context.Response.StatusCode = 200;
|
|
return;
|
|
}
|
|
|
|
await _next(context);
|
|
}
|
|
}
|
|
|
|
// API响应格式
|
|
public class ApiResponse
|
|
{
|
|
public bool Success { get; set; }
|
|
public object Data { get; set; }
|
|
public string Message { get; set; }
|
|
public DateTime Timestamp { get; set; }
|
|
public int Code { get; set; }
|
|
|
|
public static ApiResponse Success(object data = null, string message = "Success")
|
|
{
|
|
return new ApiResponse
|
|
{
|
|
Success = true,
|
|
Data = data,
|
|
Message = message,
|
|
Timestamp = DateTime.Now,
|
|
Code = 200
|
|
};
|
|
}
|
|
|
|
public static ApiResponse Error(string message = "Error", int code = 500, object data = null)
|
|
{
|
|
return new ApiResponse
|
|
{
|
|
Success = false,
|
|
Data = data,
|
|
Message = message,
|
|
Timestamp = DateTime.Now,
|
|
Code = code
|
|
};
|
|
}
|
|
|
|
public static ApiResponse NotFound(string message = "Resource not found")
|
|
{
|
|
return Error(message, 404);
|
|
}
|
|
|
|
public static ApiResponse BadRequest(string message = "Bad request")
|
|
{
|
|
return Error(message, 400);
|
|
}
|
|
|
|
public static ApiResponse Unauthorized(string message = "Unauthorized")
|
|
{
|
|
return Error(message, 401);
|
|
}
|
|
}
|
|
|
|
// 统一响应包装器
|
|
public class PagedResponse<T>
|
|
{
|
|
public IEnumerable<T> Items { get; set; }
|
|
public int TotalCount { get; set; }
|
|
public int PageNumber { get; set; }
|
|
public int PageSize { get; set; }
|
|
public int TotalPages { get; set; }
|
|
public bool HasNextPage { get; set; }
|
|
public bool HasPreviousPage { get; set; }
|
|
|
|
public static PagedResponse<T> Create(IEnumerable<T> items, int totalCount, int pageNumber, int pageSize)
|
|
{
|
|
return new PagedResponse<T>
|
|
{
|
|
Items = items,
|
|
TotalCount = totalCount,
|
|
PageNumber = pageNumber,
|
|
PageSize = pageSize,
|
|
TotalPages = (int)Math.Ceiling(totalCount / (double)pageSize),
|
|
HasNextPage = pageNumber < (int)Math.Ceiling(totalCount / (double)pageSize),
|
|
HasPreviousPage = pageNumber > 1
|
|
};
|
|
}
|
|
}
|
|
|
|
// 分页参数
|
|
public class PaginationParams
|
|
{
|
|
public int PageNumber { get; set; } = 1;
|
|
public int PageSize { get; set; } = 10;
|
|
public string SortBy { get; set; }
|
|
public string SortOrder { get; set; } = "asc";
|
|
public string Search { get; set; }
|
|
}
|
|
|
|
// 排序参数
|
|
public class SortParams
|
|
{
|
|
public string Field { get; set; }
|
|
public string Direction { get; set; } = "asc";
|
|
}
|
|
} |