添加项目文件。
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace IM.ASPNETCore
|
||||
{
|
||||
public class ApiControllerBase : ControllerBase
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
using IM.Commons;
|
||||
using IM.DomainCommons;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace IM.ASPNETCore
|
||||
{
|
||||
public class ExceptionMiddleware
|
||||
{
|
||||
private readonly RequestDelegate _next;
|
||||
public ExceptionMiddleware(RequestDelegate next)
|
||||
{
|
||||
_next = next;
|
||||
}
|
||||
|
||||
public async Task InvokeAsync(HttpContext context)
|
||||
{
|
||||
try
|
||||
{
|
||||
await _next(context);
|
||||
}
|
||||
catch (DomainException ex)
|
||||
{
|
||||
await DomainExceptionHandlerAsync(context, ex);
|
||||
}
|
||||
}
|
||||
|
||||
public Task DomainExceptionHandlerAsync(HttpContext context, DomainException ex)
|
||||
{
|
||||
context.Response.ContentType = "application/json";
|
||||
var result = Result<object>.Fail(ResultCode.PARAMETER_ERROR, ex.Message); // 包装成你的 Result
|
||||
return context.Response.WriteAsJsonAsync(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.0" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.6.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\IM.Commons\IM.Commons.csproj" />
|
||||
<ProjectReference Include="..\DomainCommons\IM.DomainCommons.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,24 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace IM.ASPNETCore
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Class
|
||||
| AttributeTargets.Method, AllowMultiple = false, Inherited = true
|
||||
)]
|
||||
public class UnitOfWorkAttribute : Attribute
|
||||
{
|
||||
public Type[] DbContextTypes { get; private set; }
|
||||
|
||||
public UnitOfWorkAttribute(params Type[] dbContextTypes)
|
||||
{
|
||||
this.DbContextTypes = dbContextTypes;
|
||||
foreach (var type in dbContextTypes)
|
||||
{
|
||||
if (!typeof(DbContext).IsAssignableFrom(type))
|
||||
{
|
||||
throw new ArgumentException($"{type} must inherit from DbContext");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
using Microsoft.AspNetCore.Mvc.Abstractions;
|
||||
using Microsoft.AspNetCore.Mvc.Controllers;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System.Reflection;
|
||||
using System.Transactions;
|
||||
|
||||
namespace IM.ASPNETCore
|
||||
{
|
||||
public class UnitOfWorkFilter : IAsyncActionFilter
|
||||
{
|
||||
private static UnitOfWorkAttribute? GetUoWAttr(ActionDescriptor actionDesc)
|
||||
{
|
||||
var caDesc = actionDesc as ControllerActionDescriptor;
|
||||
if (caDesc == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
//try to get UnitOfWorkAttribute from controller,
|
||||
//if there is no UnitOfWorkAttribute on controller,
|
||||
//try to get UnitOfWorkAttribute from action
|
||||
var uowAttr = caDesc.ControllerTypeInfo
|
||||
.GetCustomAttribute<UnitOfWorkAttribute>();
|
||||
if (uowAttr != null)
|
||||
{
|
||||
return uowAttr;
|
||||
}
|
||||
else
|
||||
{
|
||||
return caDesc.MethodInfo
|
||||
.GetCustomAttribute<UnitOfWorkAttribute>();
|
||||
}
|
||||
}
|
||||
public async Task OnActionExecutionAsync(ActionExecutingContext context,
|
||||
ActionExecutionDelegate next)
|
||||
{
|
||||
var uowAttr = GetUoWAttr(context.ActionDescriptor);
|
||||
if (uowAttr == null)
|
||||
{
|
||||
await next();
|
||||
return;
|
||||
}
|
||||
using TransactionScope txScope = new(TransactionScopeAsyncFlowOption.Enabled);
|
||||
List<DbContext> dbCtxs = new List<DbContext>();
|
||||
foreach (var dbCtxType in uowAttr.DbContextTypes)
|
||||
{
|
||||
//用HttpContext的RequestServices
|
||||
//确保获取的是和请求相关的Scope实例
|
||||
var sp = context.HttpContext.RequestServices;
|
||||
DbContext dbCtx = (DbContext)sp.GetRequiredService(dbCtxType);
|
||||
dbCtxs.Add(dbCtx);
|
||||
}
|
||||
var result = await next();
|
||||
if (result.Exception == null)
|
||||
{
|
||||
foreach (var dbCtx in dbCtxs)
|
||||
{
|
||||
await dbCtx.SaveChangesAsync();
|
||||
}
|
||||
txScope.Complete();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using IM.Commons;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
|
||||
namespace IM.ASPNETCore
|
||||
{
|
||||
public class ValidatorFilter : IActionFilter
|
||||
{
|
||||
public void OnActionExecuted(ActionExecutedContext context)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void OnActionExecuting(ActionExecutingContext context)
|
||||
{
|
||||
if (context.ModelState.IsValid) return;
|
||||
|
||||
var errors = context.ModelState.Where(x => x.Value.Errors.Count() > 0).ToList();
|
||||
|
||||
var errMsg = errors.FirstOrDefault().Value?.Errors.First().ErrorMessage
|
||||
?? ResultCode.PARAMETER_ERROR.GetDescription();
|
||||
var result = Result<object>.Fail(ResultCode.PARAMETER_ERROR, errMsg);
|
||||
|
||||
context.Result = new OkObjectResult(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user