ASP.NET MVC Razor : 컨트롤러 작업 내에서 Razor 부분보기의 HTML을 렌더링하는 방법


97

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();
    }

1
지금까지 예외를 생성하는 코드를 보여줄 수 있습니까?
— mlibby

답변:


154
@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();
    }
}

예, 이것이 뷰 내부에서 부분 뷰를 렌더링하는 방법입니다. 하지만 컨트롤러 액션 안에서 어떻게 렌더링할까요?
— Peter Stegnar 2010

대단한 지금입니다! Razon 및 ASP 표기법과 함께 작동합니다.
— Peter Stegnar 2010

2
하나의 하위 질문 : 다른 컨트롤러 범위에있는 뷰를 현재 뷰로 렌더링하는 방법은 무엇입니까? "EmailController"범위 (이메일보기 폴더)에 있다고 가정 해 보겠습니다.
— Peter Stegnar 2010

1
이것은 훌륭한 솔루션이었습니다. 나는 이메일에 대한 정확한 필요가 있었고 이것을 사용하기로 결정했습니다.
— uadrive

2
@AmeyKhadatkar : 아니요. jquery는 클라이언트 측이며 뷰는 브라우저로 전송되기 전에 서버 측에서 생성됩니다.
— jgauffin 2015

8

적절한 답변이 이미 주어졌지만 MVC 컨트롤러 클래스에서 사용할 수있는 도우미 메서드없이 사용할 수있는 덜 장황한 솔루션을 제안하고 싶습니다. "RazorEngine"이라는 타사 라이브러리를 사용하면 .Net 파일 IO를 사용하여 razor 파일의 내용을 가져오고 호출 할 수 있습니다.

string html = Razor.Parse(razorViewContentString, modelObject);

여기에서 타사 라이브러리를 가져옵니다 .


5

당신은 또한 사용할 수 RenderView Controller extension에서 여기 ( 소스 )

다음과 같이 사용하십시오.

public ActionResult Do() {
var html = this.RenderView("index", theModel);
...
}

면도기 및 웹 양식 뷰 엔진에서 작동합니다.


링크를 확인했습니다. @ChurkNorris는 버전 2.0 (현재 최신 릴리스 2012 년 3 월 12 일) 의 상용 제품인 ASP.net MVC Awesome 의 저자입니다 . 버전 1.9 (2011 년 6 월 9 일 최신 릴리스)는 여전히 오픈 소스이지만 더 이상 개발되지 않을 것입니다. 1.9의 포크가 있습니까?
— Joel Purra

@Omu : RenderView가 무효입니다. msdn.microsoft.com/en-us/library/…
— roland

@Roland 이것은 사용자 지정 컨트롤러 확장입니다
— Omu

1

누군가 다른 컨트롤러에 대해 어떻게해야할지 궁금해하는 것을 보았습니다.

제 경우에는 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 객체에서 사용할 초기 상태로 되돌립니다.


1

훌륭한 코드; 약간의 힌트 : 뷰 모델뿐만 아니라 더 많은 데이터를 우회해야하는 경우 ..

 if (model is ViewDataDictionary)
 {
     controller.ViewData = model as ViewDataDictionary;
 } else {
     controller.ViewData.Model = model;
 }

2
당신은 당신의 대답 완료되지 않은
— poohdedoo

0

@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)

1
@ Html.Partial (string partialViewName, object model, ViewDataDictionary viewData) 사용과의 차이점을 설명해 주시겠습니까? HtmlHelper가 필요하므로 어떤 이점이 있습니까?
— bkqc
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.