Home > Back-end >  Return inline dynamic SVG from MVC Controller
Return inline dynamic SVG from MVC Controller

Time:03-13

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);
            }
  • Related