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.