如何将部分视图渲染为字符串

发布于 2024-08-26 13:20:43 字数 536 浏览 11 评论 0原文

我有以下代码:

public ActionResult SomeAction()
{
    return new JsonpResult
    {
        Data = new { Widget = "some partial html for the widget" }
    };
}

我想修改它,以便我可以

public ActionResult SomeAction()
{
    // will render HTML that I can pass to the JSONP result to return.
    var partial = RenderPartial(viewModel); 
    return new JsonpResult
    {
        Data = new { Widget = partial }
    };
}

这样做吗?有人可以解释一下怎么做吗?

注意,我在发布解决方案之前编辑了问题。

I have the following code:

public ActionResult SomeAction()
{
    return new JsonpResult
    {
        Data = new { Widget = "some partial html for the widget" }
    };
}

I'd like to modify it so that I could have

public ActionResult SomeAction()
{
    // will render HTML that I can pass to the JSONP result to return.
    var partial = RenderPartial(viewModel); 
    return new JsonpResult
    {
        Data = new { Widget = partial }
    };
}

is this possible? Could somebody explain how?

note, I edited the question before posting the solution.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

独守阴晴ぅ圆缺 2024-09-02 13:20:43

我为 ASP.NET MVC 4 应用程序选择了如下扩展方法。我认为它比我见过的一些建议更简单:

public static class ViewExtensions
{
    public static string RenderToString(this PartialViewResult partialView)
    {
        var httpContext = HttpContext.Current;

        if (httpContext == null)
        {
            throw new NotSupportedException("An HTTP context is required to render the partial view to a string");
        }

        var controllerName = httpContext.Request.RequestContext.RouteData.Values["controller"].ToString();

        var controller = (ControllerBase)ControllerBuilder.Current.GetControllerFactory().CreateController(httpContext.Request.RequestContext, controllerName);

        var controllerContext = new ControllerContext(httpContext.Request.RequestContext, controller);

        var view = ViewEngines.Engines.FindPartialView(controllerContext, partialView.ViewName).View;

        var sb = new StringBuilder();

        using (var sw = new StringWriter(sb))
        {
            using (var tw = new HtmlTextWriter(sw))
            {
                view.Render(new ViewContext(controllerContext, view, partialView.ViewData, partialView.TempData, tw), tw);
            }
        }

        return sb.ToString();
    }
}

它允许我执行以下操作:

var html = PartialView("SomeView").RenderToString();

此外,此方法会保留任何 ModelViewBag 和其他视图数据的观点。

I opted for an extension method like the following for an ASP.NET MVC 4 app. I think it's simpler than some of the suggestions I've seen:

public static class ViewExtensions
{
    public static string RenderToString(this PartialViewResult partialView)
    {
        var httpContext = HttpContext.Current;

        if (httpContext == null)
        {
            throw new NotSupportedException("An HTTP context is required to render the partial view to a string");
        }

        var controllerName = httpContext.Request.RequestContext.RouteData.Values["controller"].ToString();

        var controller = (ControllerBase)ControllerBuilder.Current.GetControllerFactory().CreateController(httpContext.Request.RequestContext, controllerName);

        var controllerContext = new ControllerContext(httpContext.Request.RequestContext, controller);

        var view = ViewEngines.Engines.FindPartialView(controllerContext, partialView.ViewName).View;

        var sb = new StringBuilder();

        using (var sw = new StringWriter(sb))
        {
            using (var tw = new HtmlTextWriter(sw))
            {
                view.Render(new ViewContext(controllerContext, view, partialView.ViewData, partialView.TempData, tw), tw);
            }
        }

        return sb.ToString();
    }
}

It allows me to do the following:

var html = PartialView("SomeView").RenderToString();

Also, this approach persists any Model, ViewBag and other view data for the view.

三月梨花 2024-09-02 13:20:43

这是一个有效答案的稍微修改版本:

