Closed ardalis closed 3 years ago
The only difference between that and what we have:
public abstract Task<ActionResult<TResponse>> HandleAsync(
TRequest request,
CancellationToken cancellationToken = default
);
is the lack of ActionResult<>
wrapping the TResponse
. That's what you need? The ActionResult is causing problems when you want to return a File?
Looking at this SO thread (https://stackoverflow.com/questions/42460198/return-file-in-asp-net-core-web-api) it looks like there are plenty of ways to use a custom ActionResult to return a file. And the issue seems to be that ApiEndpoints doesn't let you swap out the ActionResult type with FileContentResult or FileStreamResult, correct?
If that's correct, sorry not for not making me understand well but I don't speak English.
The error occurs when the returns a FileResult or FileStreamResult, the type of parameter returned by the ActionResult does not match, leaving an error of the type ActionResult<T>
not defined"
Hi,
I ran into a similar problem. I would like to return a "FileContentResult" which is an ActionResult at the end. So it will return a ActionResult
System.ArgumentException: Invalid type parameter 'Microsoft.AspNetCore.Mvc.FileContentResult' specified for 'ActionResult
That's how my code looks like:
[ApiController]
[Route("fxrates")]
public class GetForDate : BaseAsyncEndpoint
.WithRequest<DateTime>
.WithResponse<FileContentResult>
{
private readonly IService _service;
private readonly ILogger<GetForDate> _logger;
public GetForDate(
IService service,
ILogger<GetForDate> logger)
{
_service = service;
_logger = logger;
}
[HttpGet]
[Produces("text/plain")]
public override async Task<ActionResult<FileContentResult>> HandleAsync(
DateTime request,
CancellationToken cancellationToken = default)
{
var (filename, content) = await _service.GetFileForDay(DateTime.Now, cancellationToken);
if (content == null)
return NotFound();
return File(content, "text/plain", Path.GetFileName(filename));
}
}
What seems to be working is this modification of the code
[ApiController]
[Route("fxrates")]
public class GetForDate : BaseAsyncEndpoint
.WithRequest<DateTime>
.WithoutResponse
{
private readonly IService _service;
private readonly ILogger<GetForDate> _logger;
public GetForDate(
IService service,
ILogger<GetForDate> logger)
{
_service = service;
_logger = logger;
}
[HttpGet]
[Produces("text/plain")]
public override async Task<ActionResult> HandleAsync(
DateTime request,
CancellationToken cancellationToken = default)
{
var (filename, content) = await _service.GetFileForDay(DateTime.Now, cancellationToken);
if (content == null)
return NotFound();
return File(content, "text/plain", Path.GetFileName(filename));
}
}
Not sure if I like this approach, but it works.
Cheers Daniel
I've added a sample that shows how to download a file using ApiEndpoints and the fluent generic base classes. It's here:
Basically you just need to use WithoutResponse
and return File(...)
Hi Ardalis, please consider adding a custom return type for File types public abstract class WithResponseCustoms : BaseEndpointAsync { public abstract Task HandleAsync( TRequest request, CancellationToken cancellationToken = default ); }
from https://github.com/ardalis/ApiEndpoints/issues/77#issuecomment-829787486