Some background to my issue:
It appears that there is a change/bug in Mvc2 concerning ValidateAntiForgeryTokenAttribute
.
When upgrading from Mvc1 to Mvc2, users with an active session will receive the following error when they request a page using ValidateAntiForgeryTokenAttribute
:
Unable to cast object of type 'System.Web.UI.Triplet' to type 'System.Object[]'.
The issue is documented here.
After upgrading to Mvc2, we anticipate that we will be seriously affected by this issue. I have coded a fix derived from the code in the comments (documented below for posterity). At the moment this code is invoked by creating a subclass of Controller
and AsyncController
overriding the Initialize method in order to correct the problem. e.g.
public class FixedController:Controller
{
protected override void Initialize(RequestContext requestContext)
{
base.Initialize(requestContext);
this.FixAntiForgeryTokenMvc1ToMvc2(requestContext); //extension
}
}
internal static class ControllerEx
{
public static void FixAntiForgeryTokenMvc1ToMvc2(
this Controller controller,
RequestContext requestContext)
{
var cc = new ControllerContext(requestContext,
controller);
var antiForgeryAttribute = new ValidateAntiForgeryTokenAttribute();
try
{
antiForgeryAttribute.OnAuthorization(new AuthorizationContext(cc));
}
catch (HttpAntiForgeryException forgeryException)
{
var castException = forgeryException.InnerException;
if (castException != null
&& castException is InvalidCastException
&& castException.Message.StartsWith(
"Unable to cast object of type"
+ " 'System.Web.UI.Triplet' to type"
+ " 'System.Object[]'"))
{
var responseTokenCookieNames =
controller
.Response
.Cookies
.Cast<Cookie>()
.Select(c => c.Name)
.Where(n => n.Contains("RequestVerificationToken"));
foreach (var s in responseTokenCookieNames)
{
var cookie = controller.Response.Cookies[s];
if (cookie != null)
{
cookie.Value = "";
}
}
var requestTokenCookieNames =
controller
.Request
.Cookies
.Cast<String>()
.Where(n => n.Contains("RequestVerificationToken"))
.ToList();
foreach (var c in requestTokenCookieNames)
{
controller.Request.Cookies.Remove(c);
}
}
}
}
}
The knock on effect of this is that I must alter all my controller classes to derive from my new, corrected Controller subclasses. This seems quite intrusive for code that intend to deprecate in about a month's time.
So, coming to my question, I'd like to know if there is a less intrusive means of patching existing classes such that downstream users of the class do not have to be altered, perhaps using reflection?