タイトル一覧   関連タグ: Web C#
タグ:Web C# タイトル:__VIEWSTATEのレンダリング位置を変えたい
1 2
1:  お名前:菊池 2008/01/18 15:37:26

ASP.NET で __VIEWSTATE が form の先頭でデフォルトで出るんだけど、これを form の末尾にもって行きたいときってどうやるんでしたっけ?

どっかで見た記憶があるんですがたどりつけません。
知ってる方が居ればお教え願います。

狙ってるのはSEOとか、ページのレンダリング速度の観点でページのできるだけ前のほうにコンテンツをもって行きたいって話なんですが。

2:  お名前:Roger 2008/01/21 12:45:29

そうですね。PageのRender方法をoverrideしてみせんか?
3:  お名前:Roger 2008/01/21 12:53:44

Render中に、_VIEWSTATEを見つけたら、取り替えます。それ後、</form>前に_VIEWSTATEを挿入するよ。
4:  お名前:菊池 2008/01/22 9:38:34

なんだかスマートにやる方法は無いっぽいですね。

App_Browserにて
<browsers>
  <browser refID="Default">
  <controlAdapters>
  <adapter
  controlType="System.Web.UI.HtmlControls.HtmlForm"
  adapterType="Adapters.HtmlFormAdapter" />
  </controlAdapters>
  </browser>
</browsers>

ってやって

using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Web.UI;
using System.Web.UI.Adapters;

namespace Adapters
{

  public class HtmlFormAdapter : ControlAdapter
  {
  protected override void Render(HtmlTextWriter writer)
  {
  HiddenFieldRepositionTextWriter wr2 = new HiddenFieldRepositionTextWriter(writer);
  base.Render( new HtmlTextWriter(wr2));
  return;
  }

  internal class HiddenFieldRepositionTextWriter : TextWriter
  {
  private static bool isHiddenField(string input)
  {
  if (input.Contains("type=\"hidden\""))
  {
  return true;
  }
  return false;
  }

  StringBuilder tagBuffer = new StringBuilder();
  private List<string> hiddenFields = new List<string>();
  private bool buffering;
  private TextWriter backWriter;

  public HiddenFieldRepositionTextWriter(TextWriter writer)
  {
  backWriter = writer;
  }

  public override void Write(char value)
  {
  if (value == '<')
  {
  buffering = true;
  tagBuffer.Append(value);
  return;
  }
  if (!buffering)
  {
  backWriter.Write(value);
  return;
  }
  tagBuffer.Append(value);
  if (value != '>')
  {
  return;
  }
  buffering = false;
  string tag = tagBuffer.ToString();
  tagBuffer.Length = 0;
  if (isHiddenField(tag))
  {
  hiddenFields.Add(tag);
  return;
  }
  if (tag.StartsWith("</form"))
  {
  foreach (string hiddenField in hiddenFields)
  {
  backWriter.WriteLine(hiddenField);
  }
  }
  backWriter.Write(tag);
  }

  public override Encoding Encoding
  {
  get { return backWriter.Encoding; }
  }
  }
  }

}

って格好でやっつけてみました。

5:  お名前:菊池 2008/01/22 9:39:07

あぁ、タブが皆左によってしもった…

6:  お名前:Roger 2008/01/22 9:58:39

public partial class Test_ViewState : System.Web.UI.Page
{
  //ViewState、Html中に正規表現パターン
  private static readonly Regex viewStateRegex = new Regex(@"(<input type=""hidden"" name=""__VIEWSTATE"" id=""__VIEWSTATE"" value=""[w+\/=]+"" />)", RegexOptions.Multiline | RegexOptions.Compiled);
  //</form>の正規表現パターン
  private static readonly Regex endFormRegex = new Regex(@"</form>", RegexOptions.Multiline | RegexOptions.Compiled);

  protected override void Render(HtmlTextWriter writer)
  {
  System.IO.StringWriter stringWriter = new System.IO.StringWriter();
  HtmlTextWriter htmlWriter = new HtmlTextWriter(stringWriter);
  base.Render(htmlWriter);

  string html = stringWriter.ToString();
  Match viewStateMatch = viewStateRegex.Match(html);
  //ViewStateのHtmlを見つける
  string viewStateString = viewStateMatch.Captures[0].Value;
  //ViewStateのHtmlを取り替えます
  html = html.Remove(viewStateMatch.Index, viewStateMatch.Length);

  //</form>を見つける
  Match endFormMath = endFormRegex.Match(html, viewStateMatch.Index);
  //</form>前に_VIEWSTATEを挿入するよ。
  html = html.Insert(endFormMath.Index, viewStateString);
  writer.Write(html);
 
  }
  protected void Page_Load(object sender, EventArgs e)
  {

  }
}

7:  お名前:Roger 2008/01/22 9:59:34

このコードをやってみる
8:  お名前:小野@どっとねっとふぁん 2008/01/22 10:33:58

Adapterを使うとページのベースページを書き換えたりする必要がなくて良いね。
この程度で書き換えられるのねぇ。。。
9:  お名前:菊池 2008/01/22 12:56:47

> Adapterを使うとページのベースページを書き換えたりする必要がなくて良いね。

うん、これで全部のページに自動的にかかるので便利でございます。

>>6

Pageでやると全部のページに仕込まないといけないのが…でControlAdapterに行ってみました。
StringWriterの中にHTML全部持つのはメモリ消費的にやりたくなかったのですよ。

10:  お名前:Roger 2008/01/22 13:31:43

そうですね、Pageのサイズが大きいになったら、メモリの方には考えない。
1 2
お名前
メッセージ
次回のために入力情報を記録