我的问题的一些背景:
Mvc2似乎有ValidateAntiForgeryTokenAttribute
的变更/错误。
从Mvc1升级到Mvc2时,具有活动会话的用户在使用ValidateAntiForgeryTokenAttribute
请求页面时会收到以下错误:
无法将'System.Web.UI.Triplet'类型的对象强制转换为'System.Object []'。
问题记录在案here。
升级到Mvc2后,我们预计会受到此问题的严重影响。我编写了一个从注释中的代码派生的修复程序(下面记录为后代)。目前,通过创建Controller
和AsyncController
的子类来覆盖Initialize方法来调用此代码,以便纠正问题。 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);
}
}
}
}
}
这样做的结果是我必须改变我的所有控制器类,以从我的新的,更正的Controller子类派生。对于打算在大约一个月的时间内弃用的代码,这似乎非常具有侵扰性。
所以,回答我的问题,我想知道是否有一种较少侵入性的修补现有类的方法,以便不必改变类的下游用户,也许使用反射?
答案 0 :(得分:1)
彭德,
而不是编码每个控制器,使用基本控制器并继承它:
public abstract class BaseController : Controller
{
protected override void Initialize(RequestContext requestContext)
{
base.Initialize(requestContext);
FixAntiForgeryTokenMvc1ToMvc2(this, requestContext);
}
private static void FixAntiForgeryTokenMvc1ToMvc2(
Controller controller, RequestContext requestContext)
{
// stuff ....
}
}
在你的'普通'控制器中,只需:
public class NormalController : BaseController
{
// all the previous stuff
}
试一试......