MVC3会话状态

时间:2014-04-15 21:02:14

标签: asp.net asp.net-mvc-3 session-state

我最近一直在将我的代码重新分解为从inproc转移到Session State。我创建了一个新的类,我从一开始就构建了可序列化的类。我目前正在收到“无法序列化会话状态”。错误。但是,我能够使用JsonConvert(newtonsoft)序列化该类。

不允许使用哪种方法?

这就是它的样子:

[Serializable()]
public class SessionStateObject
{


    public int CurrentSessionId { get; set; }
    public int CurrentAssessmentId { get; set; }
    public int CurrentAssessmentElementId { get; set; }
    public int CurrentUserId { get; set; }

    public Dictionary<string, int> AssessmentItemsIds { get; set; }
    public Dictionary<string, int> SessionResponseIds { get; set; }


    public List<string> AdministeredItemOrderByName;
    public string LastVisitedItem;
    public int? TotalAssessmentCurrentItemOrder;

    public RenderablePersistanceObject RenderablePersistance;



    #region formula engine section variables

    public string BranchingResult { get; set; }
    public string ContentOutput { get; set; }

    public int CurrentItemId { get; set; }
    public int VirtualWorkingItemId { get; set; }


    public bool isCloneItem { get; set; }
    public bool wasPreFormulaRun;
    public bool wasContentOutput;
    public bool wasPrefillReached;
    public bool isVirtual;


    public List<string> FormulaStack { get; set; }
    public List<string> ItemNameTokens { get; set; }
    public string serializedJSContext { get; set; }
    public string CloneSourceItem { get; set; }

    public int itemsAbletoFastForwardThrough { get; set; }

    #endregion

    private Dictionary<int, int> itemIdByMultiGroupId;  //key is itemId, val is groupId
    private Dictionary<int, List<int>> MultiGroupIdByItemIds; //key is groupId, val is itemId



    public SessionStateObject()
    {
        RenderablePersistance = new RenderablePersistanceObject();
        AssessmentItemsIds = new Dictionary<string, int>();
        SessionResponseIds = new Dictionary<string, int>();
        AdministeredItemOrderByName = new List<string>();
        FormulaStack = new List<string>();
        ItemNameTokens = new List<string>();

        itemIdByMultiGroupId = new Dictionary<int, int>();
        MultiGroupIdByItemIds = new Dictionary<int, List<int>>();
    }


    public void initMultiItemGroups(Assessment assessment, NetScidDbContainer dbContext)
    {

        List<MultiItem> assessmentMultiItems = (from multi in dbContext.MultiItems
                                                where multi.AssessmentId == assessment.Id
                                                select multi).ToList();
        List<int> uniqueGroupIds = new List<int>();

        foreach (MultiItem mItem in assessmentMultiItems)
        {
            itemIdByMultiGroupId.Add(mItem.ItemId, mItem.GroupId);
            if (!uniqueGroupIds.Contains(mItem.GroupId))
            {
                uniqueGroupIds.Add(mItem.GroupId);
            }
        }

        foreach (int groupId in uniqueGroupIds)
        {
            List<int> ItemIds = (from itemGroup in assessmentMultiItems
                                 where itemGroup.GroupId == groupId
                                 orderby itemGroup.Id ascending
                                 select itemGroup.ItemId).ToList();
            MultiGroupIdByItemIds.Add(groupId, ItemIds);
        }

    }

    public List<int> GetItemIdsFromSingleItemId(int itemId)
    {
        List<int> foundItemIDs = new List<int>();
        int foundGroupId = -1;
        if (this.itemIdByMultiGroupId.ContainsKey(itemId))
        {
            foundGroupId = this.itemIdByMultiGroupId[itemId];
        }

        if (this.MultiGroupIdByItemIds.ContainsKey(foundGroupId))
        {
            foundItemIDs = this.MultiGroupIdByItemIds[foundGroupId];
        }

        return foundItemIDs;

    }

    public void nullifyRenderable()
    {
        this.RenderablePersistance = null;
    }




    public void PersistRenderable(IRenderable renderable)
    {
        this.RenderablePersistance = new RenderablePersistanceObject();
        if (renderable is MultiItemRenderable)
        {
            //get list of item IDs from the multi-item lookup
            this.RenderablePersistance.isMultiItem = true;
            this.RenderablePersistance.primaryItemId = ((Item)((MultiItemRenderable)renderable).IndexedItems.Last()).Id;
        }
        else  //regular renderable
        {
            this.RenderablePersistance.isMultiItem = false;
            this.RenderablePersistance.primaryItemId = ((Item)renderable).Id;
        }

    }

