ASP.NET보기 엔진에서 지정된 부분보기의 HTML을 생성하는 방법 은 알려져 있습니다.
그러나이 기능이 면도기 부분보기에서 사용되면 부분보기가 “UserControl”에서 파생되지 않는다는 예외가 있기 때문에 작동하지 않습니다.
Razor 부분보기를 지원하도록 렌더링을 수정하는 방법은 무엇입니까?
이 부분보기에서 이메일을 생성하기 때문에 이것이 필요합니다 …
최신 정보:
실패한 코드 (@mcl) :
public string RenderPartialToString(string controlName, object viewData)
{
ViewPage viewPage = new ViewPage() { ViewContext = new ViewContext() };
viewPage.Url = this.GetUrlHelper();
string fullControlName = "~/Views/Email/" + controlName + ".ascx";
viewPage.ViewData = new ViewDataDictionary(viewData);
viewPage.Controls.Add(viewPage.LoadControl(fullControlName));
StringBuilder sb = new StringBuilder();
using (StringWriter sw = new StringWriter(sb))
{
using (HtmlTextWriter tw = new HtmlTextWriter(sw))
{
viewPage.RenderControl(tw);
}
}
return sb.ToString();
}
답변
@Html.Partial("nameOfPartial", Model)
최신 정보
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();
}
}
답변
적절한 답변이 이미 주어졌지만 MVC 컨트롤러 클래스에서 사용할 수있는 도우미 메서드없이 사용할 수있는 덜 장황한 솔루션을 제안하고 싶습니다. “RazorEngine”이라는 타사 라이브러리를 사용하면 .Net 파일 IO를 사용하여 razor 파일의 내용을 가져오고 호출 할 수 있습니다.
string html = Razor.Parse(razorViewContentString, modelObject);
여기에서 타사 라이브러리를 가져옵니다 .
답변
당신은 또한 사용할 수 RenderView Controller extension
에서 여기
( 소스 )
다음과 같이 사용하십시오.
public ActionResult Do() {
var html = this.RenderView("index", theModel);
...
}
면도기 및 웹 양식 뷰 엔진에서 작동합니다.
답변
누군가 다른 컨트롤러에 대해 어떻게해야할지 궁금해하는 것을 보았습니다.
제 경우에는 Views / Email 폴더에 모든 이메일 템플릿이 있었지만 뷰가 연결된 컨트롤러에서 전달하도록 수정할 수 있습니다.
public static string RenderViewToString(Controller controller, string viewName, object model)
{
var oldController = controller.RouteData.Values["controller"].ToString();
if (controller.GetType() != typeof(EmailController))
controller.RouteData.Values["controller"] = "Email";
var oldModel = controller.ViewData.Model;
controller.ViewData.Model = model;
try
{
using (var sw = new StringWriter())
{
var viewResult = ViewEngines.Engines.FindView(controller.ControllerContext, viewName,
null);
var viewContext = new ViewContext(controller.ControllerContext, viewResult.View, controller.ViewData, controller.TempData, sw);
viewResult.View.Render(viewContext, sw);
//Cleanup
controller.ViewData.Model = oldModel;
controller.RouteData.Values["controller"] = oldController;
return sw.GetStringBuilder().ToString();
}
}
catch (Exception ex)
{
Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
throw ex;
}
}
본질적으로 이것이하는 일은 AccountController와 같은 컨트롤러를 가져 와서 코드가 Views/Email
폴더 에서 보이도록 EmailController라고 생각하도록 수정하는 것 입니다. FindView
메서드가 매개 변수로 직선 경로를 사용하지 않기 때문에이 작업을 수행해야 합니다 ControllerContext
.
문자열 렌더링이 완료되면 AccountController를 Response 객체에서 사용할 초기 상태로 되돌립니다.
답변
훌륭한 코드; 약간의 힌트 : 뷰 모델뿐만 아니라 더 많은 데이터를 우회해야하는 경우 ..
if (model is ViewDataDictionary)
{
controller.ViewData = model as ViewDataDictionary;
} else {
controller.ViewData.Model = model;
}
답변
@jgauffin 답변을 HtmlHelper 확장으로 빌리기 :
public static class HtmlHelperExtensions
{
public static MvcHtmlString RenderPartialViewToString(
this HtmlHelper html,
ControllerContext controllerContext,
ViewDataDictionary viewData,
TempDataDictionary tempData,
string viewName,
object model)
{
viewData.Model = model;
string result = String.Empty;
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);
result = sw.GetStringBuilder().ToString();
}
return MvcHtmlString.Create(result);
}
}
면도기보기에서의 사용법 :
Html.RenderPartialViewToString(ViewContext, ViewData, TempData, "Search", Model)
답변
