【问题标题】:Getting a Partial View's HTML from inside of the controller从控制器内部获取部分视图的 HTML
【发布时间】:2010-09-22 02:48:01
【问题描述】:

我为我的 mvc 网站开发了一个简单的机制,通过 jquery 拉入 html,然后填充指定的 div。一切都很好,看起来很酷。
我的问题是我现在正在我的控制器内部创建 html 标记(这在 VB.net 中很容易做到)我不想混淆关注点的分离。

是否可以使用自定义的“MVC 视图用户控件”来满足这种需求?我可以创建一个控件实例,传入模型数据并渲染到 html 吗?然后,渲染并传回调用浏览器将是一件简单的事情。

【问题讨论】:

  • 你不是在控制器中制作 HTML 标记来混淆关注点的分离吗?如果您需要重复执行某些操作,请查看使用 ascx 控件?
  • 视图不应该关心生成HTML吗?为什么你的标记在你的控制器中?
  • 2leggedspider.wordpress.com/2009/11/05/… 我只需要相同的功能。在我的 Json 对象中返回渲染的部分。这个链接对我有用

标签: html asp.net-mvc viewusercontrol


【解决方案1】:

这是一个适用于 ASP.Net MVC 1.0 的解决方案(许多声称适用于 beta 3 的解决方案不适用于 1.0),不会受到“服务器无法在 HTTP 标头被设置后设置内容类型”的影响发送的问题,可以从控制器(不仅仅是视图)中调用:

/// <summary>
/// Render a view into a string. It's a hack, it may fail badly.
/// </summary>
/// <param name="name">Name of the view, that is, its path.</param>
/// <param name="data">Data to pass to the view, a model or something like that.</param>
/// <returns>A string with the (HTML of) view.</returns>
public static string RenderPartialToString(string controlName, object viewData) {
    ViewPage viewPage = new ViewPage() { ViewContext = new ViewContext() };
    viewPage.Url = GetBogusUrlHelper();

    viewPage.ViewData = new ViewDataDictionary(viewData);
    viewPage.Controls.Add(viewPage.LoadControl(controlName));

    StringBuilder sb = new StringBuilder();
    using (StringWriter sw = new StringWriter(sb)) {
        using (HtmlTextWriter tw = new HtmlTextWriter(sw)) {
            viewPage.RenderControl(tw);
        }
    }

    return sb.ToString();
}

public static UrlHelper GetBogusUrlHelper() {
  var httpContext = HttpContext.Current;

  if (httpContext == null) {
    var request = new HttpRequest("/", Config.Url.ToString(), "");
    var response = new HttpResponse(new StringWriter());
    httpContext = new HttpContext(request, response);
  }

  var httpContextBase = new HttpContextWrapper(httpContext);
  var routeData = new RouteData();
  var requestContext = new RequestContext(httpContextBase, routeData);

  return new UrlHelper(requestContext);
}

这是一种静态方法,您可以将其放在您认为方便的地方。你可以这样称呼它:

string view = RenderPartialToString("~/Views/Controller/AView.ascx", someModelObject); 

【讨论】:

  • 这仍然是任何主要 MVC 项目中经常需要的东西。所以谢谢你的方法
  • 这似乎对我不起作用,因为我的部分使用填充到 ViewUserControl 的 Url 属性中的 UrlHelper 类,并且此方法似乎将该属性保留为空,导致我的异常助手来电。有什么建议吗?
  • 迈克尔,也许stackoverflow.com/questions/2031995/… 中的一些信息可以帮助你。我不记得 Url 有问题,我想我正在使用它。
  • Michael Lang,我为你的情况修好了。
  • 如何渲染 Razor 局部视图?
【解决方案2】:

我整理了一个粗略的框架,它允许您从 MVC Beta 中的控制器方法将视图呈现为字符串。这应该有助于暂时解决这个限制。

此外,我还为 MVC Beta 编写了一个类似 Rails 的 RJS javascript 生成框架。

查看http://www.brightmix.com/blog/how-to-renderpartial-to-string-in-asp-net-mvc 并告诉我您的想法。

