I'm building a method on my Controller to generate an SVG QR Code (QRCoder) and I'm trying to inline the resultant SVG from the controller into the View using a Method on the Controller.
When I attempt to view the method directly, I see the SVG XML coming back successfully, but it's getting an exception. I'm not quite sure what I need to make my controller return so that I can do this in my view.
<img src="~/Redirect/QRCode/{code}/svg"/>
the equivalent PNG version works perfectly.
<img src="~/Redirect/QRCode/{code}/png"/>
[Route("[controller]/QRCode/{code}/{format?}")]
public IActionResult QRCodeImage(string code, BarcodeService.Format format = BarcodeService.Format.Png)
{
//Database call to get the real Uri...
var uri = "https://github.com/paulfarry/";
switch (format)
{
case BarcodeService.Format.Svg:
{
var data = barcodeService.GenerateQRCodeSvg(uri);
return File(data, "image/svg xml; charset=utf-8");
}
case BarcodeService.Format.Png:
default:
{
var data = barcodeService.GenerateQRCode(uri);
return File(data, "image/png");
}
}
}
When I view the page directly I would have expected to see the SVG rendered but I get this exception information plus the SVG data.
https://localhost:5001/Redirect/QRCode/a/svg
An unhandled exception occurred while processing the request.
FileNotFoundException: Could not find file:
<svg version="1.1" baseProfile="full" shape-rendering="crispEdges" width="740" height="740" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><rect x="0" y="0" width="740" height="740" fill="#FFFFFF" />
<!--Remaining SVG data is here-->
</svg>
Microsoft.AspNetCore.Mvc.Infrastructure.VirtualFileResultExecutor.ExecuteAsync(ActionContext context, VirtualFileResult result)
Microsoft.AspNetCore.Mvc.VirtualFileResult.ExecuteResultAsync(ActionContext context)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultAsync(IActionResult result)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext<TFilter, TFilterAsync>(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeNextResultFilterAsync<TFilter, TFilterAsync>()
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResultExecutedContextSealed context)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext<TFilter, TFilterAsync>(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultFilters()
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|24_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.MigrationsEndPointMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
CodePudding user response:
Turns out to be very simple to solve.
Just needed to return Content
instead of File
But took a lot of experimenting.
case BarcodeService.Format.Svg:
{
var data = barcodeService.GenerateQRCodeSvg(uri);
return Content(data, "image/svg xml);
}