protected override string GetContextToken(ReponseRepoMonitor repoMon, ScorableResponse scorableResponse)
        {
            int[] itemKey = scorableResponse.GetItemKeyTokens();

            ItemScoreRequestContextToken contextToken = new ItemScoreRequestContextToken()
            {
                clientName       = repoMon.ClientName,
                oppKey           = scorableResponse.OppKey,
                reportingVersion = scorableResponse.ResponseSequence,
                itemBank         = itemKey[0],
                itemID           = itemKey[1],
                TISIP            = repoMon.DBIP,
                TISDbName        = repoMon.DBName,
                environment      = repoMon.Environment,
                itemType         = scorableResponse.Format
            };

            return(EncryptionHelper.EncryptToBase64(JsonHelper.Serialize <ItemScoreRequestContextToken>(contextToken)));  // encrypt token (do not url encode)
        }
        private void ProcessScore(HttpContext context)
        {
            Interlocked.Increment(ref RequestCount);

            // GET RESPONSE
            ItemScoreResponse itemScoreResponse;

            // Get XML
            using (XmlReader reader = XmlReader.Create(context.Request.InputStream))
            {
                itemScoreResponse = HttpWebHelper.DeserializeXml <ItemScoreResponse>(reader);
                reader.Close();
            }

            // get the context token and deserialize it
            string decryptedToken = GetContextToken(itemScoreResponse);
            ItemScoreRequestContextToken tokenData = null;

            // get test data
            try
            {
                tokenData = JsonHelper.Deserialize <ItemScoreRequestContextToken>(decryptedToken);
            }
            catch (Exception ex)
            {
                throw new ApplicationException(String.Format("Could not read contextToken: {0},  Error: {1}.", decryptedToken ?? "(null)", ex.Message));
            }

            // create response
            ScoredResponse scoredResponse = new ScoredResponse()
            {
                ItemKey         = tokenData.ItemKey,
                OppKey          = tokenData.oppKey,
                Sequence        = tokenData.reportingVersion ?? -1,
                Score           = itemScoreResponse.Score.ScoreInfo.Points,
                ScoreStatus     = itemScoreResponse.Score.ScoreInfo.Status.ToString(),
                ScoreRationale  = null,
                ScoreDimensions = HttpWebHelper.SerializeXml(itemScoreResponse.Score.ScoreInfo)
            };

            string hubDBIP     = tokenData.TISIP;
            string hubDBName   = tokenData.TISDbName;
            string clientName  = tokenData.clientName;
            string environment = tokenData.environment;

            // create function for submitting scores
            Action submitScore = delegate
            {
                Interlocked.Increment(ref ProgressCount);

                try
                {
                    if (String.IsNullOrEmpty(hubDBIP))
                    {
                        // must be sending items for scoring in the TDSReport format where we don't send
                        //  this information in the context token.  In this case, we can only support a single configured hub.
                        //  Grab the info from that hub.
                        IAdminRepository     cloudRepository = ServiceLocator.Resolve <IAdminRepository>();
                        List <DataStoreInfo> hubs            = cloudRepository.GetMonitoredDataStores(ScoringDaemonSettings.MachineName);
                        hubs = hubs.FindAll(h => h.ClientName == clientName).ToList <DataStoreInfo>();
                        if (hubs.Count == 0)
                        {
                            throw new ApplicationException(String.Format("No hubs are configured for client: {0} on machine: {1}", clientName, ScoringDaemonSettings.MachineName));
                        }
                        if (hubs.Count > 1)
                        {
                            throw new ApplicationException(String.Format("TIS item scoring callback handler only supports a single hub per client for this type of request.  {0} are configured for client: {1}.", hubs.Count, clientName));
                        }
                        hubDBIP     = ScoringDaemonSettings.HubIP(hubs[0]);
                        hubDBName   = hubs[0].DBName;
                        clientName  = hubs[0].ClientName;
                        environment = hubs[0].Environment;
                    }

                    // Save score to DB
                    IResponseRepository responseRepo = ServiceLocator.Resolve <IResponseRespositoryFactory>()
                                                       .Create(ScoringDaemonSettings.HubConnectionString(hubDBIP, hubDBName), clientName, environment);

                    if (responseRepo == null)
                    {
                        // this is really unusual. We got a item score response for an unknown hub.
                        string errorMessage =
                            String.Format(
                                "Got a score response for a hub that we dont monitor. oppKey:{0}, itemKey: {1}, sequence:{2}, clientName: {3}, environment: {4}",
                                scoredResponse.OppKey, scoredResponse.ItemKey, scoredResponse.Sequence, clientName, environment);
                        throw new InvalidDataException(errorMessage);
                    }

                    //run resolution rule if there is one
                    //Zach 12/11/2014 TODO: Add checks or try/catches around each part of running the rule to give more specific error messages?
                    TISItemResolutionRule rule = TISItemResolutionRule.CreateRule(tokenData.itemType, scoredResponse.ItemKey, clientName);
                    if (rule != null)
                    {
                        TDSQASystemAPI.TestResults.ItemScoreInfo resolvedScore = rule.ResolveItemScore(Serialization.DeserializeXml <TDSQASystemAPI.TestResults.ItemScoreInfo>(scoredResponse.ScoreDimensions));
                        scoredResponse.Score           = (int)resolvedScore.Points;
                        scoredResponse.ScoreStatus     = resolvedScore.Status == TDSQASystemAPI.TestResults.ScoringStatus.Scored ? ScoringStatus.Scored.ToString() : ScoringStatus.ScoringError.ToString();
                        scoredResponse.ScoreDimensions = HttpWebHelper.SerializeXml(resolvedScore);
                    }

                    responseRepo.UpdateItemScore(scoredResponse);
                }
                catch (Exception ex)
                {
                    Interlocked.Decrement(ref ProgressCount);
                    Interlocked.Increment(ref ErrorCount);

                    LastError = String.Format("{0} ({1})", ex.Message, DateTime.Now);

                    // wasn't logging the exception.  See TDS.Shared.Logging.TraceLog.ToString()
                    string id = tokenData == null ? "Unknown" : tokenData.ToString();
                    TDSLogger.Application.Error(new ApplicationException(String.Format("Error submitting callback score for: {0}", id), ex));
                    //TDSLogger.Application.Error(new TraceLog("Error submitting callback score.", ex));

                    return;
                }

                Interlocked.Decrement(ref ProgressCount);
                Interlocked.Increment(ref SuccessCount);
            };

            // check if thread pooling is enabled for callbacks
            if (WorkerPool != null)
            {
                // async
                if (!WorkerPool.Enqueue(submitScore))
                {
                    Interlocked.Increment(ref RejectCount);
                }
            }
            else
            {
                // sync
                submitScore();
            }
        }