新しいMVC6プロジェクトを作成し、新しいサイトを構築しました。目的は、ビューのレンダリング結果を取得することです。次のコードを見つけましたが、ControllerContext
とViewEngines
が見つからないため、機能しません。
これが私が書き直したいコードです:
protected string RenderPartialViewToString(string viewName, object model)
{
if (string.IsNullOrEmpty(viewName))
viewName = ControllerContext.RouteData.GetRequiredString("action");
ViewData.Model = model;
using (StringWriter sw = new StringWriter())
{
ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(ControllerContext, viewName);
ViewContext viewContext = new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, sw);
viewResult.View.Render(viewContext, sw);
return sw.GetStringBuilder().ToString();
}
}
pdate:APIが2015年から変更されているため、.Net Core 2.xで動作するように更新しています!
まず最初に、ASP.Net MVCコアに付属する組み込みの依存関係注入を利用して、ビューを手動でレンダリングするために必要なICompositeViewEngine
オブジェクトを取得できます。たとえば、コントローラは次のようになります。
public class MyController : Controller
{
private ICompositeViewEngine _viewEngine;
public MyController(ICompositeViewEngine viewEngine)
{
_viewEngine = viewEngine;
}
//Rest of the controller code here
}
次に、実際にビューをレンダリングするために必要なコード。内部的に非同期呼び出しを行うため、これはasync
メソッドになっていることに注意してください。
private async Task<string> RenderPartialViewToString(string viewName, object model)
{
if (string.IsNullOrEmpty(viewName))
viewName = ControllerContext.ActionDescriptor.ActionName;
ViewData.Model = model;
using (var writer = new StringWriter())
{
ViewEngineResult viewResult =
_viewEngine.FindView(ControllerContext, viewName, false);
ViewContext viewContext = new ViewContext(
ControllerContext,
viewResult.View,
ViewData,
TempData,
writer,
new HtmlHelperOptions()
);
await viewResult.View.RenderAsync(viewContext);
return writer.GetStringBuilder().ToString();
}
}
メソッドを呼び出すには、次のように簡単です。
public async Task<IActionResult> Index()
{
var model = new TestModel
{
SomeProperty = "whatever"
}
var renderedView = await RenderPartialViewToString("NameOfView", model);
//Do what you want with the renderedView here
return View();
}
リリースされたdotnetコア1.0は変更され、上記のコードのこのバージョンは1.0 RTMで動作します。
protected string RenderPartialViewToString(string viewName, object model)
{
if (string.IsNullOrEmpty(viewName))
viewName = ControllerContext.ActionDescriptor.DisplayName;
ViewData.Model = model;
using (StringWriter sw = new StringWriter())
{
var engine = _serviceProvider.GetService(typeof(ICompositeViewEngine)) as ICompositeViewEngine; // Resolver.GetService(typeof(ICompositeViewEngine)) as ICompositeViewEngine;
ViewEngineResult viewResult = engine.FindView(ControllerContext, viewName, false);
ViewContext viewContext = new ViewContext(
ControllerContext,
viewResult.View,
ViewData,
TempData,
sw,
new HtmlHelperOptions() //Added this parameter in
);
//Everything is async now!
var t = viewResult.View.RenderAsync(viewContext);
t.Wait();
return sw.GetStringBuilder().ToString();
}
}
これらの使用法は、このコードをコンパイルするために必要です。
using System.IO;
using Microsoft.AspNetCore.Mvc.ViewEngines;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
また、コントローラーコンストラクターにDIインターフェイスを追加する必要がありました。
IServiceProvider serviceProvider
私のアカウントコンストラクターは次のようになります。
public AccountController(
UserManager<ApplicationUser> userManager,
SignInManager<ApplicationUser> signInManager,
IEmailSender emailSender,
ISmsSender smsSender,
ILoggerFactory loggerFactory,
IServiceProvider serviceProvider)
{
_userManager = userManager;
_signInManager = signInManager;
_emailSender = emailSender;
_smsSender = smsSender;
_logger = loggerFactory.CreateLogger<AccountController>();
_serviceProvider = serviceProvider;
}
Martin Tomesによって提供されたソリューションは私にとってはうまくいきましたが、私は置き換える必要がありました:
ViewEngineResult viewResult = engine.FindView(ControllerContext, viewName, false);
と
ViewEngineResult viewResult = engine.GetView(_env.WebRootPath, viewName, false);
また、コントローラのコンストラクタで追加する必要がありました
private IHostingEnvironment _env;
public AccountController(IHostingEnvironment env)
{
_env = env;
}
Martin Tomesによる解決策はうまく機能します。私の変更:serviceProviderを削除し、DIを介してコンストラクターでICompositeViewEngineを取得しました。コンストラクタは次のようになります。
private readonly ICompositeViewEngine _viewEngine;
public AccountController(
UserManager<ApplicationUser> userManager,
SignInManager<ApplicationUser> signInManager,
IEmailSender emailSender,
ISmsSender smsSender,
ILoggerFactory loggerFactory,
ICompositeViewEngine viewEngine)
{
_userManager = userManager;
_signInManager = signInManager;
_emailSender = emailSender;
_smsSender = smsSender;
_logger = loggerFactory.CreateLogger<AccountController>();
_viewEngine = viewEngine;;
}
そして、置きます
ViewEngineResult viewResult = _viewEngine.FindView(ControllerContext, viewName, false);
の代わりに
var engine = _serviceProvider.GetService(typeof(ICompositeViewEngine)) as ICompositeViewEngine; // Resolver.GetService(typeof(ICompositeViewEngine)) as ICompositeViewEngine;
ViewEngineResult viewResult = engine.FindView(ControllerContext, viewName, false);