zoukankan      html  css  js  c++  java
  • ASP.NET Core中使用Razor视图引擎渲染视图为字符串

    一、前言

      在有些项目需求上或许需要根据模板生产静态页面,那么你一样可以用Razor语法去直接解析你的页面从而把解析的页面生成静态页,这样的使用场景很多,不限于生成静态页面,视图引擎为我们提供了模型到视图的代码或文本生成的能力。

      本文章中采用的是ASP.NET Core MVC原生的方法;当然我在YOYOFx中也实现了这种视图引擎 ( https://github.com/maxzhang1985/YOYOFx/blob/master/AspNetCore/YOYO.AspNetCore.ViewEngine.Razor ) 。

      当然在MVC 4、5的时代,我们也使用过如RazorEngine这样的第三方的视图引擎,那时候MVC中的Razor与框架耦合的比较紧密,第三方开源组件帮我们实现了在任意项目中使用Razor渲染视图为文本的方式;但是在.NET Core中 RazorEngine开源组件并没有移植过来,接下来我们还是要自食其力实现一个吧。

    二、实现视图渲染器

      其实在ASP.NET Core MVC中给我们提供了这样的方法,只是用起来不太方便,我们来对它进行一下封装。

      框架早已经为我们提供了视图渲染的接口 IRazorViewEngine 通过它的FindView方法来查找视图及.cshtml文件,当然查找方法也与MVC中的视图路径规则是对应的,本来就是一个东西嘛:) 

      我们来一步步实现,首先我们建立一个视图渲染器的接口:

    public interface IViewRenderService
    {
        Task<string> RenderToStringAsync(string viewName, object model);
    }

      然后是实现类了,代码很简单一看就懂了:

    public class ViewRenderService : IViewRenderService
    {
            private readonly IRazorViewEngine _razorViewEngine;
            private readonly ITempDataProvider _tempDataProvider;
            private readonly IServiceProvider _serviceProvider;
    
            public ViewRenderService(IRazorViewEngine razorViewEngine,
                ITempDataProvider tempDataProvider,
                IServiceProvider serviceProvider)
            {
                _razorViewEngine = razorViewEngine;
                _tempDataProvider = tempDataProvider;
                _serviceProvider = serviceProvider;
            }
    
            public async Task<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()
                    );
    
                    await viewResult.View.RenderAsync(viewContext);
                    return sw.ToString();
                }
            }
    }

    三、如何使用

      我们使用一个简单的例子来说明如何使用我们上面那个渲染器。

      1、建立ViewModel

    public class MyUserViewModel
    {
         public string Name { set; get; }
    }

      2、建立视图

    @model WebApplication6.Models.MyUserViewModel
    @{
        Layout = null;
    }
    <!DOCTYPE html>
    <html>
    <head>
        <title>Render view to string</title>
    </head>
    <body>
    <div>
          @Model.Name
    </div>
    </body>
    </html>

      3、修改HomeController

    public class HomeController : Controller
    {
            private IViewRenderService _viewRenderService;
            public HomeController(IViewRenderService viewSendeRenderService)
            {
                _viewRenderService = viewSendeRenderService;
            }
    
    
            public async Task<IActionResult> Index()
            {
                var user = new MyUserViewModel { Name = "hello world" };
                var result = await _viewRenderService.RenderToStringAsync("Home/Template1", user);
                return Content(result);
            }
    }

      4、别忘了Startup

    public void ConfigureServices(IServiceCollection services)
    {
          services.AddScoped<IViewRenderService, ViewRenderService>();
          services.AddMvc();
    }

    四、写在最后

      最后我只能说在ASP.NET Core中是万物皆DI啊,其实ASP.NET Core中的实现早就为我们想好了这些功能,只是改变了使用方式。

      GitHub:https://github.com/maxzhang1985/YOYOFx  如果觉还可以请Star下, 欢迎一起交流。

      .NET Core 开源学习群: 214741894  

  • 相关阅读:
    python中进程池和回调函数
    python网络编程中互斥锁与进程之间的通信
    python支持的进程与线程
    python网络编程之进程
    python网络编程之粘包
    python中socket编程
    python的异常处理
    webstorm(四):webstrom配置一键修复ESLint的报错
    JavaScript Array map() 方法
    ES6之Array.includes()函数
  • 原文地址:https://www.cnblogs.com/maxzhang1985/p/6268777.html
Copyright © 2011-2022 走看看