简体   繁体   English

在Controller ASP.NET MVC 4中调用RenderAction用于仪表板(多)视图

[英]Calling RenderAction in Controller ASP.NET MVC 4 For Dashboard (Multi) View

I have a template HTML string, which at various unknown points has {{Url}} placeholders in it, which relate to certain controller/actions in my application. 我有一个模板HTML字符串,它在各个未知点都有{{Url}}个占位符,它与我的应用程序中的某些控制器/操作有关。 What I need to do is render the html into these placeholders, before rendering the final html in a view. 我需要做的是在视图中渲染最终的html之前将html渲染到这些占位符中。

In a view I can simply call Html.RenderAction("Action","Controller") which returns the string I need. 在视图中,我可以简单地调用Html.RenderAction("Action","Controller") ,它返回我需要的字符串。 However , I need to call this method in the controller code , for example (This is simplified): 但是 ,我需要在控制器代码中调用此方法,例如(这是简化的):

In "Dashboard" Controller: 在“仪表板”控制器中:

var templateHtml = GetTemplateHtml();

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

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

Then in the "Dashboard View": 然后在“仪表板视图”中:

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

How do I call "RenderAction" to get the Rendered HTML string in the controller? 如何调用“RenderAction”来获取控制器中的Rendered HTML字符串?

EDIT: There seems to be confusion over what I am trying to achieve. 编辑:似乎对我想要实现的目标感到困惑。 Basically, we need administrators to be able to create an HTML template, which will effectively have frames for various different pages of our application. 基本上,我们需要管理员能够创建一个HTML模板,它将有效地为我们的应用程序的各种不同页面提供框架。 Iframes would work, but we'd much prefer to have all the HTML built on the server. iframe可以工作,但我们更喜欢在服务器上构建所有HTML。

I think you want HtmlHelper.Action rather than RenderAction . 我想你想要HtmlHelper.Action而不是RenderAction RenderAction writes the content to the response stream. RenderAction将内容写入响应流。 Action returns it as a string. Action将其作为字符串返回。

http://msdn.microsoft.com/en-us/library/ee721266(v=vs.108).aspx 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在ChildActionExtensions类中定义,该类位于System.Web.Mvc.Html命名空间中,因此您的控制器代码需要使用该命名空间。

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. Action将Html作为字符串返回,而RenderAction返回void,因为RenderAction将其Html输出直接写入与父文档内联的当前响应流。 This is why it works from a view but not a controller. 这就是它从视图而不是控制器工作的原因。

To create an HtmlHelper instance in MVC 4 you can use this: 要在MVC 4中创建HtmlHelper实例,您可以使用:

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). 正如其他评论家在相关的SO问题上所说的那样,这并不是真正的意图(通过hacky方式来实现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. 如果可以的话,最好重构为更多的MVC,尽管有时我意识到这不是一个选择。

So, found a solution, but it is very hacky and there simply must be a cleaner way! 所以,找到了一个解决方案,但它非常hacky,而且必须有一个更清洁的方式!

I have a shared partial view "_view", which only has this in it: 我有一个共享的部分视图“_view”,其中只有这个:

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

I have used the code from this blog: http://approache.com/blog/render-any-aspnet-mvc-actionresult-to/ to write an extension method for the ActionResult class. 我使用了这个博客中的代码: http ://approache.com/blog/render-any-aspnet-mvc-actionresult-to/为ActionResult类编写扩展方法。

Then in my controller I do this: 然后在我的控制器中我这样做:

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

//Repeat for other pages

return View();

Below the code for the extension method I used from the blog: 在我从博客中使用的扩展方法的代码下面:

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

I think you need partial views you can render partial view in your main view 我认为你需要局部视图,你可以在主视图中渲染局部视图

 @Html.Partial("myPartailView")

for detail check link 详细检查链接

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

To Render view as string you can follow following approach: 要将视图渲染为字符串,您可以遵循以下方法:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM