diff --git a/Rotativa.AspNetCore/AsImageResultBase.cs b/Rotativa.AspNetCore/AsImageResultBase.cs
new file mode 100644
index 0000000..332f09c
--- /dev/null
+++ b/Rotativa.AspNetCore/AsImageResultBase.cs
@@ -0,0 +1,70 @@
+using Microsoft.AspNetCore.Mvc;
+using Rotativa.AspNetCore.Options;
+
+namespace Rotativa.AspNetCore
+{
+ public abstract class AsImageResultBase : AsResultBase
+ {
+ ///
+ /// Set height for cropping
+ ///
+ [OptionFlag("-f")]
+ public ImageFormat? Format { get; set; }
+
+ ///
+ /// Output image quality (between 0 and 100) (default 94)
+ ///
+ [OptionFlag("--quality")]
+ public int? Quality { get; set; }
+
+ ///
+ /// Set height for cropping
+ ///
+ [OptionFlag("--crop-h")]
+ public int? CropHeight { get; set; }
+
+ ///
+ /// Set width for cropping
+ ///
+ [OptionFlag("--crop-w")]
+ public int? CropWidth { get; set; }
+
+ ///
+ /// Set x coordinate for cropping
+ ///
+ [OptionFlag("--crop-x")]
+ public int? CropX { get; set; }
+
+ ///
+ /// Set y coordinate for cropping
+ ///
+ [OptionFlag("--crop-y")]
+ public int? CropY { get; set; }
+
+ ///
+ /// Sets the page width.
+ ///
+ /// Set screen width, note that this is used only as a guide line.
+ [OptionFlag("--width")]
+ public int? PageWidth { get; set; }
+
+ ///
+ /// Sets the page height in mm.
+ ///
+ /// Has priority over but has to be also specified.
+ [OptionFlag("--height")]
+ public int? PageHeight { get; set; }
+
+ protected override byte[] WkhtmlConvert(string switches)
+ {
+ return WkhtmltoimageDriver.Convert(this.WkhtmlPath, switches);
+ }
+
+ protected override string GetContentType()
+ {
+ var imageFormat = this.Format ?? ImageFormat.jpeg;
+
+ return $"image/{imageFormat}";
+ }
+ }
+}
\ No newline at end of file
diff --git a/Rotativa.AspNetCore/ViewAsImage.cs b/Rotativa.AspNetCore/ViewAsImage.cs
new file mode 100644
index 0000000..8e00943
--- /dev/null
+++ b/Rotativa.AspNetCore/ViewAsImage.cs
@@ -0,0 +1,151 @@
+using System;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Mvc.ModelBinding;
+using Microsoft.AspNetCore.Mvc.Rendering;
+using Microsoft.AspNetCore.Mvc.ViewEngines;
+using Microsoft.AspNetCore.Mvc.ViewFeatures;
+
+namespace Rotativa.AspNetCore
+{
+ public class ViewAsImage : AsImageResultBase
+ {
+ private string _viewName;
+
+ public string ViewName
+ {
+ get => _viewName ?? string.Empty;
+ set => _viewName = value;
+ }
+
+ private string _masterName;
+
+ public string MasterName
+ {
+ get => _masterName ?? string.Empty;
+ set => _masterName = value;
+ }
+
+ public object Model { get; set; }
+
+ public ViewDataDictionary ViewData { get; set; }
+
+ public ViewAsImage(ViewDataDictionary viewData = null)
+ {
+ this.WkhtmlPath = string.Empty;
+ MasterName = string.Empty;
+ ViewName = string.Empty;
+ Model = null;
+ ViewData = viewData;
+ }
+
+ public ViewAsImage(string viewName, ViewDataDictionary viewData = null)
+ : this(viewData)
+ {
+ ViewName = viewName;
+ }
+
+ public ViewAsImage(object model, ViewDataDictionary viewData = null)
+ : this(viewData)
+ {
+ Model = model;
+ }
+
+ public ViewAsImage(string viewName, object model, ViewDataDictionary viewData = null)
+ : this(viewData)
+ {
+ ViewName = viewName;
+ Model = model;
+ }
+
+ public ViewAsImage(string viewName, string masterName, object model)
+ : this(viewName, model)
+ {
+ MasterName = masterName;
+ }
+
+ protected override string GetUrl(ActionContext context)
+ {
+ return string.Empty;
+ }
+
+ protected virtual ViewEngineResult GetView(ActionContext context, string viewName, string masterName)
+ {
+ var engine = context.HttpContext.RequestServices.GetService(typeof(ICompositeViewEngine)) as ICompositeViewEngine;
+ var getViewResult = engine.GetView(executingFilePath: null, viewPath: viewName, isMainPage: true);
+ if (getViewResult.Success)
+ {
+ return getViewResult;
+ }
+
+ var findViewResult = engine.FindView(context, viewName, isMainPage: true);
+ if (findViewResult.Success)
+ {
+ return findViewResult;
+ }
+
+ var searchedLocations = getViewResult.SearchedLocations.Concat(findViewResult.SearchedLocations);
+ var errorMessage = string.Join(
+ Environment.NewLine,
+ new[] { $"Unable to find view '{viewName}'. The following locations were searched:" }.Concat(searchedLocations));
+
+ throw new InvalidOperationException(errorMessage);
+ }
+
+ protected override async Task CallTheDriver(ActionContext context)
+ {
+ // use action name if the view name was not provided
+ string viewName = ViewName;
+ if (string.IsNullOrEmpty(ViewName))
+ {
+ viewName = ((Microsoft.AspNetCore.Mvc.Controllers.ControllerActionDescriptor)context.ActionDescriptor).ActionName;
+ }
+
+ ViewEngineResult viewResult = GetView(context, viewName, MasterName);
+ var html = new StringBuilder();
+
+ //string html = context.GetHtmlFromView(viewResult, viewName, Model);
+ ITempDataProvider tempDataProvider = context.HttpContext.RequestServices.GetService(typeof(ITempDataProvider)) as ITempDataProvider;
+
+ var viewDataDictionary = new ViewDataDictionary(
+ metadataProvider: new EmptyModelMetadataProvider(),
+ modelState: new ModelStateDictionary())
+ {
+ Model = this.Model
+ };
+ if (this.ViewData != null)
+ {
+ foreach (var item in this.ViewData)
+ {
+ viewDataDictionary.Add(item);
+ }
+ }
+ using (var output = new StringWriter())
+ {
+ var view = viewResult.View;
+ var tempDataDictionary = new TempDataDictionary(context.HttpContext, tempDataProvider);
+ var viewContext = new ViewContext(
+ context,
+ viewResult.View,
+ viewDataDictionary,
+ tempDataDictionary,
+ output,
+ new HtmlHelperOptions());
+
+ await view.RenderAsync(viewContext);
+
+ html = output.GetStringBuilder();
+ }
+
+ string baseUrl = $"{context.HttpContext.Request.Scheme}://{context.HttpContext.Request.Host}";
+ var htmlForWkhtml = Regex.Replace(html.ToString(), "", $"", RegexOptions.IgnoreCase);
+
+ byte[] fileContent = WkhtmltoimageDriver.ConvertHtml(this.WkhtmlPath, this.GetConvertOptions(), htmlForWkhtml);
+ return fileContent;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Rotativa.AspNetCore/WkhtmltoimageDriver.cs b/Rotativa.AspNetCore/WkhtmltoimageDriver.cs
new file mode 100644
index 0000000..e48c737
--- /dev/null
+++ b/Rotativa.AspNetCore/WkhtmltoimageDriver.cs
@@ -0,0 +1,36 @@
+using System.Runtime.InteropServices;
+
+namespace Rotativa.AspNetCore
+{
+ public class WkhtmltoimageDriver : WkhtmlDriver
+ {
+ ///
+ /// wkhtmltoimage only has a .exe extension in Windows.
+ ///
+ private static readonly string wkhtmlExe =
+ RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "wkhtmltoimage.exe" : "wkhtmltoimage";
+
+ ///
+ /// Converts given HTML string to Image.
+ ///
+ /// Path to wkthmltoimage.
+ /// Switches that will be passed to wkhtmltoimage binary.
+ /// String containing HTML code that should be converted to Image.
+ /// PDF as byte array.
+ public static byte[] ConvertHtml(string wkhtmltoimagePath, string switches, string html)
+ {
+ return Convert(wkhtmltoimagePath, switches, html, wkhtmlExe);
+ }
+
+ ///
+ /// Converts given URL to Image.
+ ///
+ /// Path to wkthmltoimage.
+ /// Switches that will be passed to wkhtmltoimage binary.
+ /// PDF as byte array.
+ public static byte[] Convert(string wkhtmltoimagePath, string switches)
+ {
+ return Convert(wkhtmltoimagePath, switches, null, wkhtmlExe);
+ }
+ }
+}
\ No newline at end of file