public void SerializeAnalyzeV1Response() { var response = new AnalyzeResponse { MissingDependencies = new List <MemberInfo> { new MemberInfo { MemberDocId = "doc1" }, new MemberInfo { MemberDocId = "doc2" } }, SubmissionId = Guid.NewGuid().ToString(), Targets = new List <FrameworkName> { new FrameworkName("target1", Version.Parse("1.0.0.0")) }, UnresolvedUserAssemblies = new List <string> { "assembly1", "assembly2", "assembly3" }, }; var v1 = new AnalyzeResponseV1(response); var newtonsoft = v1.Serialize().Deserialize <AnalyzeResponseV1>(); var dcjs = DeserializeObjectDcjs <AnalyzeResponseV1>(SerializeDcjs(v1)); CompareAnalyzeResponseV1(v1, newtonsoft); CompareAnalyzeResponseV1(v1, dcjs); }
private ReportingResult GetReportingResult(AnalyzeRequest request, AnalyzeResponse response, IDependencyInfo dependencyInfo) { if (response == null) { return(null); } using (var progressTask = _progressReport.StartTask(LocalizedStrings.ComputingReport)) { try { return(_reportGenerator.ComputeReport( response.Targets, response.SubmissionId, request.RequestFlags, dependencyInfo?.Dependencies, response.MissingDependencies, dependencyInfo?.UnresolvedAssemblies, response.UnresolvedUserAssemblies, dependencyInfo?.AssembliesWithErrors, response.NuGetPackages )); } catch (Exception) { progressTask.Abort(); throw; } } }
private static void CompareAnalyzeResponse(AnalyzeResponse response, AnalyzeResponse deserialized) { CollectionAssertAreEquivalent(response.MissingDependencies, deserialized.MissingDependencies); Assert.Equal(response.SubmissionId, deserialized.SubmissionId); CollectionAssertAreEquivalent(response.Targets, deserialized.Targets); CollectionAssertAreEquivalent(response.UnresolvedUserAssemblies, deserialized.UnresolvedUserAssemblies); }
public async Task <ActionResult> Index(string id) { if (string.IsNullOrWhiteSpace(id)) { return(View((AnalyzeResponse)null)); } try { var response = await _apiPortService.GetAnalysisAsync(id); return(View(response.Response)); } catch (NotFoundException) { var response = new AnalyzeResponse { SubmissionId = id, Targets = null }; return(View(response)); } catch (PortabilityAnalyzerException e) { return(View(e)); } }
public void WriteStream(Stream stream, AnalyzeResponse response) { using (var streamWriter = new StreamWriter(stream)) using (var writer = new JsonTextWriter(streamWriter)) { DataExtensions.Serializer.Serialize(writer, response); } }
public IEnumerator TestAnalyze() { Log.Debug("VisualRecognitionServiceV4IntegrationTests", "Attempting to Analyze..."); AnalyzeResponse analyzeResponse = null; List <FileWithMetadata> imagesFile = new List <FileWithMetadata>(); using (FileStream fs1 = File.OpenRead(giraffeImageFilepath), fs2 = File.OpenRead(turtleImageFilepath)) { using (MemoryStream ms1 = new MemoryStream(), ms2 = new MemoryStream()) { fs1.CopyTo(ms1); fs2.CopyTo(ms2); FileWithMetadata fileWithMetadata = new FileWithMetadata() { Data = ms1, ContentType = "image/jpeg", Filename = Path.GetFileName(giraffeImageFilepath) }; imagesFile.Add(fileWithMetadata); FileWithMetadata fileWithMetadata2 = new FileWithMetadata() { Data = ms2, ContentType = "image/jpeg", Filename = Path.GetFileName(turtleImageFilepath) }; imagesFile.Add(fileWithMetadata2); service.Analyze( callback: (DetailedResponse <AnalyzeResponse> response, IBMError error) => { Log.Debug("VisualRecognitionServiceV4IntegrationTests", "Analyze result: {0}", response.Response); analyzeResponse = response.Result; Assert.IsNotNull(analyzeResponse); Assert.IsNotNull(analyzeResponse.Images); Assert.IsTrue(analyzeResponse.Images.Count > 0); Assert.IsNotNull(analyzeResponse.Images[0].Objects.Collections); Assert.IsTrue(analyzeResponse.Images[0].Objects.Collections.Count > 0); Assert.IsNull(error); }, collectionIds: new List <string>() { giraffeCollectionId }, features: new List <string>() { "objects" }, imagesFile: imagesFile ); while (analyzeResponse == null) { yield return(null); } } } }
public async Task WriteStreamAsync(Stream stream, AnalyzeResponse response) { using (var scope = _factory.CreateScope()) { var model = new RazorHtmlObject(response, _targetMapper); var helper = scope.ServiceProvider.GetRequiredService <RazorViewToStringRenderer>(); await helper.RenderViewAsync("Views/ReportTemplate.cshtml", model, stream); } }
public void CreatesHtmlReport() { var mapper = Substitute.For <ITargetMapper>(); var writer = new HtmlReportWriter(mapper); var response = new AnalyzeResponse { MissingDependencies = new List <MemberInfo> { new MemberInfo { MemberDocId = "Type1.doc1", DefinedInAssemblyIdentity = "Assembly1", TypeDocId = "Type1" }, new MemberInfo { MemberDocId = "Type2.doc2", DefinedInAssemblyIdentity = "Assembly2", TypeDocId = "Type2" } }, SubmissionId = Guid.NewGuid().ToString(), Targets = new List <FrameworkName> { new FrameworkName("target1", Version.Parse("1.0.0.0")) }, UnresolvedUserAssemblies = new List <string> { "UnresolvedAssembly", "UnresolvedAssembly2", "UnresolvedAssembly3" }, BreakingChangeSkippedAssemblies = new List <AssemblyInfo>(), BreakingChanges = new List <BreakingChangeDependency>(), }; var reportingResult = new ReportingResult(response.Targets, response.MissingDependencies, response.SubmissionId, AnalyzeRequestFlags.NoTelemetry); response.ReportingResult = reportingResult; var tempFile = Path.GetTempFileName(); try { using (var file = File.OpenWrite(tempFile)) { writer.WriteStream(file, response); } Assert.True(File.Exists(tempFile)); var contents = File.ReadAllText(tempFile); Assert.True(!string.IsNullOrEmpty(contents)); Assert.Contains(response.SubmissionId, contents); } finally { if (File.Exists(tempFile)) { File.Delete(tempFile); } } }
private void _defaultAnalyzeAssertations(AnalyzeResponse r) { Assert.True(r.IsValid); Assert.NotNull(r.Tokens); Assert.True(r.Tokens.Any()); Assert.True(r.Tokens.All(t => { return(!t.Token.IsNullOrEmpty() && !t.Type.IsNullOrEmpty() && t.EndPostion > 0); })); }
public Task WriteStreamAsync(Stream stream, AnalyzeResponse response) { using (var streamWriter = new StreamWriter(stream)) { using (var writer = new JsonTextWriter(streamWriter)) { DataExtensions.Serializer.Serialize(writer, response); } } return(Task.CompletedTask); }
public void WriteStream(Stream stream, AnalyzeResponse response) { const string ReportTemplateName = "ReportTemplate"; using (var writer = new StreamWriter(stream)) { var reportObject = new RazorHtmlObject(response, _targetMapper); var mainTemplate = Resolve(ReportTemplateName); var razor = _razorService.RunCompile(mainTemplate, ReportTemplateName, typeof(RazorHtmlObject), reportObject); writer.Write(razor); } }
public RazorHtmlObject(AnalyzeResponse response, ITargetMapper targetMapper) { _targetMapper = targetMapper; RequestFlags = response.ReportingResult.RequestFlags; ReportingResult = response.ReportingResult; TargetMapper = _targetMapper; OrderedUnresolvedAssemblies = response.ReportingResult.GetUnresolvedAssemblies().OrderBy(asm => asm.Key); OrderedAssembliesByIdentity = response.ReportingResult.GetAssemblyUsageInfo().OrderBy(a => a.SourceAssembly.AssemblyIdentity); MissingTypes = response.ReportingResult.GetMissingTypes(); TargetHeaders = _targetMapper.GetTargetNames(response.ReportingResult.Targets, true); OrderedBreakingChangesByAssembly = GetGroupedBreakingChanges(response.BreakingChanges, response.ReportingResult.GetAssemblyUsageInfo().Select(a => a.SourceAssembly)); BreakingChangesSummary = GetBreakingChangesSummary(OrderedBreakingChangesByAssembly); OrderedBreakingChangeSkippedAssemblies = response.BreakingChangeSkippedAssemblies.OrderBy(a => a.AssemblyIdentity); }
public AnalyzeResponse Analyze(string url, Dictionary <string, object> parameters) { try { var html_content = HttpHelper.Get(url, _headers); if (url.Contains("bangumi")) { return(ExtractBangumi(url, html_content)); } return(ExtractNormalVideo(url, html_content)); } catch (Exception ex) { return(AnalyzeResponse.Fail(ex.Message)); } }
/// <summary> /// Writes analysis reports to path supplied by options /// </summary> /// <param name="options"></param> /// <param name="includeResponse"></param> /// <returns>Output paths to the reports that were successfully written.</returns> public async Task <ReportingResultPaths> WriteAnalysisReportsAsync(IApiPortOptions options, bool includeResponse) { ValidateOptions(options); var jsonAdded = includeResponse ? TryAddJsonToOptions(options, out options) : false; foreach (var errorInput in options.InvalidInputFiles) { _progressReport.ReportIssue(string.Format(CultureInfo.CurrentCulture, LocalizedStrings.InvalidFileName, errorInput)); } var results = await GetAnalysisResultAsync(options); var outputPaths = new List <string>(); AnalyzeResponse response = null; foreach (var result in results.Results) { if (string.Equals(Json, result.Format, StringComparison.OrdinalIgnoreCase)) { response = result.Data?.Deserialize <AnalyzeResponse>(); if (jsonAdded) { continue; } } var outputPath = await CreateReport(result.Data, options.OutputFileName, result.Format, options.OverwriteOutputFile); if (!string.IsNullOrEmpty(outputPath)) { outputPaths.Add(outputPath); } } return(new ReportingResultPaths { Paths = outputPaths, Result = GetReportingResult(results.Request, response, results.Info) }); }
protected override void ExpectResponse(AnalyzeResponse response) { response.Tokens.Should().HaveCount(0); response.Detail.Should().NotBeNull("details should not be null because explain was specified"); response.Detail.CustomAnalyzer.Should().BeTrue(); response.Detail.CharFilters.Should().NotBeEmpty(); foreach (var c in response.Detail.CharFilters) { c.Name.Should().NotBeNullOrWhiteSpace(); c.FilteredText.Should().NotBeEmpty(); } response.Detail.Filters.Should().NotBeEmpty(); foreach (var c in response.Detail.Filters) { AssertTokenDetail(c); } response.Detail.Tokenizer.Should().NotBeNull(); AssertTokenDetail(response.Detail.Tokenizer); }
public RazorHtmlObject(AnalyzeResponse response, ITargetMapper targetMapper) { CatalogBuiltOn = response.CatalogLastUpdated; _targetMapper = targetMapper; RequestFlags = response.ReportingResult.RequestFlags; ReportingResult = response.ReportingResult; TargetMapper = _targetMapper; OrderedUnresolvedAssemblies = response.ReportingResult.GetUnresolvedAssemblies().OrderBy(asm => asm.Key); OrderedAssembliesByIdentity = response.ReportingResult.GetAssemblyUsageInfo().OrderBy(a => a.SourceAssembly.AssemblyIdentity); MissingTypes = response.ReportingResult.GetMissingTypes(); Targets = response.Targets; TargetHeaders = _targetMapper.GetTargetNames(response.ReportingResult.Targets, true); OrderedBreakingChangesByAssembly = GetGroupedBreakingChanges(response.BreakingChanges, response.ReportingResult.GetAssemblyUsageInfo().Select(a => a.SourceAssembly)); BreakingChangesSummary = GetBreakingChangesSummary(OrderedBreakingChangesByAssembly); var skippedAssemblies = response.BreakingChangeSkippedAssemblies ?? Enumerable.Empty <AssemblyInfo>(); OrderedBreakingChangeSkippedAssemblies = skippedAssemblies.OrderBy(a => a.AssemblyIdentity); NuGetPackages = response.NuGetPackages; }
public static ReferenceGraph CreateGraph(AnalyzeResponse response) { ReferenceGraph rg = new ReferenceGraph(); AnalyzeRequest request = response.Request; // get the list of assemblies that have some data reported for them. var assembliesWithData = response.ReportingResult.GetAssemblyUsageInfo().ToDictionary(x => x.SourceAssembly.AssemblyIdentity, x => x.UsageData); var unresolvedAssemblies = response.ReportingResult.GetUnresolvedAssemblies().Select(x => x.Key).ToList(); // Add every user specified assembly to the graph foreach (var userAsem in request.UserAssemblies) { var node = rg.GetOrAddNodeForAssembly(new ReferenceNode(userAsem.AssemblyIdentity)); // For this node, make sure we capture the data, if we have it. if (assembliesWithData.ContainsKey(node.Assembly)) { node.UsageData = assembliesWithData[node.Assembly]; } // create nodes for all the references, if non platform. foreach (var reference in userAsem.AssemblyReferences) { if (!(assembliesWithData.ContainsKey(reference.ToString()) || unresolvedAssemblies.Contains(reference.ToString()))) { // platform reference (not in the user specified asssemblies and not an unresolved assembly. continue; } var refNode = rg.GetOrAddNodeForAssembly(new ReferenceNode(reference.ToString())); // if the reference is missing, flag it as such. refNode.IsMissing = unresolvedAssemblies.Contains(reference.ToString()); node.AddReferenceToNode(refNode); } } return(rg); }
private static void GenerateOrderPage(Worksheet page, AnalyzeResponse response) { page.AddRow(new[] { LocalizedStrings.RecommendedOrderDetails }); page.AddRow(); var header = new[] { LocalizedStrings.AssemblyHeader }; page.AddRow(header); int detailsRows = 1; foreach (var assembly in response.RecommendedOrder) { page.AddRow(assembly); detailsRows++; } // Generate the pretty table page.AddTable(3, detailsRows, 1, header.ToArray()); page.AddColumnWidth(100); }
public static void SerializeAnalyzeResponse() { var response = new AnalyzeResponse { MissingDependencies = new List <MemberInfo> { new MemberInfo { MemberDocId = "doc1" }, new MemberInfo { MemberDocId = "doc2" } }, SubmissionId = Guid.NewGuid().ToString(), Targets = new List <FrameworkName> { new FrameworkName("target1", Version.Parse("1.0.0.0")) }, UnresolvedUserAssemblies = new List <string> { "assembly1", "assembly2", "assembly3" } }; var newtonsoft = response.Serialize().Deserialize <AnalyzeResponse>(); CompareAnalyzeResponse(response, newtonsoft); }
private static void GenerateUnreferencedAssembliesPage(Worksheet missingAssembliesPage, AnalyzeResponse response) { var missingAssembliesPageHeader = new[] { LocalizedStrings.AssemblyHeader, LocalizedStrings.UsedBy, LocalizedStrings.UnresolvedAssemblyStatus }; int detailsRows = 0; missingAssembliesPage.AddRow(missingAssembliesPageHeader.ToArray()); detailsRows++; var unresolvedAssembliesMap = response.ReportingResult.GetUnresolvedAssemblies(); foreach (var unresolvedAssemblyPair in unresolvedAssembliesMap.OrderBy(asm => asm.Key)) { if (unresolvedAssemblyPair.Value.Any()) { foreach (var usedIn in unresolvedAssemblyPair.Value) { missingAssembliesPage.AddRow(unresolvedAssemblyPair.Key, usedIn, LocalizedStrings.UnresolvedUsedAssembly); detailsRows++; } } else { missingAssembliesPage.AddRow(unresolvedAssemblyPair.Key, string.Empty, LocalizedStrings.UnresolvedUsedAssembly); detailsRows++; } } foreach (var unresolvedAssemblyPair in response.Request.NonUserAssemblies.OrderBy(asm => asm.AssemblyIdentity)) { missingAssembliesPage.AddRow(unresolvedAssemblyPair.AssemblyIdentity, string.Empty, LocalizedStrings.SkippedAssembly); detailsRows++; } // Generate the pretty table missingAssembliesPage.AddTable(1, detailsRows, 1, missingAssembliesPageHeader); missingAssembliesPage.AddColumnWidth(40, 40, 30); }
public Task WriteStreamAsync(Stream stream, AnalyzeResponse response) { // Create a new dgml every time write to a new stream. var dgml = new DGMLManager(); var rg = ReferenceGraph.CreateGraph(response); var analysisResult = response.ReportingResult; var targets = analysisResult.Targets; GenerateTargetContainers(dgml, targets); dgml.SetTitle(response.ApplicationName); // For each target, let's generate the assemblies foreach (var node in rg.Nodes.Keys) { for (int i = 0; i < targets.Count; i++) { double portabilityIndex = 0, portabilityIndexRefs = 0; string missingTypes = null; if (node.UsageData != null) { TargetUsageInfo usageInfo = node.UsageData[i]; portabilityIndex = node.GetPortabilityIndex(i); portabilityIndexRefs = node.GetPortabilityIndexForReferences(i); missingTypes = GenerateMissingTypes(node.Assembly, analysisResult, i); } // generate the node string tfm = targets[i].FullName; Guid nodeGuid = dgml.GetOrCreateGuid($"{node.Assembly},TFM:{tfm}"); string nodeTitle = $"{node.SimpleName}: {Math.Round(portabilityIndex * 100, 2)}%, References: {Math.Round(portabilityIndexRefs * 100, 2)}%"; string nodeCategory = node.IsMissing ? "Unresolved" : GetCategory(Math.Round(portabilityIndex * portabilityIndexRefs * 100, 2)); dgml.AddNode(nodeGuid, nodeTitle, nodeCategory, portabilityIndex, group: string.IsNullOrEmpty(missingTypes) ? null : "Collapsed"); if (dgml.TryGetId(tfm, out Guid frameworkGuid)) { dgml.AddLink(frameworkGuid, nodeGuid, "Contains"); } if (!string.IsNullOrEmpty(missingTypes)) { Guid commentGuid = Guid.NewGuid(); dgml.AddNode(commentGuid, missingTypes, "Comment"); dgml.AddLink(nodeGuid, commentGuid, "Contains"); } } } // generate the references. foreach (var node in rg.Nodes.Keys) { for (int i = 0; i < targets.Count; i++) { // generate the node string tfm = targets[i].FullName; Guid nodeGuid = dgml.GetOrCreateGuid($"{node.Assembly},TFM:{tfm}"); foreach (var refNode in node.Nodes) { Guid refNodeGuid = dgml.GetOrCreateGuid($"{refNode.Assembly},TFM:{tfm}"); dgml.AddLink(nodeGuid, refNodeGuid); } } } dgml.Save(stream); return(Task.CompletedTask); }
}; //腾讯视频客户端下载1080P public AnalyzeResponse Analyze(string url, Dictionary <string, object> parameters) { var response = new AnalyzeResponse(); try { if (Util.IsMatch(url, "https?://(m\\.)?egame.qq.com/"))//企鹅电竞 { //TODO return(AnalyzeResponse.NotSupported()); } else if (url.Contains("kg.qq.com") || url.Contains("kg2.qq.com"))//全民K歌 { //TODO return(AnalyzeResponse.NotSupported()); } else if (url.Contains("live.qq.com"))//企鹅直播 { //TODO return(AnalyzeResponse.NotSupported()); } else if (url.Contains("mp.weixin.qq.com/s"))//微信公众号 { //只取第一个 var content = HttpHelper.Get(url); var vid = Util.Match(content, "\\?vid=(\\w+)"); var detail = GetInfos(vid, out string errorMsg); if (detail != null) { response.Success = true; response.Data = detail; } else { response.Success = false; response.Message = errorMsg; } } else { var content = ""; var title = ""; var vid = ""; if (url.Contains("kuaibao.qq.com") || Util.IsMatch(url, "http://daxue.qq.com/content/content/id/\\d+")) { //# http://daxue.qq.com/content/content/id/2321 content = HttpHelper.Get(url, _headers); vid = Util.Match(content, "vid\\s*=\\s*\"\\s*([^\"]+)\""); title = Util.Match(content, "title\">([^\"]+)</p>"); title = string.IsNullOrWhiteSpace(title) ? vid : title; } else if (url.Contains("iframe/player.html")) { vid = Util.Match(url, "\\bvid=(\\w+)"); title = vid; } else if (url.Contains("view.inews.qq.com")) { content = HttpHelper.Get(url, _headers); vid = Util.Match(content, "\"vid\":\"(\\w+)\""); title = Util.Match(content, "\"title\":\"(\\w +)\""); } else { content = HttpHelper.Get(url, _headers); vid = Util.Match(content, "vid\"*\\s*:\\s*\"\\s*([^\"]+)\""); if (string.IsNullOrWhiteSpace(vid)) { vid = Util.Match(content, "id\"*\\s*:\\s*\"(.+?)\""); } title = Util.Match(content, $"<a.*?id\\s*=\\s*\"{vid}\".*?title\\s*=\\s*\"(.+?)\".*?>"); if (string.IsNullOrWhiteSpace(title)) { title = Util.Match(content, "title\">([^\"]+)</p>"); } if (string.IsNullOrWhiteSpace(title)) { title = Util.Match(content, "\"title\":\"([^\"]+)\""); } title = string.IsNullOrWhiteSpace(title) ? vid : title; } var detail = GetInfos(vid, out string errorMsg); if (detail != null) { response.Success = true; response.Data = detail; } else { response.Success = false; response.Message = errorMsg; } } return(response); } catch (Exception ex) { return(AnalyzeResponse.Fail(ex.Message)); } }
public Task WriteStreamAsync(Stream stream, AnalyzeResponse response) { var excelWriter = new ExcelOpenXmlOutputWriter(_targetMapper, response.ReportingResult, response.BreakingChanges, response.CatalogLastUpdated, description: null); return(excelWriter.WriteToAsync(stream)); }
public void Analysis() { IClient client = CreateClient(); IRequest request = Substitute.For <IRequest>(); client.GetAsync(Arg.Any <string>()) .Returns(request); #region response var analyzeResponse = new AnalyzeResponse() { Images = new List <Image>() { new Image() { Source = new ImageSource() { Type = "type", Filename = "filename", ArchiveFilename = "archiveFilename", SourceUrl = "sourceUrl", ResolvedUrl = "resolvedUrl" }, Dimensions = new ImageDimensions() { Width = 100, Height = 200 }, Objects = new DetectedObjects() { Collections = new List <CollectionObjects>() { new CollectionObjects() { CollectionId = "collectionId", Objects = new List <ObjectDetail>() { new ObjectDetail() { _Object = "object", Location = new ObjectDetailLocation() { Top = 0, Left = 1, Width = 2, Height = 3 } } } } } } } } }; var response = new DetailedResponse <AnalyzeResponse>(); response.Result = analyzeResponse; #endregion request.WithArgument(Arg.Any <string>(), Arg.Any <string>()) .Returns(request); request.WithBodyContent(new MultipartFormDataContent()) .Returns(request); request.As <AnalyzeResponse>() .Returns(Task.FromResult(response)); NoAuthAuthenticator authenticator = new NoAuthAuthenticator(); VisualRecognitionService service = new VisualRecognitionService(client); service.Version = "versionDate"; service.Analyze( collectionIds: new List <string> { "colletionIds" }, features: new List <string> { "features" }); Assert.IsTrue(response.Result.Images[0].Source.Type == "type"); Assert.IsTrue(response.Result.Images[0].Source.Filename == "filename"); Assert.IsTrue(response.Result.Images[0].Source.ArchiveFilename == "archiveFilename"); Assert.IsTrue(response.Result.Images[0].Source.SourceUrl == "sourceUrl"); Assert.IsTrue(response.Result.Images[0].Source.ResolvedUrl == "resolvedUrl"); Assert.IsTrue(response.Result.Images[0].Dimensions.Width == 100); Assert.IsTrue(response.Result.Images[0].Dimensions.Height == 200); Assert.IsTrue(response.Result.Images[0].Objects.Collections[0].CollectionId == "collectionId"); Assert.IsTrue(response.Result.Images[0].Objects.Collections[0].Objects[0]._Object == "object"); Assert.IsTrue(response.Result.Images[0].Objects.Collections[0].Objects[0].Location.Top == 0); Assert.IsTrue(response.Result.Images[0].Objects.Collections[0].Objects[0].Location.Left == 1); Assert.IsTrue(response.Result.Images[0].Objects.Collections[0].Objects[0].Location.Width == 2); Assert.IsTrue(response.Result.Images[0].Objects.Collections[0].Objects[0].Location.Height == 3); }
public ExcelOpenXmlOutputWriter(ITargetMapper mapper, AnalyzeResponse response, string description) { _mapper = mapper; _response = response; _description = description ?? string.Empty; }
public Task WriteStreamAsync(Stream stream, AnalyzeResponse response) { var excelWriter = new ExcelOpenXmlOutputWriter(_targetMapper, response, description: null); return(excelWriter.WriteToAsync(stream)); }