    public AssessmentRuntime StartAdministrativeSession(NetScidDbContainer dataContext, Assessment assessment, User currentUser, string pid = "1")
    {

        AssessmentRuntime newRuntime = new AssessmentRuntime(this, dataContext);

        Session newSession = new Session();


        assessment.PrepElements();

        PermissionEntity rootPE = new PermissionEntity();

        if (currentUser != null)
        {
            rootPE = PermissionEntityHelper.GetRootPermissionEnity(dataContext, currentUser);
        }
        else
        {
            rootPE = (from adminpe in dataContext.PermissionEntities
                      where adminpe.Name == "TelesageAdmin"
                      select adminpe
                ).FirstOrDefault();
        }
        newSession.Participant = (from pids in dataContext.ParticipantIdAliasLookups
                                  where pid == pids.AliasId && pids.RootPermissionEntity.Id == rootPE.Id
                                  select pids.Participant).FirstOrDefault();


        if (newSession.Participant == null)
        {
            Participant newParticipant = new Participant();
            ParticipantIdAliasLookup newPidAlias = new ParticipantIdAliasLookup();
            newParticipant.ParticipantDataJSON = "";

            newPidAlias.AliasId = pid;
            newPidAlias.RootPermissionEntity = rootPE;

            newParticipant.AliasLookup = newPidAlias;
            newParticipant.PermissionEntities.Add(currentUser.PermissionEntity);
            newParticipant.PermissionEntities.Add(rootPE);

            newSession.Participant = newParticipant;

            dataContext.Participants.AddObject(newParticipant);
            dataContext.ParticipantIdAliasLookups.AddObject(newPidAlias);

        }

        newSession.Assessment = assessment;
        newSession.User = currentUser;
        newSession.StartTime = DateTime.Now;

        newSession.PermissionEntity = currentUser.PermissionEntity;

        newSession.SetSessionData("engineversion", typeof(SmartQWeb.MvcApplication).Assembly.GetName().Version.ToString());
        newSession.SetSessionData("assessmentname", newSession.Assessment.Name);
        newSession.SetSessionData("assessmentversion", newSession.Assessment.Version);
        newSession.SetSessionData("computername", Environment.MachineName);
        newSession.SetSessionData("username", currentUser.Name);



        dataContext.Sessions.AddObject(newSession);

        newSession.SetSessionData("dxdata", JsonConvert.SerializeObject(newRuntime.RenderedDiagnoses));

        newRuntime.formulaEngine = new FixedLengthFormulaEngine(newRuntime);
        SessionLog newSessionLog = new SessionLog();

        dataContext.SessionLogs.AddObject(newSessionLog);
        newSession.SessionLog = newSessionLog;




        dataContext.SaveChanges();

        initMultiItemGroups(assessment, dataContext);

        this.CurrentSessionId = newSession.Id;
        this.CurrentUserId = currentUser.Id;
        this.CurrentAssessmentId = assessment.Id;
        newRuntime.Context = new RuntimeContext(this, dataContext);


        this.GetAssessmentItems(assessment);  //to populate the items dict
        newRuntime.formulaEngine.InitializeContext(this.AssessmentItemsIds.Keys.ToList());
        newRuntime.RenderedDiagnoses = new RenderedDiagnosisModel(newRuntime.Context.AdministeredItemOrderByName);

        newRuntime.Context.Logger.WriteLog("Session started with assessment: " + newRuntime.Context.Assessment.Name + " with version: " + newRuntime.Context.Assessment.Version);
        newRuntime.Context.Logger.WriteLog("Session started by user: " + newRuntime.Context.CurrentUser.Name + "for participant ID: " + newSession.ParticipantId);




        return newRuntime;
    }

