【问题标题】:asp.net mvc utilize view for rendering, without creating a controller actionasp.net mvc 利用视图进行渲染,无需创建控制器操作
【发布时间】:2010-10-29 22:19:30
【问题描述】:

我需要生成特定于 Customer 对象的 html(用于电子邮件正文)
我想制作一个 View 来获取 Customer 对象并呈现适当的文本。

有没有一种方法可以调用视图并获取渲染输出而不将其与控制器操作相关联?

理想情况下,我会在 pseydocode 中做这样的事情

customer = new Customer();
view = new GetCustomerEmailBodyView(customer);
string htmlBody = view.SomeFunctionToRenderViewAndGetOutput()

我找到了一种解决方案来获取视图here 的 HTML,该视图具有返回 StringResult(从 ViewResult 继承)的操作,而不是公开 Html 属性的 ActionResult。
但是我仍然需要进行自定义操作才能调用它,而且我不喜欢它依赖于 ControllerContext 从而难以测试它的事实。

我对 MVC 主体的要求是什么?对于这种情况,我的代码应该如何构建?

【问题讨论】:

    标签: asp.net-mvc model-view-controller asp.net-mvc-3


    【解决方案1】:

    来自here的原码

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

    【讨论】:

      【解决方案2】:

      您是说您希望某个程序能够在根本不处于控制器上下文中的情况下利用视图,或者您是说您希望能够从控制器内将视图呈现为字符串,而无需调用其他控制器?

      对于前者,我无法提供太多帮助,但对于后者,我们在所有其他控制器继承的基本控制器类型中都有这个方法:

          /// <summary>
          /// Generates a string based on the given PartialViewResult.
          /// </summary>
          /// <param name="partialViewResult"></param>
          /// <returns></returns>
          protected internal string RenderPartialViewToString(ViewResultBase partialViewResult)
          {
              Require.ThatArgument(partialViewResult != null);
              var context = ControllerContext;
              Require.That(context != null);
              using (var sw = new StringWriter())
              {
                  if (string.IsNullOrEmpty(partialViewResult.ViewName))
                  {
                      partialViewResult.ViewName = context.RouteData.GetRequiredString("action");
                  }
                  ViewEngineResult result;
                  if (partialViewResult.View == null)
                  {
                      result = partialViewResult.ViewEngineCollection.FindPartialView(context, partialViewResult.ViewName);
                      Require.That(result.View != null,
                                   () => new InvalidOperationException(
                                             "Unable to find view. Searched in: " +
                                             string.Join(",", result.SearchedLocations)));
                      partialViewResult.View = result.View;
                  }
      
                  var view = partialViewResult.View;
                  var viewContext = new ViewContext(context, view, partialViewResult.ViewData,
                                                    partialViewResult.TempData, sw);
                  view.Render(viewContext, sw);
                  return sw.ToString();
              }
          }
      

      用法:

      public ActionResult MyAction(...) 
      {
          var myModel = GetMyModel(...);
          string viewString = RenderPartialViewToString(PartialView("MyView", myModel));
          // do something with the string
          return someAction;
      }
      

      我们实际上在基于事件的 AJAX 模型中使用它,其中我们的大多数操作实际上只是返回 AJAX 编码的客户端事件列表,其中一些客户端事件可能是更新特定的 DOM 元素通过渲染这个局部视图产生的字符串。

      【讨论】:

      • 我喜欢 Require.That() 语法 - 这是您自己编写的,还是(公开的)库的一部分?
      • 我们自己编写了“Require”类。我想使用 Contract.Requires,但它增加了很多开销。我使用 .NET Reflector 从 RenderPartial 中复制了大部分代码,然后对其进行了调整以满足我们的需求。
      • 哇,我从没想过我会从 Require.That 得到如此多的回应。我应该看看我是否可以说服我的老板用它制作一个开源库?
      • 最起码的相关部分可以放在这里吗?没有它们,如果不编写我们自己的例程来替换它,上面的代码就无法集成。
      • @vapcguy: Require.That() 真的很简单,可以用简单的if(!...) throw new Exception(...) 语句替换..gist.github.com/j2jensen/11377210
      猜你喜欢
      • 1970-01-01
      • 2016-03-14
      • 1970-01-01
      • 1970-01-01
      • 2015-01-28
      • 2015-10-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多