1

I'm using a web service to get and render a GridView to HTML. The idea is to generate it asynchronously (to generate the data in a hidden row for an expandable grid, for example).

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

The problem is that rendering to HTML like that needs a dummy form to render into, and that dummy form has a __VIEWSTATE hidden input:

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

On postback after any other action, there are more than one __VIEWSTATE variables and that's obviously a no-no.

How can I force rendering of a control to HTML without the accursed __VIEWSTATE hiden input?

EDIT:

I'm using a GridView and not making a table from scratch because I need its data binding capabilities to set various styles (for example: mark negative amounts in red).

Cœur
  • 37,241
  • 25
  • 195
  • 267
MPelletier
  • 16,256
  • 15
  • 86
  • 137
  • 3
    Wouldn't it be easier to render a table yourself directly without using the ASP.NET WebControls? – Dai Feb 04 '14 at 21:02
  • @Dai: I took the lazy approach and setup a GridView with a DataSource. Making the Table by hand seemed like extra work at the time. Now I wonder... – MPelletier Feb 04 '14 at 21:04
  • While I don't want to cause you to chase something that might not work for you, what you're trying to do feels like it fits more naturally with ASP.NET MVC rather than Webforms. You can mix MVC and Webforms within the same project, if you want. I'm sure that you can also find some components for building a grid with MVC (http://stackoverflow.com/questions/177275/grid-controls-for-asp-net-mvc) so that you don't have to create it from scratch, but I personally can't say whether any of them will allow you to do what you're trying to do. This would probably be a major change in direction, though. – Dr. Wily's Apprentice Feb 04 '14 at 21:12
  • Just a suggestion, rather than having the service return HTML, perhaps you could have the service return just the data as JSON and make the JavaScript on the page be responsible for putting the data into the hidden row. – Dr. Wily's Apprentice Feb 04 '14 at 21:20
  • @Dr.Wily'sApprentice Two interesting alternatives I'll consider. – MPelletier Feb 04 '14 at 21:28

2 Answers2

2

You can render the control itself, without the surrounding form. All you need is to setup a HtmlTextWriter instance backed by a reasonable storage, such as a 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();
Ondrej Tucny
  • 27,626
  • 6
  • 70
  • 90
  • Hm, TextWriter is an abstract class, no? Trying to find the right approach here. – MPelletier Feb 04 '14 at 21:17
  • Nevermind, used StringWriter. However, `control.RenderControl(writer);` throws an HttpException, saying "GridView must be placed in a form tag with runat=server." – MPelletier Feb 04 '14 at 21:25
  • @MPelletier Regarding the `TextWriter`: sorry I wrote the code without trying. And yes, you still have to build a `Page` and `HtmlForm` instances—ASP.NET `Control`'s internals are sometimes too attached to the enclosing (parent) control, which in turn creates a recursive dependency on the form and page. – Ondrej Tucny Feb 04 '14 at 21:50
  • @MPelletier Fixed my answer accordingly. – Ondrej Tucny Feb 04 '14 at 21:52
  • Apparently I cannot render the control itself outside of a form tag (which needs runat=server). – MPelletier Feb 04 '14 at 22:21
0

It appears that it is not possible to generate the control with LoadControl into a form (required) and not have a __VIEWSTATE.

I made my own TableWriter, and did some rowbinding to it. Best I could do.

MPelletier
  • 16,256
  • 15
  • 86
  • 137