*
* , , . , , . HTTP IIS7 , . .
, , , . , , ( , , ).
, HTML, - , :
public static class HtmlHelperExtensions
{
public static HtmlString SequentialNumber(this HtmlHelper html)
{
return ":{ad_sequence}";
}
}
ASP.NET MVC , . , HomeController Index(), :
[AdSequencePostProcessingFilter]
public class HomeController : Controller
{
}
public class HomeController : Controller
{
[AdSequencePostProcessingFilter]
public ActionResult Index()
{
return View();
}
}
ASP.NET MVC 3 , :
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
GlobalFilters.Filters.Add(new AdSequencePostProcessingFilterAttribute());
}
}
, . .
AdSequencePostProcessingFilterAttribute ( ):
public class AdSequencePostProcessingFilterAttribute : ActionFilterAttribute
{
private Stream _output;
private const string AdSequenceMarker = ":{ad_sequence}";
private const char AdSequenceStart = ':';
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
_output = filterContext.HttpContext.Response.Filter;
filterContext.HttpContext.Response.Flush();
filterContext.HttpContext.Response.Filter = new CapturingResponseFilter(filterContext.HttpContext.Response.Filter);
}
public override void OnResultExecuted(ResultExecutedContext filterContext)
{
filterContext.HttpContext.Response.Flush();
CapturingResponseFilter filter =
(CapturingResponseFilter)filterContext.HttpContext.Response.Filter;
filterContext.HttpContext.Response.Filter = _output;
string html = filter.GetContents(filterContext.HttpContext.Response.ContentEncoding);
int adSequenceCounter = 1;
StringBuilder output = new StringBuilder();
for (int i = 0; i < html.Length; i++)
{
char c = html[i];
if (c == AdSequenceStart && html.Substring(i, AdSequenceMarker.Length) == AdSequenceMarker)
{
output.Append(adSequenceCounter++);
i += (AdSequenceMarker.Length - 1);
}
else
{
output.Append(c);
}
}
filterContext.HttpContext.Response.Write(output.ToString());
filterContext.HttpContext.Response.Flush();
}
}
, :
class CapturingResponseFilter : Stream
{
private Stream _sink;
private MemoryStream mem;
public CapturingResponseFilter(Stream sink)
{
_sink = sink;
mem = new MemoryStream();
}
public override bool CanRead { get { return true; } }
public override bool CanSeek { get { return false; } }
public override bool CanWrite { get { return false; } }
public override long Length { get { return 0; } }
public override long Position { get; set; }
public override long Seek(long offset, SeekOrigin direction)
{
return 0;
}
public override void SetLength(long length)
{
_sink.SetLength(length);
}
public override void Close()
{
_sink.Close();
mem.Close();
}
public override void Flush()
{
_sink.Flush();
}
public override int Read(byte[] buffer, int offset, int count)
{
return _sink.Read(buffer, offset, count);
}
public override void Write(byte[] buffer, int offset, int count)
{
mem.Write(buffer, 0, count);
}
public string GetContents(Encoding enc)
{
var buffer = new byte[mem.Length];
mem.Position = 0;
mem.Read(buffer, 0, buffer.Length);
return enc.GetString(buffer, 0, buffer.Length);
}
}
voilà, , : P