public static string RenderPartialToString(string controlName, object viewData)
{
    ViewPage viewPage = new ViewPage() { ViewContext = new ViewContext() };

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

用法:

string ret = RenderPartialToString("~/Views/MyController/MyPartial.ascx", model);

This is a slightly modified version of an answer that works:

public static string RenderPartialToString(string controlName, object viewData)
{
    ViewPage viewPage = new ViewPage() { ViewContext = new ViewContext() };

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

Usage:

string ret = RenderPartialToString("~/Views/MyController/MyPartial.ascx", model);
宛菡 2024-09-02 13:20:43

DaveDev 的答案对我来说效果很好,但是当部分视图调用另一个部分视图时,我得到“值不能为空。参数名称:视图”

搜索周围我做了一个变体 以下 似乎效果很好。

 public static string RenderPartialToString(string viewName, object model, ControllerContext ControllerContext)
    {
        if (string.IsNullOrEmpty(viewName))
            viewName = ControllerContext.RouteData.GetRequiredString("action");
        ViewDataDictionary ViewData = new ViewDataDictionary();
        TempDataDictionary TempData = new TempDataDictionary();
        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();
        }

    }

用法:

String result = MVCHelpers.RenderPartialToString("PartialViewHere", Model, ControllerContext)

DaveDev's answer worked well for me, however when the partial view calls another partial I get "Value cannot be null. Parameter name: view"

Searching around I have made a variant of the following that seems to work well.

 public static string RenderPartialToString(string viewName, object model, ControllerContext ControllerContext)
    {
        if (string.IsNullOrEmpty(viewName))
            viewName = ControllerContext.RouteData.GetRequiredString("action");
        ViewDataDictionary ViewData = new ViewDataDictionary();
        TempDataDictionary TempData = new TempDataDictionary();
        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();
        }

    }

Usage:

String result = MVCHelpers.RenderPartialToString("PartialViewHere", Model, ControllerContext)
音盲 2024-09-02 13:20:43

您可以创建将视图呈现为字符串的扩展。

public static class RenderPartialToStringExtensions
{
    /// <summary>
    /// render PartialView and return string
    /// </summary>
    /// <param name="context"></param>
    /// <param name="partialViewName"></param>
    /// <param name="model"></param>
    /// <returns></returns>
    public static string RenderPartialToString(this ControllerContext context, string partialViewName, object model)
    {
        return RenderPartialToStringMethod(context, partialViewName, model);
    }

    /// <summary>
    /// render PartialView and return string
    /// </summary>
    /// <param name="context"></param>
    /// <param name="partialViewName"></param>
    /// <param name="viewData"></param>
    /// <param name="tempData"></param>
    /// <returns></returns>
    public static string RenderPartialToString(ControllerContext context, string partialViewName, ViewDataDictionary viewData, TempDataDictionary tempData)
    {
        return RenderPartialToStringMethod(context, partialViewName, viewData, tempData);
    }

    public static string RenderPartialToStringMethod(ControllerContext context, string partialViewName, ViewDataDictionary viewData, TempDataDictionary tempData)
    {
        ViewEngineResult result = ViewEngines.Engines.FindPartialView(context, partialViewName);

        if (result.View != null)
        {
            StringBuilder sb = new StringBuilder();
            using (StringWriter sw = new StringWriter(sb))
            {
                using (HtmlTextWriter output = new HtmlTextWriter(sw))
                {
                    ViewContext viewContext = new ViewContext(context, result.View, viewData, tempData, output);
                    result.View.Render(viewContext, output);
                }
            }

            return sb.ToString();
        }
        return String.Empty;
    }

    public static string RenderPartialToStringMethod(ControllerContext context, string partialViewName, object model)
    {
        ViewDataDictionary viewData = new ViewDataDictionary(model);
        TempDataDictionary tempData = new TempDataDictionary();
        return RenderPartialToStringMethod(context, partialViewName, viewData, tempData);
    }
}

然后在行动中使用它

[HttpPost]
public ActionResult GetTreeUnit(string id)
{
    int _id = id.ExtractID();
    string render = ControllerContext.RenderPartialToString("SomeView");
    return Json(new { data = render });
}

You can create extension that render view into string.

public static class RenderPartialToStringExtensions
{
    /// <summary>
    /// render PartialView and return string
    /// </summary>
    /// <param name="context"></param>
    /// <param name="partialViewName"></param>
    /// <param name="model"></param>
    /// <returns></returns>
    public static string RenderPartialToString(this ControllerContext context, string partialViewName, object model)
    {
        return RenderPartialToStringMethod(context, partialViewName, model);
    }

