MVC3 Razor'da, bir eylemin içinde işlenmiş bir görünümün html'sini nasıl alabilirim?


90

Bir görünümün oluşturulmuş html'sini bir eylemin içine almayı bilen var mı?

Bunun gibi bir şey mi:

public ActionResult Do()
{
    var html = RenderView("hello", model);
...
}

Yanıtlar:


152

Bir sınıfta statik bir metot kullanıyorum. Utilities.CommonGörünümleri sürekli olarak JSON nesnelerinin özellikleri olarak istemciye geri gönderiyorum, bu yüzden onları bir dizeye dönüştürme ihtiyacım vardı. İşte gidiyorsun:

public static string RenderPartialViewToString(Controller controller, string viewName, object model)
{
    controller.ViewData.Model = model;
    using (StringWriter sw = new StringWriter())
    {
        ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(controller.ControllerContext, viewName);
        ViewContext viewContext = new ViewContext(controller.ControllerContext, viewResult.View, controller.ViewData, controller.TempData, sw);
        viewResult.View.Render(viewContext, sw);

        return sw.ToString();
    }
}

Bu sadece değiştirmek, tam manzarasına yanı sıra kısmi görünümleri için çalışacaktır ViewEngines.Engines.FindPartialViewiçin ViewEngines.Engines.FindView.


14
FindView, masterNameboş olarak belirteceğiniz başka bir parametreye ( ) ihtiyaç duyar . Ayrıca yöntemin geçerli denetleyici örneğinde çağrılması ve modelin bu çağrıdan önce atanması durumunda controller.ViewData.Model'i kaydetmenizi ve geri yüklemenizi (render ettikten sonra) öneririm.
Andrei Rînea

4
Ayrıca viewResult.ViewEngine.ReleaseView (controller.ControllerContext, viewResult.View)
sjmeverett

3
Harika çalışıyor, ancak canlı kodumda istisnaları yakalamak ve oluşturmak istemem.
pauloya

3
Eğer onu denetleyicinin içinden çağırıyorsanız this, denetleyici argümanı olarak iletin. RenderPartialViewToString(this, "index", viewModel). Basitçe görünüm motorunu çağırmanın ve bir dizeyi geri almanın daha kolay bir yolu olmadığını düşünüyorum, ancak ASP.NET'te görünüm motorunun görünümü derlemek için denetleyici örneğine başvurması gerekiyor. Şimdi bir nodeJS geliştiricisiyim ve düğümdeki motorları görüntüle, manuel olarak veya express gibi bir MVC çerçevesiyle çağırabileceğiniz ayrı modüllerdir .
Chev

5
@PauloManuelSantos Size katılıyorum. Bunu yıllar önce yazdım ve yanıta hata işleme ekleyerek ne düşündüğümü bilmiyorum. Try / catch'i hariç tutmak için yanıtı güncelledim. Geri dönüşünüz için teşekkür ederiz.
Chev

4

Yukarıda @Chev tarafından kabul edilen cevap iyi, ancak yalnızca belirli bir görüşün değil, belirli bir eylemin sonucunu sunmak istedim .

Ayrıca, bir model enjekte etmek yerine parametreleri bu eyleme geçirebilmem gerekiyordu.

Bu yüzden, denetleyicilerimin temel sınıfına koyduğum kendi yöntemimi buldum (hepsinin kullanımına sunuyorum):

    protected string RenderViewResultAsString(ViewResult viewResult)
    {
        using (var stringWriter = new StringWriter())
        {
            this.RenderViewResult(viewResult, stringWriter);

            return stringWriter.ToString();
        }
    }

    protected void RenderViewResult(ViewResult viewResult, TextWriter textWriter)
    {
        var viewEngineResult = this.ViewEngineCollection.FindView(
            this.ControllerContext, 
            viewResult.ViewName, 
            viewResult.MasterName);
        var view = viewEngineResult.View;

        try
        {
            var viewContext = new ViewContext(
                this.ControllerContext, 
                view, 
                this.ViewData, 
                this.TempData, 
                textWriter);

            view.Render(viewContext, textWriter);
        }
        finally
        {
            viewEngineResult.ViewEngine.ReleaseView(this.ControllerContext, view);
        }
    }

FooBir model nesnesini ve diğer bazı parametreleri alan ve birlikte hangi görünümün kullanılacağını etkileyen adında bir eylemim olduğunu varsayalım :

    public ViewResult Foo(MyModel model, int bar)
    {
        if (bar == 1)
            return this.View("Bar1");
        else
            return this.View("Bar2", model);
    }

Şimdi, eylem çağrısının sonucunu almak istersem , yöntemi çağırarak Foobasitçe alabilir ve ardından HTML metnini almak için çağrı yapabilirim :ViewResultFooRenderViewResultAsString

    var viewResult = this.Foo(model, bar);

    var html = this.RenderViewResultAsString(viewResult);
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.