-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Provide a more in depth example of writing responses in middleware #7238
Comments
Another user also asked for this in a comment on the page https://docs.microsoft.com/en-us/aspnet/core/mvc/models/formatting
|
There's no support for using MVC's content negotiation in middleware right now. @rynowak has been doing some work to streamline the result executor model, so from 2.1, you should be able to inject See #6822 (comment) and aspnet/Diagnostics#346. |
Thanks for reporting this issue. We'll consider your feedback as part of an existing issue we're tracking as part of our planning at the moment. |
In 2.1, you can have something like this: using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Abstractions;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection;
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);
}
} And use it like this: using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
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; }
} |
Thanks @khellang |
I've tried something like this, but it always fails on this (cannot resolve the service):
I've tried resolving |
What is |
Well, in this case a class that derives from Not sure if this matters, I'm using the latest versions of asp.netcore packages (Microsoft.AspNetCore 2.1.2, Microsoft.AspNetCore.Mvc 2.1.1). |
The services are registered as their Mvc/src/Microsoft.AspNetCore.Mvc.Core/DependencyInjection/MvcCoreServiceCollectionExtensions.cs Lines 245 to 255 in f12f9b4
So resolving If the type derives from I suggest changing the method to a non-generic version, which takes in an |
Doh, now when you said it, it's so obvious. Thanks, got it working. For a side note, I did try a case when |
Yes, that's because the registration is for |
What if we are handling global exception and we want to write a content in json or xml or custom (based on content negotiation)? e.g.
|
See this middleware for an example of how to do this. |
Thank you it's almost clear but as the example:
this code generates this error
|
It would be nice to have This should be documented more, there is a lot of wrong and misleading examples on the internet always writing to JSON(like using Newtonsoft.Json directly) completely ignoring content negotiation and output formatters mechanisms in ASP.NET Core. @khellang From what I see
Mvc/src/Microsoft.AspNetCore.Mvc.WebApiCompatShim/HttpRequestMessage/HttpRequestMessageExtensions.cs Line 268 in a67d936
EDIT: actually |
I'd like to return a response from middleware that obeys the same behaviour as returning an
ObjectResult
from a controller, i.e. it uses my default output formatter if no Accept header is specified or uses the correct output formatter based on the Accept header.Looking at the current docs it's not clear how this can be achieved since they only demonstrate writing simple strings in the response.
See https://stackoverflow.com/questions/48228167/how-can-i-write-a-response-in-middleware-using-the-same-settings-as-returning-an for a more in depth explanation.
The text was updated successfully, but these errors were encountered: