日期:2014-05-20  浏览次数:21046 次

asp.net mvc中使用自定义用户控件遇到mac验证报错
您好 我在view的页面里使用一个form来post back到服务器,其中这个form内含有一个用户控件,控件里有一些文本框,当我post back的时候,出现“验证视图状态 MAC 失败”的错误,就算我在web.config或页面的page里加上EnableEventValidation="false" EnableViewStateMac="false",问题依旧。不知各位有没遇见这种情况,先感谢各位了


====================================================
验证视图状态 MAC 失败。如果此应用程序由网络场或群集承载,请确保 <machineKey> 配置指定了相同的 validationKey 和验证算法。不能在群集中使用 AutoGenerate。 
说明: 执行当前 Web 请求期间,出现未处理的异常。请检查堆栈跟踪信息,以了解有关该错误以及代码中导致错误的出处的详细信息。 

异常详细信息: System.Web.HttpException: 验证视图状态 MAC 失败。如果此应用程序由网络场或群集承载,请确保 <machineKey> 配置指定了相同的 validationKey 和验证算法。不能在群集中使用 AutoGenerate。

源错误: 


行 11: <% using (Html.BeginForm()) {%>
行 12:  
行 13: <% Html.RenderPartial("TestUserControl"); %>
行 14: <!-- header*******start -->
行 15: <div style="background-color:ThreeDFace">
 

源文件: d:\work\AnesthesiologyManagerSystem\Web\Views\Result\Create.aspx 行: 13 



------解决方案--------------------
检查你的页面是不是过于酷炫,如果是,那么然后检查你的页面的ViewState是不是过大,如果也是,那么你的页面应该修改其继承声明代码来使用我这里写的父类:
C# code
using System;
using System.IO;
using System.Linq;
using System.Runtime.Serialization.Formatters.Binary;
using System.Web.UI;

public class XVPage : Page
{
    static private DirectoryInfo _Dir;

    private static DirectoryInfo Dir
    {
        get
        {
            if (_Dir == null)
            {
                _Dir = new DirectoryInfo(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "App_Data"));
                if (!_Dir.Exists)
                    _Dir.Create();
                _Dir = new DirectoryInfo(Path.Combine(_Dir.FullName, "ViewState"));
                if (!_Dir.Exists)
                    _Dir.Create();
            }
            return _Dir;
        }
    }

    protected override object LoadPageStateFromPersistenceMedium()
    {
        PageStatePersister ps = this.PageStatePersister;
        ps.Load();
        if (ps.ControlState != null)
            ps.ControlState = 反序列化对象((string)ps.ControlState);
        if (ps.ViewState != null)
            ps.ViewState = 反序列化对象((string)ps.ViewState);
        return new Pair(ps.ControlState, ps.ViewState);
    }

    protected override void SavePageStateToPersistenceMedium(object state)
    {
        PageStatePersister ps = this.PageStatePersister;
        if (state is Pair)
        {
            ps.ControlState = ((Pair)state).First;
            ps.ViewState = ((Pair)state).Second;
        }
        else
            ps.ViewState = state;
        if (ps.ControlState != null)
            ps.ControlState = 序列化对象(ps.ControlState);
        if (ps.ViewState != null)
            ps.ViewState = 序列化对象(ps.ViewState);
        ps.Save();
    }

    private object 反序列化对象(string stateID)
    {
        if (stateID == null)
            return null;

        object state = Cache[stateID];
        string fname = Path.Combine(Dir.FullName, stateID);
        if (state == null)
            using (var stream = File.OpenRead(fname))
                state = new BinaryFormatter().Deserialize(stream);
        this.Page.SaveStateComplete += (s, e) =>    //当发生异常时,此方法不会执行,因此可以保证不会误删ViewState文件
        {
            Cache.Remove(stateID);
            File.Delete(fname);     //这个方法恰好可以禁止浏览器端的“刷新”。
        };
        return state;
    }

    static long seed1 = DateTime.Now.Ticks;
    static ulong seed2 = 0;

    private string 序列化对象(object obj)
    {
        string stateID = seed1.ToString() + "_" + (seed2++).ToString();
        Cache.Insert(stateID, obj, null, DateTime.Now.AddMinutes(5), TimeSpan.Zero);
        var stream = new MemoryStream();
        new BinaryFormatter().Serialize(stream, obj);
        File.WriteAllBytes(Path.Combine(Dir.FullName, stateID), stream.ToArray());
        return stateID;
    }

    static XVPage()
    {
        var et = DateTime.Now.AddMinutes(-30);
        Dir.GetFiles()
            .Where(f => f.LastAccessTime < et)
            .ToList()
            .ForEach(f =>
            {
                try
                {
                    f.Delete();
                }
                catch { }
            });
    }
}