public async Task <FileContentResult> PrintDynamic(int templateId, [FromQuery] PrintDynamicArguments args, CancellationToken cancellation) { var service = GetFactService(); var result = await service.PrintDynamic(templateId, args, cancellation); var fileBytes = result.FileBytes; var fileName = result.FileName; var contentType = ControllerUtilities.ContentType(fileName); Response.Headers.Add("x-filename", fileName); return(File(fileContents: fileBytes, contentType: contentType, fileName)); }
/// <summary> /// Returns a template-generated text file that is evaluated based on the given <paramref name="templateId"/>. /// The text generation will implicitly contain a variable $ that evaluates to the results of the dynamic query specified in <paramref name="args"/>. /// </summary> public async Task <FileResult> PrintDynamic(int templateId, PrintDynamicArguments args, CancellationToken cancellation) { await Initialize(cancellation); // (1) Preloaded Query var collection = typeof(TEntity).Name; var defId = DefinitionId; // (2) Functions + Variables var globalFunctions = new Dictionary <string, EvaluationFunction>(); var localFunctions = new Dictionary <string, EvaluationFunction>(); var globalVariables = new Dictionary <string, EvaluationVariable>(); var localVariables = new Dictionary <string, EvaluationVariable> { ["$Source"] = new EvaluationVariable($"{collection}/{defId}"), ["$Type"] = new EvaluationVariable(args.Type), ["$Select"] = new EvaluationVariable(args.Select), ["$OrderBy"] = new EvaluationVariable(args.OrderBy), ["$Filter"] = new EvaluationVariable(args.Filter), ["$Having"] = new EvaluationVariable(args.Having), ["$Top"] = new EvaluationVariable(args.Top), ["$Skip"] = new EvaluationVariable(args.Skip) }; await FactBehavior.SetPrintingFunctions(localFunctions, globalFunctions, cancellation); await FactBehavior.SetPrintingVariables(localVariables, globalVariables, cancellation); // (2) The templates var template = await FactBehavior.GetPrintingTemplate(templateId, cancellation); var nameP = new TemplatePlanLeaf(template.DownloadName, TemplateLanguage.Text); var bodyP = new TemplatePlanLeaf(template.Body, TemplateLanguage.Html); var printoutP = new TemplatePlanTuple(nameP, bodyP); TemplatePlan plan; if (string.IsNullOrWhiteSpace(template.Context)) { IReadOnlyList <DynamicRow> data; if (args.Type == "Fact") { var result = await GetFact(new FactArguments { Select = args.Select, Filter = args.Filter, OrderBy = args.OrderBy, Top = args.Top, Skip = args.Skip, CountEntities = false, }, cancellation); data = result?.Data; } else if (args.Type == "Aggregate") { var result = await GetAggregate(new GetAggregateArguments { Select = args.Select, Filter = args.Filter, Having = args.Having, OrderBy = args.OrderBy, Top = args.Top, }, cancellation); data = result?.Data; } else { throw new ServiceException($"Unknown Type '{args.Type}'."); } localVariables.Add("$", new EvaluationVariable(data)); plan = printoutP; } else { plan = new TemplatePlanDefine("$", template.Context, printoutP); } // (4) Culture CultureInfo culture = GetCulture(args.Culture); // Generate the output var genArgs = new TemplateArguments(globalFunctions, globalVariables, localFunctions, localVariables, culture); await _templateService.GenerateFromPlan(plan, genArgs, cancellation); var downloadName = nameP.Outputs[0]; var body = bodyP.Outputs[0]; // Change the body to bytes var bodyBytes = Encoding.UTF8.GetBytes(body); // Use a default download name if none is provided if (string.IsNullOrWhiteSpace(downloadName)) { var meta = await GetMetadata(cancellation); downloadName = meta.PluralDisplay(); } if (!downloadName.ToLower().EndsWith(".html")) { downloadName += ".html"; } // Return as a file return(new FileResult(bodyBytes, downloadName)); }