    /// <summary>
    /// render PartialView and return string
    /// </summary>
    /// <param name="context"></param>
    /// <param name="partialViewName"></param>
    /// <param name="viewData"></param>
    /// <param name="tempData"></param>
    /// <returns></returns>
    public static string RenderPartialToString(ControllerContext context, string partialViewName, ViewDataDictionary viewData, TempDataDictionary tempData)
    {
        return RenderPartialToStringMethod(context, partialViewName, viewData, tempData);
    }

    public static string RenderPartialToStringMethod(ControllerContext context, string partialViewName, ViewDataDictionary viewData, TempDataDictionary tempData)
    {
        ViewEngineResult result = ViewEngines.Engines.FindPartialView(context, partialViewName);

        if (result.View != null)
        {
            StringBuilder sb = new StringBuilder();
            using (StringWriter sw = new StringWriter(sb))
            {
                using (HtmlTextWriter output = new HtmlTextWriter(sw))
                {
                    ViewContext viewContext = new ViewContext(context, result.View, viewData, tempData, output);
                    result.View.Render(viewContext, output);
                }
            }

            return sb.ToString();
        }
        return String.Empty;
    }

    public static string RenderPartialToStringMethod(ControllerContext context, string partialViewName, object model)
    {
        ViewDataDictionary viewData = new ViewDataDictionary(model);
        TempDataDictionary tempData = new TempDataDictionary();
        return RenderPartialToStringMethod(context, partialViewName, viewData, tempData);
    }
}

And then use it in action

[HttpPost]
public ActionResult GetTreeUnit(string id)
{
    int _id = id.ExtractID();
    string render = ControllerContext.RenderPartialToString("SomeView");
    return Json(new { data = render });
}
乖不如嘢 2024-09-02 13:20:43

完美运行(仅需要查看名称)

* 对于参数,您可以使用模型

* 也可以从视图调用

此视图端或调用端

BuyOnlineCartMaster ToInvoice1 = new BuyOnlineCartMaster(); // for passing parameters
ToInvoice1.CartID = 1;

string HtmlString = RenderPartialViewToString("PartialInvoiceCustomer", ToInvoice1);

函数生成 HTML

public class BuyOnlineCartMaster
{
        public int CartID { get; set; }
}

 public static string RenderPartialViewToString(string viewName, object model)
 {    
     using (var sw = new StringWriter())
            {
                BuyOnlineController controller = new BuyOnlineController(); // instance of the required controller (you can pass this as a argument if needed)

                // Create an MVC Controller Context
                var wrapper = new HttpContextWrapper(System.Web.HttpContext.Current);

                RouteData routeData = new RouteData();

                routeData.Values.Add("controller", controller.GetType().Name
                                                            .ToLower()
                                                            .Replace("controller", ""));

                controller.ControllerContext = new ControllerContext(wrapper, routeData, controller);

                controller.ViewData.Model = model;

                var viewResult = ViewEngines.Engines.FindPartialView(controller.ControllerContext, viewName);

                var viewContext = new ViewContext(controller.ControllerContext, viewResult.View, controller.ViewData, controller.TempData, sw);
                viewResult.View.Render(viewContext, sw);

                return sw.ToString();
            }
   }

部分视图页面

@{ 
    var ModelContents = (Common.BuyOnlineCartMaster)ViewData.Model;


}

Your cart id : @(ModelContents.CartID)

Works perfect (Only view name required)

* for parameters you can use a model

* can call this from a view also

View side or Calling Side

BuyOnlineCartMaster ToInvoice1 = new BuyOnlineCartMaster(); // for passing parameters
ToInvoice1.CartID = 1;

string HtmlString = RenderPartialViewToString("PartialInvoiceCustomer", ToInvoice1);

Function Generating HTML

public class BuyOnlineCartMaster
{
        public int CartID { get; set; }
}

 public static string RenderPartialViewToString(string viewName, object model)
 {    
     using (var sw = new StringWriter())
            {
                BuyOnlineController controller = new BuyOnlineController(); // instance of the required controller (you can pass this as a argument if needed)

                // Create an MVC Controller Context
                var wrapper = new HttpContextWrapper(System.Web.HttpContext.Current);

                RouteData routeData = new RouteData();

                routeData.Values.Add("controller", controller.GetType().Name
                                                            .ToLower()
                                                            .Replace("controller", ""));

                controller.ControllerContext = new ControllerContext(wrapper, routeData, controller);

                controller.ViewData.Model = model;

                var viewResult = ViewEngines.Engines.FindPartialView(controller.ControllerContext, viewName);

                var viewContext = new ViewContext(controller.ControllerContext, viewResult.View, controller.ViewData, controller.TempData, sw);
                viewResult.View.Render(viewContext, sw);

                return sw.ToString();
            }
   }

