fix enum convertor for api and razor
This commit is contained in:
31
ServiceHost/MiddleWare/ApiJsonEnumFilter.cs
Normal file
31
ServiceHost/MiddleWare/ApiJsonEnumFilter.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace ServiceHost.MiddleWare;
|
||||
|
||||
public class ApiJsonEnumFilter : IActionFilter
|
||||
{
|
||||
public void OnActionExecuting(ActionExecutingContext context)
|
||||
{
|
||||
// قبل از اکشن نیازی نیست کاری کنیم
|
||||
}
|
||||
|
||||
public void OnActionExecuted(ActionExecutedContext context)
|
||||
{
|
||||
if (context.Result is ObjectResult objectResult)
|
||||
{
|
||||
var enumConverter = new JsonStringEnumConverter();
|
||||
var options = new JsonSerializerOptions(JsonSerializerDefaults.Web);
|
||||
options.Converters.Add(enumConverter);
|
||||
var json = JsonSerializer.Serialize(objectResult.Value, options);
|
||||
context.Result = new ContentResult
|
||||
{
|
||||
Content = json,
|
||||
ContentType = "application/json",
|
||||
StatusCode = objectResult.StatusCode
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
29
ServiceHost/MiddleWare/ConditionalJsonOutputFormatter.cs
Normal file
29
ServiceHost/MiddleWare/ConditionalJsonOutputFormatter.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
using Microsoft.AspNetCore.Mvc.Formatters;
|
||||
using System.Text.Json;
|
||||
using System.Text;
|
||||
|
||||
namespace ServiceHost.MiddleWare;
|
||||
|
||||
public class ConditionalJsonOutputFormatter : TextOutputFormatter
|
||||
{
|
||||
private readonly JsonSerializerOptions _options;
|
||||
|
||||
public ConditionalJsonOutputFormatter(JsonSerializerOptions options)
|
||||
{
|
||||
_options = options;
|
||||
SupportedMediaTypes.Add("application/json");
|
||||
SupportedEncodings.Add(System.Text.Encoding.UTF8);
|
||||
}
|
||||
|
||||
public override bool CanWriteResult(OutputFormatterCanWriteContext context)
|
||||
{
|
||||
var path = context.HttpContext.Request.Path;
|
||||
return path.StartsWithSegments("/api", StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
public override async Task WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding)
|
||||
{
|
||||
var response = context.HttpContext.Response;
|
||||
await JsonSerializer.SerializeAsync(response.Body, context.Object, context.ObjectType ?? context.Object?.GetType() ?? typeof(object), _options);
|
||||
}
|
||||
}
|
||||
42
ServiceHost/MiddleWare/CustomJsonResultExecutor.cs
Normal file
42
ServiceHost/MiddleWare/CustomJsonResultExecutor.cs
Normal file
@@ -0,0 +1,42 @@
|
||||
using Microsoft.AspNetCore.Mvc.Infrastructure;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Text;
|
||||
|
||||
public class CustomJsonResultExecutor : IActionResultExecutor<JsonResult>
|
||||
{
|
||||
private readonly IHttpContextAccessor _httpContextAccessor;
|
||||
private readonly ILogger<CustomJsonResultExecutor> _logger;
|
||||
|
||||
public CustomJsonResultExecutor(IHttpContextAccessor httpContextAccessor, ILogger<CustomJsonResultExecutor> logger)
|
||||
{
|
||||
_httpContextAccessor = httpContextAccessor;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async Task ExecuteAsync(ActionContext context, JsonResult result)
|
||||
{
|
||||
var response = context.HttpContext.Response;
|
||||
response.ContentType = "application/json; charset=utf-8";
|
||||
|
||||
var requestPath = context.HttpContext.Request.Path;
|
||||
|
||||
var options = new JsonSerializerOptions
|
||||
{
|
||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
||||
WriteIndented = false
|
||||
};
|
||||
|
||||
if (requestPath.HasValue && requestPath.StartsWithSegments("/api", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
// API → enum به صورت string
|
||||
options.Converters.Add(new JsonStringEnumConverter());
|
||||
}
|
||||
// Else: Razor → enum بدون converter (یعنی عدد)
|
||||
|
||||
var json = JsonSerializer.Serialize(result.Value, options);
|
||||
|
||||
await response.WriteAsync(json, Encoding.UTF8);
|
||||
}
|
||||
}
|
||||
61
ServiceHost/MiddleWare/RazorJsonEnumOverrideMiddleware.cs
Normal file
61
ServiceHost/MiddleWare/RazorJsonEnumOverrideMiddleware.cs
Normal file
@@ -0,0 +1,61 @@
|
||||
using System.Text.Json;
|
||||
using System.Text;
|
||||
|
||||
namespace ServiceHost.MiddleWare;
|
||||
|
||||
public class RazorJsonEnumOverrideMiddleware
|
||||
{
|
||||
private readonly RequestDelegate _next;
|
||||
|
||||
public RazorJsonEnumOverrideMiddleware(RequestDelegate next)
|
||||
{
|
||||
_next = next;
|
||||
}
|
||||
|
||||
public async Task InvokeAsync(HttpContext context)
|
||||
{
|
||||
// نگهدار خروجی
|
||||
var originalBody = context.Response.Body;
|
||||
using var newBody = new MemoryStream();
|
||||
context.Response.Body = newBody;
|
||||
|
||||
await _next(context); // اجرای مرحله بعدی
|
||||
|
||||
// فقط برای مسیرهای غیر /api و وقتی Content-Type = application/json
|
||||
if (!context.Request.Path.StartsWithSegments("/api", StringComparison.OrdinalIgnoreCase) &&
|
||||
context.Response.ContentType?.Contains("application/json", StringComparison.OrdinalIgnoreCase) == true)
|
||||
{
|
||||
newBody.Seek(0, SeekOrigin.Begin);
|
||||
using var reader = new StreamReader(newBody);
|
||||
var originalJson = await reader.ReadToEndAsync();
|
||||
|
||||
// JSON رو deserialize و دوباره serialize میکنیم بدون EnumConverter
|
||||
try
|
||||
{
|
||||
var obj = JsonSerializer.Deserialize<object>(originalJson);
|
||||
var newJson = JsonSerializer.Serialize(obj, new JsonSerializerOptions
|
||||
{
|
||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
|
||||
});
|
||||
|
||||
context.Response.Body = originalBody;
|
||||
context.Response.ContentLength = Encoding.UTF8.GetByteCount(newJson);
|
||||
await context.Response.WriteAsync(newJson);
|
||||
return;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// fallback if deserialization fails
|
||||
context.Response.Body = originalBody;
|
||||
newBody.Seek(0, SeekOrigin.Begin);
|
||||
await newBody.CopyToAsync(originalBody);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// اگر شرط نداشت، همون خروجی قبلی رو منتقل کن
|
||||
context.Response.Body = originalBody;
|
||||
newBody.Seek(0, SeekOrigin.Begin);
|
||||
await newBody.CopyToAsync(originalBody);
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,10 @@ using _0_Framework.Application.UID;
|
||||
using _0_Framework.Exceptions.Handler;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using ServiceHost.Test;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Text.Json;
|
||||
using Microsoft.AspNetCore.Mvc.Infrastructure;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
@@ -51,6 +55,7 @@ var connectionStringTestDb = builder.Configuration.GetConnectionString("TestDb")
|
||||
//builder.Services.AddSingleton<IMongoDatabase>(mongoDatabase);
|
||||
|
||||
#endregion
|
||||
builder.Services.AddSingleton<IActionResultExecutor<JsonResult>, CustomJsonResultExecutor>();
|
||||
PersonalBootstrapper.Configure(builder.Services, connectionString);
|
||||
TestDbBootStrapper.Configure(builder.Services, connectionStringTestDb);
|
||||
AccountManagementBootstrapper.Configure(builder.Services, connectionString);
|
||||
@@ -142,11 +147,15 @@ builder.Services.AddAuthorization(options =>
|
||||
|
||||
// });
|
||||
|
||||
builder.Services.AddControllers()
|
||||
.AddJsonOptions(options =>
|
||||
{
|
||||
options.JsonSerializerOptions.Converters.Add(new System.Text.Json.Serialization.JsonStringEnumConverter());
|
||||
});
|
||||
builder.Services.AddControllers().AddJsonOptions(options =>
|
||||
{
|
||||
options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
|
||||
});
|
||||
|
||||
//builder.Services.AddControllers(
|
||||
//options=> {
|
||||
// options.Filters.Add(new ApiJsonEnumFilter());
|
||||
//});
|
||||
|
||||
|
||||
builder.Services.AddRazorPages(options =>
|
||||
@@ -181,8 +190,9 @@ builder.Services.AddSignalR();
|
||||
#region Swagger
|
||||
builder.Services.AddSwaggerGen(options =>
|
||||
{
|
||||
|
||||
var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
|
||||
options.UseInlineDefinitionsForEnums();
|
||||
|
||||
var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
|
||||
var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
|
||||
options.IncludeXmlComments(xmlPath);
|
||||
|
||||
@@ -321,6 +331,7 @@ app.UseAuthorization();
|
||||
//app.UseLoginHandlerMiddleware();
|
||||
|
||||
//app.UseCheckTaskMiddleware();
|
||||
app.UseMiddleware<RazorJsonEnumOverrideMiddleware>();
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user