如何使用 MVC 的内容协商在 ASP.NET Core MVC 中间件中返回响应?
Posted
技术标签:
【中文标题】如何使用 MVC 的内容协商在 ASP.NET Core MVC 中间件中返回响应?【英文标题】:How can I return a response in ASP.NET Core MVC middleware using MVC's content negotiation? 【发布时间】:2018-01-12 14:23:22 【问题描述】:我有一些 ASP.NET Core MVC 中间件来捕获我想从中返回响应的未处理异常。
虽然httpContext.Response.WriteAsync
很容易写一个字符串,例如使用JsonSerializer
将对象序列化为字符串,我想使用标准的序列化设置和内容协商,以便如果我将默认输出格式更改为XML 或text/xml
在我有多个输出格式化程序时发送接受标头如果我从控制器返回 ObjectResult
,则会返回 XML。
有谁知道如何在中间件中实现这一点?
这是我目前只写 JSON 的代码:
public class UnhandledExceptionMiddleware
private readonly RequestDelegate _next;
private readonly IOutputFormatter _outputFormatter;
private readonly IHttpResponseStreamWriterFactory _streamWriterFactory;
public UnhandledExceptionMiddleware(RequestDelegate next, JsonOutputFormatter outputFormatter, IHttpResponseStreamWriterFactory streamWriterFactory)
_next = next;
_outputFormatter = outputFormatter;
_streamWriterFactory = streamWriterFactory;
public async Task Invoke(HttpContext context)
try
await _next(context);
catch (Exception ex)
await HandleExceptionAsync(context, ex);
private async Task HandleExceptionAsync(HttpContext context, Exception exception)
var error = new ErrorResultModel("Internal Server Error", exception.Message, exception.StackTrace);
context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
await _outputFormatter.WriteAsync(new OutputFormatterWriteContext(context, _streamWriterFactory.CreateWriter, typeof(ErrorResultModel), error));
其中ErrorResultModel
定义为:
public class ErrorResultModel
public string ResultMessage get; ;
public string ExceptionMessage get; ;
public string ExceptionStackTrace get; ;
public ErrorResultModel(string resultMessage, string exceptionMessage, string exceptionStackTrace)
ResultMessage = resultMessage;
ExceptionMessage = exceptionMessage;
ExceptionStackTrace = exceptionStackTrace;
【问题讨论】:
【参考方案1】:这在ASP.NET Core 2.0 MVC 中是不可能的。
这将是可能的in 2.1:
public static class HttpContextExtensions
private static readonly RouteData EmptyRouteData = new RouteData();
private static readonly ActionDescriptor EmptyActionDescriptor = new ActionDescriptor();
public static Task WriteResultAsync<TResult>(this HttpContext context, TResult result)
where TResult : IActionResult
if (context == null)
throw new ArgumentNullException(nameof(context));
var executor = context.RequestServices.GetService<IActionResultExecutor<TResult>>();
if (executor == null)
throw new InvalidOperationException($"No result executor for 'typeof(TResult).FullName' has been registered.");
var routeData = context.GetRouteData() ?? EmptyRouteData;
var actionContext = new ActionContext(context, routeData, EmptyActionDescriptor);
return executor.ExecuteAsync(actionContext, result);
public class Program : StartupBase
public static Task Main(string[] args)
return BuildWebHost(args).RunAsync();
public static IWebHost BuildWebHost(string[] args)
return new WebHostBuilder().UseStartup<Program>().UseKestrel().Build();
public override void ConfigureServices(IServiceCollection services)
services.AddMvcCore().AddJsonFormatters();
public override void Configure(IApplicationBuilder app)
app.Use((ctx, next) =>
var model = new Person("Krisian", "Hellang");
var result = new ObjectResult(model);
return ctx.WriteResultAsync(result);
);
public class Person
public Person(string firstName, string lastName)
FirstName = firstName;
LastName = lastName;
public string FirstName get;
public string LastName get;
【讨论】:
知道为什么var executor = context.RequestServices.GetService<IActionResultExecutor<TResult>>();
这段代码会失败吗?我尝试了所有变体,包括仅解析 ObjectResultExecutor。没有任何效果。但是我可以看到它在services.AddMvc()
之后注册。以上是关于如何使用 MVC 的内容协商在 ASP.NET Core MVC 中间件中返回响应?的主要内容,如果未能解决你的问题,请参考以下文章
Asp.net MVC 与 Asp.net Web API 区别
如何使用 jquery 或 ajax 在 c#/asp.net 中为 MVC 项目更新 razor 部分视图
大型查询如何在 C#/ASP.NET MVC 4 部分中返回结果
ASP.NET MVC:如何在返回状态码 404 时提供内容? [复制]