public string RenderToStringAsync(string viewName, object model) { var httpContext = new DefaultHttpContext { RequestServices = _serviceProvider }; var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor()); using (var sw = new StringWriter()) { var viewResult = _razorViewEngine.FindView(actionContext, viewName, false); if (viewResult.View == null) { throw new ArgumentNullException($"{viewName} does not match any available view"); } var viewDictionary = new ViewDataDictionary(new EmptyModelMetadataProvider(), new ModelStateDictionary()) { Model = model }; var viewContext = new ViewContext( actionContext, viewResult.View, viewDictionary, new TempDataDictionary(actionContext.HttpContext, _tempDataProvider), sw, new HtmlHelperOptions() ); viewResult.View.RenderAsync(viewContext); return(sw.ToString()); } }
public IEnumerable <IDocument> Execute(IReadOnlyList <IDocument> inputs, IExecutionContext context) { // Register all the MVC and Razor services // In the future, if DI is implemented for all Wyam, the IExecutionContext would be registered as a service // and the IHostingEnviornment would be registered as transient with the execution context provided in ctor IServiceCollection serviceCollection = new ServiceCollection(); IMvcCoreBuilder builder = serviceCollection .AddMvcCore() .AddRazorViewEngine(); builder.PartManager.FeatureProviders.Add(new MetadataReferenceFeatureProvider(context)); serviceCollection.Configure <RazorViewEngineOptions>(options => { options.ViewLocationExpanders.Add(new ViewLocationExpander()); }); serviceCollection .AddSingleton <ILoggerFactory, TraceLoggerFactory>() .AddSingleton <DiagnosticSource, SilentDiagnosticSource>() .AddSingleton <IHostingEnvironment, HostingEnvironment>() .AddSingleton <ObjectPoolProvider, DefaultObjectPoolProvider>() .AddSingleton <IExecutionContext>(context) .AddSingleton <IBasePageTypeProvider>(new BasePageTypeProvider(_basePageType ?? typeof(RazorPage))) .AddScoped <IMvcRazorHost, RazorHost>(); IServiceProvider services = serviceCollection.BuildServiceProvider(); // Eliminate input documents that we shouldn't process List <IDocument> validInputs = inputs .Where(x => _ignorePrefix == null || !x.ContainsKey(Keys.SourceFileName) || !x.FilePath(Keys.SourceFileName).FullPath.StartsWith(_ignorePrefix)) .ToList(); // Compile and evaluate the pages in parallel IServiceScopeFactory scopeFactory = services.GetRequiredService <IServiceScopeFactory>(); return(validInputs.AsParallel().Select(input => { Trace.Verbose("Compiling Razor for {0}", input.SourceString()); using (var scope = scopeFactory.CreateScope()) { // Get services IRazorViewEngine viewEngine = services.GetRequiredService <IRazorViewEngine>(); IRazorPageActivator pageActivator = services.GetRequiredService <IRazorPageActivator>(); HtmlEncoder htmlEncoder = services.GetRequiredService <HtmlEncoder>(); IRazorPageFactoryProvider pageFactoryProvider = services.GetRequiredService <IRazorPageFactoryProvider>(); IRazorCompilationService razorCompilationService = services.GetRequiredService <IRazorCompilationService>(); IHostingEnvironment hostingEnviornment = services.GetRequiredService <IHostingEnvironment>(); // Compile the view string relativePath = GetRelativePath(input, context); FilePath viewStartLocationPath = _viewStartPath?.Invoke <FilePath>(input, context); string viewStartLocation = viewStartLocationPath != null ? GetRelativePath(viewStartLocationPath, context) : null; string layoutLocation = _layoutPath?.Invoke <FilePath>(input, context)?.FullPath; IView view; using (Stream stream = input.GetStream()) { view = GetViewFromStream(relativePath, stream, viewStartLocation, layoutLocation, viewEngine, pageActivator, htmlEncoder, pageFactoryProvider, hostingEnviornment.WebRootFileProvider, razorCompilationService); } // Render the view Trace.Verbose("Processing Razor for {0}", input.SourceString()); using (StringWriter output = new StringWriter()) { Microsoft.AspNetCore.Mvc.Rendering.ViewContext viewContext = GetViewContext(scope.ServiceProvider, view, input, context, output); viewContext.View.RenderAsync(viewContext).GetAwaiter().GetResult(); return context.GetDocument(input, output.ToString()); } } })); }