public async Task <ActionResult> Index(string cardUrl = null) { cardUrl = cardUrl ?? "https://raw.githubusercontent.com/Microsoft/AdaptiveCards/master/samples/v1.0/Scenarios/ActivityUpdate.json"; try { var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30)); // Get the JSON from the card URL var client = new HttpClient(); var response = await client.GetAsync(cardUrl, cts.Token); var json = await response.Content.ReadAsStringAsync(); // Make sure the payload has a version property var jObject = JObject.Parse(json); if (!jObject.TryGetValue("version", out var _)) { jObject["version"] = "0.5"; } // Parse the Adaptive Card JSON AdaptiveCardParseResult parseResult = AdaptiveCard.FromJson(jObject.ToString()); AdaptiveCard card = parseResult.Card; // Create a host config AdaptiveHostConfig hostConfig = new AdaptiveHostConfig() { SupportsInteractivity = false }; // TODO: Load custom host configs // Create a renderer AdaptiveCardRenderer renderer = new AdaptiveCardRenderer(hostConfig); // Set any XAML resource Dictionary if you have one renderer.ResourcesPath = System.IO.Path.Combine(_env.WebRootPath, "Styles", "MyStyles.xaml"); // Render the card to bitmap RenderedAdaptiveCardImage renderedCard = await renderer.RenderCardToImageAsync(card, createStaThread : true, cancellationToken : cts.Token); return(File(renderedCard.ImageStream, "image/png")); } catch (OperationCanceledException) { // Timed out return(StatusCode((int)HttpStatusCode.RequestTimeout)); } catch (Exception) { // TODO: log throw; } }
private async static Task RenderAdaptiveCard(Attachment attachment) { // This is entirely optional, just shows how to render an adaptive card which in a console app isn't really very practical! try { AdaptiveCardParseResult result = AdaptiveCard.FromJson(attachment.Content.ToString()); var adaptiveCard = AdaptiveCard.FromJson(attachment.Content.ToString()); if (adaptiveCard != null) { // Create a host config with no interactivity // (buttons in images would be deceiving) AdaptiveHostConfig hostConfig = new AdaptiveHostConfig() { SupportsInteractivity = false }; // Create a renderer AdaptiveCardRenderer renderer = new AdaptiveCardRenderer(hostConfig); // Render the card to png RenderedAdaptiveCardImage renderedCard = await renderer.RenderCardToImageAsync(adaptiveCard.Card, createStaThread : true, cancellationToken : default(CancellationToken)); string fileName = $"{Guid.NewGuid()}.png"; using (var fileStream = File.Create(fileName)) { renderedCard.ImageStream.Seek(0, SeekOrigin.Begin); renderedCard.ImageStream.CopyTo(fileStream); } Console.WriteLine($"Adaptive Card rendered to {fileName} for debug purposes."); Process.Start(fileName); } Console.WriteLine($"Adaptive Card Speak Property: {adaptiveCard.Card.Speak}"); } catch (Exception) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("Adaptive card not parsed"); Console.ForegroundColor = ConsoleColor.Gray; } }
private async void viewImage_Click(object sender, RoutedEventArgs e) { //Disable interactivity to remove inputs and actions from the image var supportsInteractivity = Renderer.HostConfig.SupportsInteractivity; Renderer.HostConfig.SupportsInteractivity = false; var renderedCard = await Renderer.RenderCardToImageAsync(AdaptiveCard.FromJson(textBox.Text).Card, false); Renderer.HostConfig.SupportsInteractivity = supportsInteractivity; var path = Path.GetRandomFileName() + ".png"; using (var fileStream = new FileStream(path, FileMode.Create)) { await renderedCard.ImageStream.CopyToAsync(fileStream); } Process.Start(path); }
private static async Task RenderCard(string file, AdaptiveCardRenderer renderer, string outPath) { try { var watch = new Stopwatch(); watch.Start(); AdaptiveCardParseResult parseResult = AdaptiveCard.FromJson(File.ReadAllText(file, Encoding.UTF8)); AdaptiveCard card = parseResult.Card; // Timeout after 30 seconds var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30)); // Render the card to an image RenderedAdaptiveCardImage renderedCard = await renderer.RenderCardToImageAsync(card, true, 400, cts.Token); // Report any warnings foreach (var warning in parseResult.Warnings.Union(renderedCard.Warnings)) { Console.WriteLine($"[{Path.GetFileName(file)}] WARNING: {warning.Message}"); } // Write to a png file with the same name as the json file var outputFile = Path.Combine(outPath, Path.ChangeExtension(Path.GetFileName(file), ".png")); using (var fileStream = new FileStream(outputFile, FileMode.Create)) { renderedCard.ImageStream.CopyTo(fileStream); Console.WriteLine($"[{watch.ElapsedMilliseconds}ms T{Thread.CurrentThread.ManagedThreadId}]\t{Path.GetFileName(file)} => {Path.GetFileName(outputFile)}"); } } catch (Exception ex) { Console.Error.WriteLine($"[FAILED]\t{Path.GetFileName(file)} => {ex.Message}"); } }
private async Task <Stream> ConvertAsync(Attachment attachment, CancellationToken cancellationToken) { if (attachment.ContentType == AdaptiveCard.ContentType) { // https://docs.microsoft.com/en-us/adaptive-cards/sdk/rendering-cards/net-image/render-a-card AdaptiveCard card = null; if (attachment.Content is AdaptiveCard adaptiveCard) { card = adaptiveCard; } else if (attachment.Content is JToken jtoken) { AdaptiveCardParseResult parseResult = AdaptiveCard.FromJson(jtoken.ToString()); card = parseResult.Card; } else { throw new NotImplementedException($"{attachment.Content.GetType().Name} is not supported yet!"); } // TODO don't know if it is thread safe or not var adaptiveRenderer = new AdaptiveCardRenderer(_adaptiveHostConfig); // Set any XAML resource Dictionary if you have one //renderer.ResourcesPath = <path-to-your-resourcedictionary.xaml>; // Render the card to png // Set createStaThread to true if running from a server var renderedCard = await adaptiveRenderer.RenderCardToImageAsync(card, createStaThread : true, cancellationToken : cancellationToken); return(renderedCard.ImageStream); } else { throw new NotSupportedException($"{attachment.ContentType} is not supported yet!"); } }