    //start from a previous existing session
    public AssessmentRuntime StartAdministrativeSession(NetScidDbContainer dataContext, Assessment assessment, Session previousSession, User currentUser, string pid = "", string resumefromlatest = "false")
    {

        AssessmentRuntime newRuntime = new AssessmentRuntime(this, dataContext);
        Session newSession = new Session();


        Assessment sessionAssessment = assessment;





        newSession.ParticipantId = previousSession.ParticipantId;
        //THE OTHER ENTITIES BESIDES THE SESSION NEED TO BE DETATCHED AND RE-ATTACHED (BY BEING ADDED TO THE NEW SESSION)  
        assessment.PrepElements();
        newRuntime.RenderedDiagnoses = new RenderedDiagnosisModel(newRuntime.Context.AdministeredItemOrderByName);

        List<Response> prevresponses = previousSession.Responses.ToList();

        if (sessionAssessment == assessment)
        {
            foreach (Response prevresponse in prevresponses)
            {
                newRuntime.Context.CachedAssessmentResponses.Add(prevresponse.Item.ItemName, prevresponse);

                dataContext.Detach(prevresponse);

                newSession.Responses.Add(prevresponse);
            }
        }
        else
        {
            //the sessionAssessment is now the more up-to-date one so the responses pulled will have to be mapped, not just detatched and copied
            foreach (Response prevresponse in prevresponses)
            {
                Dictionary<string, FixedLengthItem> newAssessmentItemNames = AssessmentHelper.GetAssessmentItems(sessionAssessment);

                if (!newAssessmentItemNames.ContainsKey(prevresponse.Item.ItemName))
                    continue;

                Response newResponse = new Response
                {
                    NumericValue = prevresponse.NumericValue,
                    Item = newAssessmentItemNames[prevresponse.Item.ItemName],
                    ItemName = prevresponse.Item.ItemName,
                    AdministeredOrder = -1,
                    Value = prevresponse.Value
                };

                newRuntime.Context.CachedAssessmentResponses.Add(newResponse.Item.ItemName, newResponse);

                newSession.Responses.Add(newResponse);
            }



        }
        newSession.SessionDataJSON = previousSession.SessionDataJSON;

        //DxData
        newRuntime.RenderedDiagnoses =
            JsonConvert.DeserializeObject<RenderedDiagnosisModel>(newSession.GetSessionData("dxdata"));



        //inc session is =2 when the the session has been resumed by
        previousSession.IncSession = 2;



        newSession.SetSessionData("previoussession", previousSession.Id.ToString());

        newSession.Participant = previousSession.Participant;

        newSession.Assessment = sessionAssessment;
        newSession.User = currentUser;
        newSession.PermissionEntity = currentUser.PermissionEntity;
        newSession.StartTime = DateTime.Now;
        dataContext.Sessions.AddObject(newSession);



        dataContext.SaveChanges();

        newRuntime.formulaEngine = new FixedLengthFormulaEngine(newRuntime);



        initMultiItemGroups(assessment, dataContext);



        newSession.SetSessionData("continuedsession", newSession.Id.ToString());


        this.CurrentSessionId = newSession.Id;
        this.CurrentUserId = currentUser.Id;
        this.CurrentAssessmentId = assessment.Id;

        this.GetAssessmentItems(assessment);  //to populate the items dict
        this.SetUpPreviousResponses(newSession); //populates SSO responses

        newRuntime.Context = new RuntimeContext(this, dataContext);
        if (newRuntime.RenderedDiagnoses != null)
            newRuntime.RenderedDiagnoses.reInitAdminOrder(newRuntime.Context.AdministeredItemOrderByName);
        newRuntime.formulaEngine.InitializeContext(this.AssessmentItemsIds.Keys.ToList());


        return newRuntime;
    }



    //start from the SSO
    public AssessmentRuntime ResumeSessionFromState(NetScidDbContainer dataContext)
    {

        AssessmentRuntime newRuntime = new AssessmentRuntime(this, dataContext);

        newRuntime.formulaEngine = new FixedLengthFormulaEngine(newRuntime);
        newRuntime.formulaEngine.InitializeSerializedContext(serializedJSContext);

        newRuntime.Context = new RuntimeContext(this, dataContext);
        if (this.CurrentAssessmentElementId != 0)
        {
            newRuntime.CurrentAssessmentElement = (from ae in dataContext.AssessmentElements
                where ae.Id == this.CurrentAssessmentElementId
                select ae).FirstOrDefault();

            newRuntime.CurrentAssessmentElement.GetNewRuntime(newRuntime.Context);
        }
        return newRuntime;
    }



    private void GetAssessmentItems(Assessment assessment)
    {
        var fixedLengthElements = (from elements in assessment.AssessmentElements
                                   where elements is FixedLengthBlock
                                   select elements);

        foreach (FixedLengthBlock elemblock in fixedLengthElements)
        {
            foreach (FixedLengthItem item in elemblock.ItemBank.Items)
            {
                item.aeRef = elemblock;
                AssessmentItemsIds.Add(item.ItemName, item.Id);
            }
        }



    }


    private void SetUpPreviousResponses(Session newSession)
    {

        //put response IDs by itemname into this dictionary

        SessionResponseIds = (from response in newSession.Responses
                              select response).ToDictionary(key => key.ItemName, value => value.Id);

    }








}

RenderablePersistanceObject如下所示:

   public class RenderablePersistanceObject
    {
        public int primaryItemId;
        public int MultiItemGroupId;
        public bool isMultiItem;
    }

2 个答案:

答案 0 :(得分:0)

您不能像这样序列化直字典。您可以查看此MSDN文章,了解有关实施的建议。如果你真的不需要一个词典,也许List&gt;可能会更好吗?

答案 1 :(得分:0)

正如Erik指出的那样,导致问题的另一个对象缺乏装配[Serializable()]。添加它解决了我的问题。