【讨论】:

    【解决方案3】:

    你会像这样创建你的动作:

            public PartialViewResult LoginForm()
            {
                var model = // get model data from somewhere
                return PartialView(model);
            }

    并且该操作会将呈现的部分视图返回给您的 jquery 响应。

    您的 jquery 可能如下所示:

    $('#targetdiv').load('/MyController/LoginForm',function(){alert('complete!');});

    【讨论】:

      【解决方案4】:

      您应该使用 jquery 来填充您的 div(并在需要时创建新的 html 元素),并为 ActionResult 使用 Json 序列化。

      另一种方法是使用 jquery 来调用一些控制器/动作,但是 json 使用常规视图(aspx 或 ascx,webforms 视图引擎)来呈现内容,并且使用 jquery 只需将该 html 注入到某个 div 中。这是从 asp.net ajax 到 UpdatePanels 的一半......

      我可能会使用第一种方法,使用 json,您无需做更多工作,但它更加“优化”,因为您不会通过网络传输整个 html,只有序列化的对象。这是“大人物”(gmail、g docs、hotmail、..)的方式 - 大量使用 UI 操作的 JS 代码。

      如果你不需要ajax,那么你基本上有两种调用局部视图的方式:

      • html.renderpartial("ascx 的名称")
      • html.RenderAction(x=>x.ActionName) 来自 Microsoft.web.mvc(mvc 期货)

      【讨论】:

      • 你建议的第一种方法,是指使用局部视图吗?
      • 不,没有用于渲染内容的View,至少在服务器端没有,只有Json对象返回给jQuery,然后需要执行渲染:动态创建Divs,Spans,Tables,.. . 并用来自 json ajax 请求的数据填充它们。第二种方法在服务器上呈现整个 HTML 并将其返回给客户端。
      【解决方案5】:

      在谷歌大量挖掘之后,我找到了答案。 您无法轻松访问视图输出的 html。

      http://ayende.com/Blog/archive/2008/11/11/another-asp.net-mvc-bug-rendering-views-to-different-output-source.aspx

      【讨论】:

        【解决方案6】:

        我为我正在开发的应用程序做了类似的事情。我有返回渲染内容的部分视图,可以使用它们的 REST 路径或使用:

        <% Html.RenderAction("Action", "Controller"); %>
        

        然后在我的实际显示 HTML 中,我有一个由 jQuery 填充的 DIV:

        <div class="onload">/controller/action</div>
        

        jQuery 看起来像这样:

        <script type="text/javascript">
            $.ajaxSetup({ cache: false });
        
            $(document).ready(function () {
                $('div.onload').each(function () {
                    var source = $(this).html();
                    if (source != "") {
                        $(this).load(source);
                    }
                });
            });
        </script>
        

        这会扫描与“onload”类匹配的所有 DIV,并从其内容中读取 REST 路径。然后它对该 REST 路径执行 jQuery.load 并使用结果填充 DIV。

        抱歉,我得搭车回家了。如果您希望我详细说明,请告诉我。

        【讨论】:

          【解决方案7】:

          您有多种选择。

          在控制器中为视图创建一个 MVC 视图用户控件和操作处理程序。要渲染视图,请使用

          <% Html.RenderPartial("MyControl") %>
          

          在这种情况下,您的操作处理程序需要将模型数据传递给视图

          public ActionResult MyControl ()
          {
              // get modelData
          
              render View (modelData);
          }
          

          您的另一个选择是从父页面传递模型数据。在这种情况下,您不需要操作处理程序,并且模型类型与父模型类型相同:

          <% Html.RenderPartial("MyControl", ViewData.Model) %>
          

          如果您的用户控件有自己的数据类型,您也可以在页面中构建它

          在 MyControl.ascx.cs 中:

          public class MyControlViewData
          {
              public string Name { get; set; }
              public string Email { get; set; }
          }
          
          public partial class MyControl : System.Web.Mvc.ViewUserControl <MyControlViewData>
          {
          }
          

          并且在你的页面中你可以初始化你的控件的数据模型:

          <% Html.RenderPartial("MyControl", new MyControlViewData ()
             {
                  Name= ViewData.Model.FirstName,
                  Email = ViewData.Model.Email,
             });
           %>
          

          【讨论】:

          • 这不会让您以编程方式访问由视图/部分权利生成的 HTML?我不明白这是如何回答这个问题的......虽然我确实从答案中学到了东西,所以我很欣赏它作为一个高质量的回答。
          • 此回复未回答所提出的问题。如何从控制器内部获取部分视图的 HTML?
          • 您是否要在将 HTML 发送回浏览器之前对其进行捕获/修改?
          • 当它不回答问题时,为什么这是公认的答案?
          【解决方案8】:

          在 Rails 中,这称为渲染局部视图,您可以使用 render :partial =&gt; 'yourfilename' 来完成。我相信 ASP.NET MVC 有类似的RenderPartial 方法,但是我找不到 MVC 的官方文档来确认或否认这样的事情。

          【讨论】:

          • 我一直在谷歌上搜索这个问题;自 MVC 进入测试版以来,似乎有一些方法已被破坏/删除。仍在寻找答案
          【解决方案9】:

          这很简单,您只需创建一个强类型的局部视图(或用户控件),然后在您的控制器中像这样:

          public PartialViewResult yourpartialviewresult()
          {
              var yourModel
              return PartialView("yourPartialView", yourModel);
          }
          

          那么您可以随时使用 JQuery 执行请求:

          $.ajax({
              type: 'GET',
              url: '/home/yourpartialviewresult',
              dataType: 'html', //be sure to use html dataType
              contentType: 'application/json; charset=utf-8',
              success: function(data){
                   $(container).html(data);
              },
              complete: function(){ }
           });    
          

          【讨论】:

            【解决方案10】:

            我发现这一行代码可以完美运行。 orderModel 是我的模型对象。就我而言,我有一个辅助方法,我必须在其中合并部分视图的 html。

            System.Web.Mvc.Html.PartialExtensions.Partial(html, "~/Views/Orders/OrdersPartialView.cshtml", orderModel).ToString();
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2013-11-13
              • 2015-11-30
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多