Partial View page

@{ 
    var ModelContents = (Common.BuyOnlineCartMaster)ViewData.Model;


}

Your cart id : @(ModelContents.CartID)
淡笑忘祈一世凡恋 2024-09-02 13:20:43

您可以使用以下方法开箱即用:

var partial = new HtmlString(Html.Partial("_myPartial", Model).ToString());

You can do that out of the box with:

var partial = new HtmlString(Html.Partial("_myPartial", Model).ToString());
等往事风中吹 2024-09-02 13:20:43

Dave,

同一主题的变体(mvc v1.0):

        protected static string RenderPartialToString(Controller controller, string partialName, object model)
    {
        var vd = new ViewDataDictionary(controller.ViewData);
        var vp = new ViewPage
        {
            ViewData = vd,
            ViewContext = new ViewContext(),
            Url = new UrlHelper(controller.ControllerContext.RequestContext)
        };

        ViewEngineResult result = ViewEngines
                                  .Engines
                                  .FindPartialView(controller.ControllerContext, partialName);

        if (result.View == null)
        {
            throw new InvalidOperationException(
            string.Format("The partial view '{0}' could not be found", partialName));
        }
        var partialPath = ((WebFormView)result.View).ViewPath;

        vp.ViewData.Model = model;

        Control control = vp.LoadControl(partialPath);
        vp.Controls.Add(control);

        var sb = new StringBuilder();

        using (var sw = new StringWriter(sb))
        {
            using (var tw = new HtmlTextWriter(sw))
            {
                vp.RenderControl(tw);
            }
        }
        return sb.ToString();
    }

在控制器中的用法:

        public string GetLocationHighlites()
    {
        IBlockData model = WebPagesMapper.GetLocationHighlites();
        // **this** being the controoler instance
        // LocationPartial.ascx can be defined in shared or in view folder
        return RenderPartialToString(**this**,"LocationPartial", model);
    }

Dave,

a variation on the same theme (mvc v1.0):

        protected static string RenderPartialToString(Controller controller, string partialName, object model)
    {
        var vd = new ViewDataDictionary(controller.ViewData);
        var vp = new ViewPage
        {
            ViewData = vd,
            ViewContext = new ViewContext(),
            Url = new UrlHelper(controller.ControllerContext.RequestContext)
        };

        ViewEngineResult result = ViewEngines
                                  .Engines
                                  .FindPartialView(controller.ControllerContext, partialName);

        if (result.View == null)
        {
            throw new InvalidOperationException(
            string.Format("The partial view '{0}' could not be found", partialName));
        }
        var partialPath = ((WebFormView)result.View).ViewPath;

        vp.ViewData.Model = model;

        Control control = vp.LoadControl(partialPath);
        vp.Controls.Add(control);

        var sb = new StringBuilder();

        using (var sw = new StringWriter(sb))
        {
            using (var tw = new HtmlTextWriter(sw))
            {
                vp.RenderControl(tw);
            }
        }
        return sb.ToString();
    }

usage within controller:

        public string GetLocationHighlites()
    {
        IBlockData model = WebPagesMapper.GetLocationHighlites();
        // **this** being the controoler instance
        // LocationPartial.ascx can be defined in shared or in view folder
        return RenderPartialToString(**this**,"LocationPartial", model);
    }
梅倚清风 2024-09-02 13:20:43
public virtual string RenderPartialViewToString(string viewName, object viewmodel)
        {
            if (string.IsNullOrEmpty(viewName))
            {
                viewName = this.ControllerContext.RouteData.GetRequiredString("action");
            }

            ViewData.Model = viewmodel;

            using (var sw = new StringWriter())
            {
                ViewEngineResult viewResult = System.Web.Mvc.ViewEngines.Engines.FindPartialView(this.ControllerContext, viewName);
                var viewContext = new ViewContext(this.ControllerContext, viewResult.View, this.ViewData, this.TempData, sw);
                viewResult.View.Render(viewContext, sw);
                viewResult.ViewEngine.ReleaseView(ControllerContext, viewResult.View);

                return sw.GetStringBuilder().ToString();
            }
        }
