4

我有一个模板 HTML 字符串,它在各个未知点都有 {{Url}} 占位符,这与我的应用程序中的某些控制器/操作有关。我需要做的是将 html 渲染到这些占位符中,然后在视图中渲染最终的 html。

在一个视图中,我可以简单地调用Html.RenderAction("Action","Controller")它返回我需要的字符串。 但是,我需要在控制器代码中调用这个方法,例如(这是简化的):

在“仪表板”控制器中:

var templateHtml = GetTemplateHtml();

//The following line doesn't compile
var html = Html.RenderAction("Index","PowerAnalysisDashpart");

ViewBag.Html = templateHtml.Replace("{{PowerAnalysisDashpart}}",html)

然后在“仪表板视图”中:

<div id="content">
    @Html.Raw(ViewBag.Html)
</div>

如何调用“RenderAction”来获取控制器中的渲染 HTML 字符串?

编辑: 似乎对我想要实现的目标感到困惑。基本上,我们需要管理员能够创建一个 HTML 模板,该模板将有效地为我们应用程序的各种不同页面提供框架。iframe 可以工作,但我们更希望将所有 HTML 构建在服务器上。

4

4 回答 4

8

I think you want HtmlHelper.Action rather than RenderAction. RenderAction writes the content to the response stream. Action returns it as a string.

http://msdn.microsoft.com/en-us/library/ee721266(v=vs.108).aspx

Action is defined in the ChildActionExtensions class which lives in the System.Web.Mvc.Html namespace so your controller code would need to be using that namespace.

Action returns Html as a string whereas RenderAction returns void because RenderAction writes its Html output directly to the current response stream inline with the parent document. This is why it works from a view but not a controller.

To create an HtmlHelper instance in MVC 4 you can use this:

HtmlHelper helper = new HtmlHelper(new ViewContext(ControllerContext, new WebFormView(ControllerContext, "Index"), new ViewDataDictionary(), new TempDataDictionary(), new StringWriter()), new ViewPage());

As other commentors have said on related SO questions, this is not really as intended (which is obvious by the hacky way you have to instaniate the HtmlHelper). I'm not sure it's much better than your alternative solution. Better to refactor to be more MVC like if you can, although I realise sometimes that is not an option.

于 2013-09-03T11:25:28.703 回答
2

所以,找到了一个解决方案,但它非常hacky,必须有一个更清洁的方法!

我有一个共享的局部视图“_view”,其中只有这个:

@{ Html.RenderAction("Index",(string)ViewBag.Controller); }

我使用了此博客中的代码:http : //approache.com/blog/render-any-aspnet-mvc-actionresult-to/ 为 ActionResult 类编写了扩展方法。

然后在我的控制器中我这样做:

var templateHtml = GetTemplateHtml();
ViewBag.Controller = "PowerAnalysis";
var html = View("_view").Capture(ControllerContext);
ViewBag.Html = htmlTemplate.Replace("{{PowerAnalysis}}", html);

//Repeat for other pages

return View();

下面是我在博客中使用的扩展方法的代码:

public class ResponseCapture : IDisposable {
        private readonly HttpResponseBase response;
        private readonly TextWriter originalWriter;
        private StringWriter localWriter;
        public ResponseCapture(HttpResponseBase response) {
            this.response = response;
            originalWriter = response.Output;
            localWriter = new StringWriter();
            response.Output = localWriter;
        }
        public override string ToString() {
            localWriter.Flush();
            return localWriter.ToString();
        }
        public void Dispose() {
            if (localWriter != null) {
                localWriter.Dispose();
                localWriter = null;
                response.Output = originalWriter;
            }
        }
    }


    public static class ActionResultExtensions {
        public static string Capture(this ActionResult result, ControllerContext controllerContext) {
            using (var it = new ResponseCapture(controllerContext.RequestContext.HttpContext.Response)) {
                result.ExecuteResult(controllerContext);
                return it.ToString();
            }
        }
    }
于 2013-09-03T13:31:56.313 回答
-2

我认为您需要部分视图,您可以在主视图中呈现部分视图

 @Html.Partial("myPartailView")

详细检查链接

http://www.codeproject.com/Tips/617361/Partial-View-in-ASP-NET-MVC-4

于 2013-09-03T10:05:32.177 回答
-2

要将视图呈现为字符串,您可以遵循以下方法:

var html = RenderRazorViewToString("viewName",model); //pass model if you are binding model in view


// It will return your view as string
[NonAction]
public string RenderRazorViewToString(string viewName, object model)
{
    ViewData.Model = model;
    using (var sw = new StringWriter())
    {
        var viewResult = ViewEngines.Engines.FindPartialView(ControllerContext, viewName);
        var viewContext = new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, sw);
        viewResult.View.Render(viewContext, sw);
        viewResult.ViewEngine.ReleaseView(ControllerContext, viewResult.View);
        return sw.GetStringBuilder().ToString();
    }
}
于 2013-09-03T10:32:00.660 回答