1. ホーム
  2. c#

[解決済み] .NET Coreでビューを文字列で返す

2023-02-18 10:11:36

質問

ASP.NETでビューを文字列に変換する方法をいくつか見つけましたが、.NET Coreで実行できるように変換することができません。

public static string RenderViewToString(this Controller controller, string viewName, object model)
{
    var context = controller.ControllerContext;
    if (string.IsNullOrEmpty(viewName))
        viewName = context.RouteData.GetRequiredString("action");

    var viewData = new ViewDataDictionary(model);

    using (var sw = new StringWriter())
    {
        var viewResult = ViewEngines.Engines.FindPartialView(context, viewName);
        var viewContext = new ViewContext(context, viewResult.View, viewData, new TempDataDictionary(), sw);
        viewResult.View.Render(viewContext, sw);

        return sw.GetStringBuilder().ToString();
    }
}

を使ってControllerから呼び出せることを想定しています。

var strView = this.RenderViewToString("YourViewName", yourModel);

上記を.NET Coreで実行しようとすると、コンパイルエラーがたくさん出ます。

私は.NET Coreで動作するように変換しようとしましたが、失敗しました、誰か必要な using .. と必要な "dependencies": { "Microsoft.AspNetCore.Mvc": "1.1.0", ... }, で使用される project.json .

その他のサンプルコード ここで はこちら はこちら

ノート ビューを変換するためのソリューションが必要です。 string に変換するソリューションを必要とします。

どのように解決するのですか?

おかげさまで パリス・ポリゾス と彼の 記事 .

元の投稿が何らかの理由で削除された場合に備えて、彼のコードをここに再投稿しています。

作成 Service ファイルに viewToString.cs を以下のようなコードで記述します。

using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Abstractions;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.Razor;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Routing;
     
namespace WebApplication.Services
{
        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();
                }
            }
        }
}

2. サービスを Startup.cs ファイルとして追加します。

using WebApplication.Services;

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

3. 追加 "preserveCompilationContext": truebuildOptions の中に project.json というように、ファイルは次のようになります。

{
    "version": "1.0.0-*",
    "buildOptions": {
    "debugType": "portable",
    "emitEntryPoint": true,
    "preserveCompilationContext": true
    },
    "dependencies": {
    "Microsoft.AspNetCore.Server.Kestrel": "1.0.1",
    "Microsoft.AspNetCore.Mvc": "1.0.1"
    },
    "frameworks": {
    "netcoreapp1.0": {
        "dependencies": {
        "Microsoft.NETCore.App": {
            "type": "platform",
            "version": "1.0.1"
        }
        },
        "imports": "dnxcore50"
    }
    }
}

4. あなたを定義する model を、例えば

public class InviteViewModel {
    public string   UserId {get; set;}
    public string   UserName {get; set;}
    public string   ReferralCode {get; set;}
    public int  Credits {get; set;}
}

5. あなたの Invite.cshtml を例えば

@{
    ViewData["Title"] = "Contact";
}
@ViewData["Title"].
user id: @Model.UserId

6. Controller :

a. 以下を冒頭で定義する。

private readonly IViewRenderService _viewRenderService;

public RenderController(IViewRenderService viewRenderService)
{
    _viewRenderService = viewRenderService;
}

b. 以下のように、モデル付きビューを呼び出して返します。

var result = await _viewRenderService.RenderToStringAsync("Email/Invite", viewModel);
return Content(result);

c. FULLコントローラの例ですが、こんな感じでしょうか。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using WebApplication.Services;

namespace WebApplication.Controllers
{
    [Route("render")]
    public class RenderController : Controller
    {
        private readonly IViewRenderService _viewRenderService;

        public RenderController(IViewRenderService viewRenderService)
        {
            _viewRenderService = viewRenderService;
        }

    [Route("invite")]
    public async Task<IActionResult> RenderInviteView()
    {
        ViewData["Message"] = "Your application description page.";
        var viewModel = new InviteViewModel
        {
            UserId = "cdb86aea-e3d6-4fdd-9b7f-55e12b710f78",
            UserName = "Hasan",
            ReferralCode = "55e12b710f78",
            Credits = 10
        };
     
        var result = await _viewRenderService.RenderToStringAsync("Email/Invite", viewModel);
        return Content(result);
    }

    public class InviteViewModel {
        public string   UserId {get; set;}
        public string   UserName {get; set;}
        public string   ReferralCode {get; set;}
        public int  Credits {get; set;}
    } 
}