public virtual string RenderPartialViewToString(string viewName, object viewmodel)
        {
            if (string.IsNullOrEmpty(viewName))
            {
                viewName = this.ControllerContext.RouteData.GetRequiredString("action");
            }

            ViewData.Model = viewmodel;

            using (var sw = new StringWriter())
            {
                ViewEngineResult viewResult = System.Web.Mvc.ViewEngines.Engines.FindPartialView(this.ControllerContext, viewName);
                var viewContext = new ViewContext(this.ControllerContext, viewResult.View, this.ViewData, this.TempData, sw);
                viewResult.View.Render(viewContext, sw);
                viewResult.ViewEngine.ReleaseView(ControllerContext, viewResult.View);

                return sw.GetStringBuilder().ToString();
            }
        }
输什么也不输骨气 2024-09-02 13:20:43

老帖子,但我认为你让这件事变得太困难了。

为什么不 return PartialView("", model); 将返回您想要的字符串。

只需将 Get/Post 方法设置为 IActionResult 作为 JsonResultPartialResult 以及其他继承自 ActionResult 的方法,您就可以发送回任何内容,包括 JsonResult阿贾克斯

  [HttpPost]
  public IActionResult CheckForContent(string id, string type){
    try{
       
       if(type = "something"){
          return Json(new {
             success = true,
             myProp = "this prop"       
          });
       } else {
          MyViewModel model = new MyViewModel();
          model.Content = _service.GetContent(new GetContentRequest(){ id = id }
          return PartialView("<my partial>", model);
    } catch(Exception ex){
       _logger.LogError(ex.Message);
       return Json(new { success = false }
    }
  }

   $.ajax({
      url: '/CheckForContent',
      type: 'POST',
      cache: false,
      contentType: false,
      processData: false,
      success: function (result) {
         if(!result && !result.success){
            console.log("Failed to load");
         } else if(result && result.success){
            $('#MyProp').val(result.myProp);
         } else {
            $('#MyContainer').html(result);
         }
      },
   });

Old post, but I think you are making this too difficult.

Why not return PartialView("<my partial>", model); will return the string you desire.

Just make the Get/Post method an IActionResult as JsonResult, PartialResultand other inherit from ActionResult you can send back anything including a JsonResult

  [HttpPost]
  public IActionResult CheckForContent(string id, string type){
    try{
       
       if(type = "something"){
          return Json(new {
             success = true,
             myProp = "this prop"       
          });
       } else {
          MyViewModel model = new MyViewModel();
          model.Content = _service.GetContent(new GetContentRequest(){ id = id }
          return PartialView("<my partial>", model);
    } catch(Exception ex){
       _logger.LogError(ex.Message);
       return Json(new { success = false }
    }
  }

Ajax:

   $.ajax({
      url: '/CheckForContent',
      type: 'POST',
      cache: false,
      contentType: false,
      processData: false,
      success: function (result) {
         if(!result && !result.success){
            console.log("Failed to load");
         } else if(result && result.success){
            $('#MyProp').val(result.myProp);
         } else {
            $('#MyContainer').html(result);
         }
      },
   });
桃扇骨 2024-09-02 13:20:43

使用 ASP.NET Core 6.0,现有的答案都不适合我,所以我推出了自己的答案。

async Task<string> getPartialViewHtml(string viewName)
{
    var builder = new StringBuilder();
    var writer  = new StringWriter(builder);
    var content = await Html.PartialAsync(viewName);

    content.WriteTo(writer, HtmlEncoder.Default);

    var output = builder.ToString();

    return output;
}

示例用法如下:

var viewHtml = await getPartialViewHtml("PartialViewNameGoesHere");

None of the existing answers worked for me, using ASP.NET Core 6.0, so I rolled my own.

async Task<string> getPartialViewHtml(string viewName)
{
    var builder = new StringBuilder();
    var writer  = new StringWriter(builder);
    var content = await Html.PartialAsync(viewName);

    content.WriteTo(writer, HtmlEncoder.Default);

    var output = builder.ToString();

    return output;
}

Example usage would be:

var viewHtml = await getPartialViewHtml("PartialViewNameGoesHere");
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文