AI OnAI Off
#region Copyright © 1997-2007 EPiServer AB. All Rights Reserved.
/*
This code may only be used according to the EPiServer License Agreement.
The use of this code outside the EPiServer environment, in whole or in
parts, is forbidden without prior written permission from EPiServer AB.
EPiServer is a registered trademark of EPiServer AB. For more information
see http://www.episerver.com/license or request a copy of the EPiServer
License Agreement by sending an email to info@episerver.com
*/
#endregion
using System;
using System.Data;
using System.Configuration;
using System.Collections.Generic;
using System.Text;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Xml;
using EPiServer.Core;
using EPiServer.PlugIn;
using EPiServer.Web;
namespace EPiServerSample.templates.Units
{
///
/// Move ViewState from the start of the form element, to the end of it. View state looks like this:
/// input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="..."
/// ViewState may be large, and cause search engines to miss significant data or rank pages lower.
/// To disable it, remove this file from the project, or implement a Web.Config setting or similar mechanism
/// to control it's activity.
///
[PagePlugIn()]
public class ViewStateMover
{
///
/// Called by the EPiServer framework during startup, due to the PagePlugIn attribute. This is not
/// a PagePlugIn, we're just piggybacking the mechanism to ensure we get called once (and only once).
///
///
public static void Initialize(int optionFlag)
{
HtmlRewritePipe.HtmlInit += HtmlInitEventHandler;
}
///
/// Init the HtmlRewrite-engines event handlers. This is called every time a HtmlRewritePipe object
/// is instantiated.
///
/// The sender.
/// The instance containing the event data.
static private void HtmlInitEventHandler(object sender, HtmlRewriteEventArgs e)
{
// We only want to hook up our events when it's due to the UrlRewriter instantiating
// a HTML rewrite. This is not necessary - we could do it always, but this demonstrates
// the technique.
UrlRewriteModuleBase thisModule = e.InitContext as UrlRewriteModuleBase;
if (thisModule == null)
{
return;
}
// We need an instance of ourselves, to keep track of our state
ViewStateMover viewStateMover = new ViewStateMover();
HtmlRewritePipe rewritePipe = (HtmlRewritePipe)sender;
// There are two major events from the HtmlRewrite-engine, which allow us to rewrite
// names and values of the content. The exact definition depends on the XmlNodeType
// that is being processed.
rewritePipe.HtmlRewriteName += viewStateMover.HtmlRewriteNameEventHandler;
rewritePipe.HtmlRewriteValue += viewStateMover.HtmlRewriteValueEventHandler;
}
///
/// The states of our state-machine as we find what we're looking for.
///
private enum State { WaitingForForm, WaitingForViewState, BufferingInput, SkipToEndForm, SkipToEnd };
private State _state;
///
/// Helper class to group the value and quote char used for attribute values
///
private class AttributeValue
{
///
/// The Value of an attribute
///
public string Value;
///
/// The quote char used
///
public char QuoteChar;
///
/// Initialize an instance
///
///
///
public AttributeValue(string value, char quoteChar)
{
Value = value;
QuoteChar = quoteChar;
}
}
///
/// Buffer attributes of the "input" element here
///
private Dictionary _inputAttributes = new Dictionary();
///
/// Marker to determine wether in fact we've seen the ViewState
///
private bool _viewStateFound = false;
///
/// Handle rewrite name
///
/// The sender.
/// The instance containing the event data.
///
/// The name event is raised before an associated value event. Check the e.NodeType and other properties to determine
/// course of action.
///
private void HtmlRewriteNameEventHandler(object sender, HtmlRewriteEventArgs e)
{
switch (_state)
{
case State.WaitingForForm:
if (e.NodeType == XmlNodeType.Element && string.Compare(e.Name, "form", StringComparison.InvariantCultureIgnoreCase) == 0)
{
_state = State.WaitingForViewState;
}
break;
case State.WaitingForViewState:
if (e.NodeType == XmlNodeType.Element && string.Compare(e.Name, "input", StringComparison.InvariantCultureIgnoreCase) == 0)
{
_inputAttributes.Clear();
e.IsHoldingOutput = true;
_state = State.BufferingInput;
}
break;
}
}
///
/// Handle rewrite value
///
/// The sender.
/// The instance containing the event data.
///
/// The value event is raised after an associated name event. Check the e.NodeType and other properties to determine
/// course of action.
///
private void HtmlRewriteValueEventHandler(object sender, HtmlRewriteEventArgs e)
{
// Remove all insignificant whitespace
if (e.NodeType == XmlNodeType.Whitespace)
{
e.ValueBuilder.Length = 0;
e.ValueBuilder.Append(" ");
return;
}
switch (_state)
{
// We're buffering the contents of input element attributes, while checking for if it is a ViewState field
case State.BufferingInput:
switch (e.NodeType)
{
// Another attribute, add it to the collection and check if it's a ViewState
case XmlNodeType.Attribute:
_inputAttributes.Add(e.Name, new AttributeValue(e.Value, e.QuoteChar));
_viewStateFound |= string.Compare(e.Name, "name", StringComparison.InvariantCultureIgnoreCase) == 0 && e.Value == "__VIEWSTATE";
e.IsHoldingOutput = true;
break;
// End of the input element start tag. Determine if we're to output and continue waiting, or if it's the ViewState,
// in which case we switch state, and output nothing here.
case XmlNodeType.Element:
if (_viewStateFound && e.IsEmptyElement)
{
e.IsHoldingOutput = true;
_state = State.SkipToEndForm;
}
else
{
e.ValueBuilder.Length = 0;
AppendInputElement(e.ValueBuilder, _inputAttributes, e.IsEmptyElement);
_inputAttributes.Clear();
_state = State.WaitingForViewState;
}
break;
}
break;
case State.SkipToEndForm:
switch (e.NodeType)
{
// Check if this is the end of the form element, if so, output the ViewState, if any.
case XmlNodeType.EndElement:
if (string.Compare(e.Name, "form", StringComparison.InvariantCultureIgnoreCase) == 0)
{
string value = e.Value;
e.ValueBuilder.Length = 0;
e.ValueBuilder.Append("");
AppendInputElement(e.ValueBuilder, _inputAttributes, e.IsEmptyElement);
e.ValueBuilder.Append("");
_inputAttributes = null;
e.ValueBuilder.Append(value);
_state = State.SkipToEnd;
}
break;
}
break;
case State.SkipToEnd:
break;
}
}
///
/// Appends the input element data to the ValueBuilderResult
///
/// The instance containing the event data.
/// The _input attributes.
private void AppendInputElement(StringBuilder sb, Dictionary _inputAttributes, bool isEmptyElement)
{
sb.AppendFormat(" kvp in _inputAttributes)
{
sb.AppendFormat(" {0}={2}{1}{2}", kvp.Key, HttpUtility.HtmlAttributeEncode(kvp.Value.Value), kvp.Value.QuoteChar);
}
sb.Append(isEmptyElement ? "/>" : ">");
}
}
}
UrlRewriteModule.RewriteValidateHtmlRewrite
UrlRewriteModule.RewriteValidateToExternal
UrlRewriteModule.RewriteValidateToInternal
and setting e.IsValidForRewrite to false, but that doesn't seem to work. If I remove the UrlRewriteModule httpModule everything works just fine, but as i said i only want to turn it off for certain URL's.
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using EPiServer.Core;
using EPiServer.PlugIn;
using EPiServer.Web;
namespace EPiServer1
{
[PagePlugIn()]
public class UrlRewriteControl
{
public static void Initialize(int optionFlag)
{
UrlRewriteModule.RewriteInit += new EventHandler(UrlRewriteModule_RewriteInit);
}
static void UrlRewriteModule_RewriteInit(object sender, UrlRewriteEventArgs e)
{
((UrlRewriteModule)sender).RewriteValidateToExternal += new EventHandler(ViewStateMover_RewriteValidateToExternal);
}
static void ViewStateMover_RewriteValidateToExternal(object sender, UrlRewriteEventArgs e)
{
if(e.Url.Path.StartsWith("/News")) // Select what URL:s should not be rewritten
e.IsValidForRewrite = false;
}
}
}
If i remove the UrlRewriteModule from web.config i get.
Note that the &
is replaced by &
Is there anyway we could work around this?