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  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM