【问题标题】:Rendering a control to HTML without __VIEWSTATE在没有 __VIEWSTATE 的情况下将控件呈现为 HTML
【发布时间】:2014-02-04 20:53:04
【问题描述】:

我正在使用 Web 服务来获取 GridView 并将其呈现为 HTML。这个想法是异步生成它(例如,在可扩展网格的隐藏行中生成数据)。

[System.Web.Services.WebMethod]
[System.Web.Script.Services.ScriptMethod]
public static string ExpandRowService(string contextKey)
{
    try
    {
        long recId = long.Parse(contextKey);
        return RenderControlToHtml("/Controls/SubGrid.ascx", recId);
    }
    catch (Exception)
    {
        return "";
    }
}

public static string RenderControlToHtml(string controlPath, params object[] constructorParams)
{
    var page = new Page
    {
        EnableEventValidation = false,
        EnableViewState = false,
    };
    var form = new HtmlForm
    {
        EnableViewState = false
    };
    page.Controls.Add(form);

    var control = page.LoadControl(controlPath, constructorParams);
    form.Controls.Add(control);

    return page.RenderControl();
}

问题是像这样渲染到 HTML 需要一个虚拟表单来渲染,而这个虚拟表单有一个 __VIEWSTATE 隐藏输入:

<form method="post" action="ExpandRowService" id="ctl00">
<div class="aspNetHidden">
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="" />
</div>

在任何其他操作后的回发中,有多个 __VIEWSTATE 变量,这显然是一个禁忌。

如何在没有被诅咒的__VIEWSTATE 隐藏输入的情况下强制将控件呈现为 HTML?

编辑:

我使用的是 GridView 而不是从头开始制作表格,因为我需要它的数据绑定功能来设置各种样式(例如:用红色标记负数)。

【问题讨论】:

  • 不使用 ASP.NET WebControls 直接自己渲染表格不是更容易吗?
  • @Dai:我采用了惰性方法并设置了一个带有数据源的 GridView。在当时,手工制作桌子似乎是一项额外的工作。现在我想知道...
  • 虽然我不想让您追逐可能对您不起作用的东西,但您尝试做的事情感觉它更自然地适合 ASP.NET MVC 而不是 Webforms。如果需要,您可以在同一个项目中混合使用 MVC 和 Webforms。我相信您还可以找到一些用于使用 MVC (stackoverflow.com/questions/177275/…) 构建网格的组件,这样您就不必从头开始创建它,但我个人不能说它们中的任何一个是否允许您做你想做的事。不过,这可能是方向上的重大变化。
  • 只是一个建议,而不是让服务返回 HTML,也许您可​​以让服务仅以 JSON 格式返回数据,并让页面上的 JavaScript 负责将数据放入隐藏行。
  • @Dr.Wily'sApprentice 我会考虑两个有趣的替代方案。

标签: c# asp.net viewstate webmethod


【解决方案1】:

您可以呈现控件本身,而无需周围的表单。您只需要设置一个由合理存储支持的HtmlTextWriter 实例,例如StringBuilder

// create control and make it part of a form and page
…

// render just the control
var c = new StringBuilder();
using (var sw = new StringWriter(c))
{
    using (var writer = new HtmlTextWriter(sw))
    {
        control.RenderControl(writer);
    }
}
return c.ToString();

【讨论】:

  • 嗯,TextWriter 是一个抽象类,不是吗?试图在这里找到正确的方法。
  • 没关系,用过 StringWriter。然而,control.RenderControl(writer); 抛出一个 HttpException,说“GridView 必须放在一个带有 runat=server 的表单标签中。”
  • @MPelletier 关于TextWriter:对不起,我没有尝试就编写了代码。是的,您仍然需要构建PageHtmlForm 实例——ASP.NET Control 的内部结构有时过于依附于封闭(父)控件,这反过来又会创建对表单的递归依赖,并且页面。
  • @MPelletier 相应地修正了我的答案。
  • 显然我无法将控件本身呈现在表单标签之外(需要 runat=server)。
【解决方案2】:

似乎无法将带有LoadControl 的控件生成为表单(必需)并且没有__VIEWSTATE

我制作了自己的 TableWriter,并对其进行了一些行绑定。尽我所能。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-06-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-02
    • 2013-09-18
    相关资源
    最近更新 更多