Значение Rotativa не может быть нулевым. Имя параметра: контекст - PullRequest
0 голосов
/ 16 января 2019

Я пытаюсь использовать Rotativa для создания PDF и возврата байтов, однако я получаю сообщение об ошибке:

Значение не может быть нулевым. Имя параметра: контекст

Вот мой код:

public string getReportsPDF(string community, string procedure)
{
    SiteSuperReportsController controller = new SiteSuperReportsController();

    string value = "";
    byte[] pdfBytes = new byte[] { };

    if (procedure == "GetProductionTasks")
    {
        var actionPDF = new Rotativa.ActionAsPdf("RedBluePDF", new { community = community, procedure = procedure })
        {
            PageSize = Size.A4,
            PageOrientation = Rotativa.Options.Orientation.Landscape,
            PageMargins = { Left = 1, Right = 1 }
        };
        try
        {
            pdfBytes = actionPDF.BuildFile(controller.ControllerContext);
            value = "Works";
        }
        catch(Exception e)
        {
            value = e.Message.ToString();
        }
    }
    return value;
}

Возвращаемое значение: Значение не может быть нулевым. Имя параметра: контекст

Что я делаю не так?

1 Ответ

0 голосов
/ 26 апреля 2019

Один из вариантов - переместить вызов на BuildFile в метод действия контроллера, где контекст контроллера доступен как свойство с именем ControllerContext.

Если вам нужно создать свой контроллер вручную, как в вашем примере, вам придется создать контекст самостоятельно. Дерек Комартин показывает в своем блоге Использование Razor в консольном приложении (вне ASP.NET Core MVC) , как это сделать для проекта ASP.Core 2. Для вашего сценария попробуйте изменить

pdfBytes = actionPDF.BuildFile(controller.ControllerContext);

до

pdfBytes = actionPDF.BuildFile(CreateDummyControllerContext("SiteSuperReports"));

с использованием следующих методов:

    private ControllerContext CreateDummyControllerContext(string controllerName)
    {
        var context = new ControllerContext
        {
            HttpContext = new DefaultHttpContext
            {
                RequestServices = GetServiceProvider()
            },
            RouteData = new RouteData
            {
                Values = {{"controller", controllerName}}
            },
            ActionDescriptor = new Microsoft.AspNetCore.Mvc.Controllers.ControllerActionDescriptor
            {
                RouteValues = new Dictionary<string, string>(),
            }
        };

        return context;
    }

    // see https://codeopinion.com/using-razor-in-a-console-application/
    private ServiceProvider GetServiceProvider()
    {
        var services = new ServiceCollection();
        services.AddSingleton(PlatformServices.Default.Application);
        var environment = new HostingEnvironment
        {
            ApplicationName = Assembly.GetEntryAssembly().GetName().Name
        };
        services.AddSingleton<IHostingEnvironment>(environment);
        services.Configure<RazorViewEngineOptions>(options =>
        {
            options.FileProviders.Clear();
            options.FileProviders.Add(new PhysicalFileProvider(Directory.GetCurrentDirectory()));
        });
        services.AddSingleton<ObjectPoolProvider, DefaultObjectPoolProvider>();
        services.AddSingleton<DiagnosticSource>(new DiagnosticListener("Microsoft.AspNetCore"));

        services.AddLogging();
        services.AddMvc();

        return services.BuildServiceProvider();
    }

Возможно, вам потребуется добавить пакет Microsoft.Extensions.PlatformAbstractions.

...