// GET: Matches public async Task<ActionResult> Index() { _webClient = GetMatchApiClient(); //need to initialize here since we're using cookie authentication var me = GetMyProfileId(); //Get user's search criteria var criteria = _profileRepo.GetMatchCriteria(me); //check for forceRecalculation flag bool forceRecalc = false; if (Session[OkbConstants.FORCE_RECALCULATE_MATCHES] != null && (bool)Session[OkbConstants.FORCE_RECALCULATE_MATCHES] == true) { forceRecalc = true; } var matches = await GetMatchesAsync(me, criteria, 1, forceRecalc); //first page var vm = new MatchesViewModel { Matches = matches, MatchApiUrl = ConfigurationManager.AppSettings["MatchApiUrl"], StorageUrl = ConfigurationManager.AppSettings["StorageUrl"] + OkbConstants.PHOTO_CONTAINER + "/", MatchCriteria = criteria }; return View(vm); }
protected override void OnActionExecuting(ActionExecutingContext filterContext) { //base.OnActionExecuting(filterContext); _webClient = GetMatchApiClient(); }
/// <summary> /// Add/Updates a user's answer in the database, and then calls MatchApiClient to /// update the cache. Responsible for keeping DB and cache in sync so wraps these /// operations in a transaction. /// /// - If getNextFlag = true get the next 2 questions and return them as JSON /// - Otherwise return the user's validated answer /// - Sets forceRecalculateMatches = true if user answered less than 10 questions (so new users can see results immediately) /// /// More info about TransactionScope (limitations): /// https://msdn.microsoft.com/en-us/data/dn456843.aspx /// /// </summary> public async Task<JsonResult> Answer(AnswerViewModel input, bool getNextFlag = true) { var profileId = GetMyProfileId(); _matchApiClient = GetMatchApiClient(); var answer = new Answer { ProfileId = profileId, QuestionId = (short)input.QuestionId }; //Convert checkboxes to bit array for Acceptable choices byte acceptBits = 0; foreach (var index in input.ChoiceAccept) { acceptBits |= (byte)(1 << (index - 1)); } answer.ChoiceIndex = (byte)input.ChoiceIndex; answer.ChoiceAccept = acceptBits; answer.ChoiceWeight = (byte)input.ChoiceImportance; //We should do some user input validation if(!_quesRepo.ValidateAnswer(answer)) { //invalid answer - return not OK Response.StatusCode = (int)HttpStatusCode.BadRequest; return Json(null); } // Isolation Level: Read Committed // Timeout : 5 minutes var options = new TransactionOptions { IsolationLevel = IsolationLevel.ReadCommitted, Timeout = TimeSpan.FromMinutes(5) }; int count; //Update DB and Cache in a transaction //By default if scope.Complete() isn't called the transaction is rolled back. using (var scope = new TransactionScope(TransactionScopeOption.Required, options, TransactionScopeAsyncFlowOption.Enabled)) { var t1 = _quesRepo.AnswerAsync(answer); var t2 = _matchApiClient.AnswerAsync(answer); //await Task.WhenAll(t1, t2); await t1; count = await t2; scope.Complete(); } //Update the Activity feed if(IsOkToAddActivity(OkbConstants.ActivityCategories.AnsweredQuestion)) { //Get the question text var ques = _quesRepo.GetQuestion(input.QuestionId); var choiceText = ""; choiceText = ques.Choices[((int)answer.ChoiceIndex - 1) % ques.Choices.Count]; _feedRepo.AnsweredQuestionActivity(profileId, ques.Text, choiceText); UpdateActivityLastAdded(OkbConstants.ActivityCategories.AnsweredQuestion); } //set forceRecalculateMatches = true if answered less than 10 questions if (count < 10) { Session[OkbConstants.FORCE_RECALCULATE_MATCHES] = true; } IList<QuestionModel> nextQuestions = null; //Get the next questions if (getNextFlag) { nextQuestions = _quesRepo.Next2Questions(profileId); return Json(nextQuestions); } else { return Json(answer); } }