using System; using System.Collections.Generic; using System.Linq; using System.Text.Json; using System.Threading.Tasks; using KBD2.Data; using KBD2.Data.Models; using KBD2.Data.ViewModels; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; namespace KBD2.Pages { public class IndexModel : PageModel { private readonly ApplicationDbContext _context; private readonly ILogger _logger; public IndexModel(ApplicationDbContext context, ILogger logger) { _context = context; _logger = logger; //UserType = SetUserType(); } [BindProperty] public AttemptLogExtraVM AttemptLogExtraData { get; set; } public AttemptLog AttemptLogData { get; private set; } public string UserType { get; private set; } // anon, guest, test or norm /// /// get survey attempt data /// /// status message /// public async Task OnGet(string message) { UserType = SetUserType(); if (message != null) ViewData["Message"] = message; ViewData["StartType"] = "BadQuiz"; // used by form-builder var quizSection = await _context.QSections.OrderBy(s => s.SectionNo).FirstOrDefaultAsync(s => s.Quiz.QuizTitle == "Customer Satisfaction Survey").ConfigureAwait(false); if (quizSection == null) return Page(); //### fetch cookie client // init id's string sQID = quizSection.QuizId; string sUID = ""; if (UserType != "anon") { // logged-in user var vUser = await _context.Users.FirstOrDefaultAsync(u => u.UserName == User.Identity.Name).ConfigureAwait(true); if (vUser != null) sUID = vUser.Id; } // fetch a-l-d AttemptLogData = _context.AttemptLogs.FirstOrDefault(a => (a.QuizId == sQID) && (a.UserId == sUID) && (a.AttemptFinishDTS == null)); //# fetch cookie state string sState = Request.Cookies["SurveyState"]; string sStart = "StartNew"; // default setting if (string.IsNullOrEmpty(sState)) { // first entry if ((UserType == "test") || (UserType == "norm")) { // check for existing survey if (AttemptLogData != null) sStart = "ContinueOrNew"; //else StartNew } //else StartNew } else { // re-entry if (sState == "Started") sStart = "ContinueExisting"; //else StartNew } if (AttemptLogData == null) AttemptLogData = new AttemptLog(); else Response.Cookies.Append("SurveyAttempLogId", AttemptLogData.Id); //### //# bind properies for VM if((UserType == "anon") || (UserType == "guest")) { // bind view-model if (!string.IsNullOrEmpty(sState) && (sState == "Started")) { // re-entry string sExtra = AttemptLogData.AttemptExtra; // json form data AttemptLogExtraData = JsonSerializer.Deserialize(sExtra); } } else { // bind comment, use vm as a-l-d is private if ((!string.IsNullOrEmpty(sState) && (sState == "Started")) || (string.IsNullOrEmpty(sState) && (sStart != "StartNew"))) { // re-entry AttemptLogExtraData = new AttemptLogExtraVM(); AttemptLogExtraData.SurveyComment = AttemptLogData.AttemptExtra; // straight text } } ViewData["StartType"] = sStart; // used by form-builder return Page(); } // end of Get(s)o /// /// Start, Continue or Finish Survey /// /// action /// public async Task OnPostAsync(string id) { UserType = SetUserType(); var quizSection = await _context.QSections.OrderBy(s => s.SectionNo).FirstOrDefaultAsync(s => s.Quiz.QuizTitle == "Customer Satisfaction Survey").ConfigureAwait(false); if (quizSection == null) return NotFound(); if (string.IsNullOrEmpty(id)) return NotFound(); string sAction = id; //# save details in log DateTime dtsStart = DateTime.Now; AttemptLog oAL = null; string sQID = quizSection.QuizId; //# get user-id string sUID = null; if (UserType != "anon") { var vUser = await _context.Users.FirstOrDefaultAsync(u => u.UserName == User.Identity.Name).ConfigureAwait(true); if (vUser != null) sUID = vUser.Id; } string sALID = ""; if (sAction == "Start") { //# start new attempt oAL = new AttemptLog(); oAL.Id = Guid.NewGuid().ToString(); oAL.UserId = sUID; oAL.QuizId = sQID; oAL.AttemptStartDTS = dtsStart; oAL.AttemptFinishDTS = null; oAL.AttemptGrade = 0; if ((UserType == "norm") || (UserType == "test")) oAL.AttemptExtra = AttemptLogExtraData.SurveyComment; else { // concatenate type and detail to form contact AttemptLogExtraData.SurveyContact = AttemptLogExtraData.ContactType + ": " + AttemptLogExtraData.ContactDetail; oAL.AttemptExtra = JsonSerializer.Serialize(AttemptLogExtraData); } //# save new log-record _context.AttemptLogs.Add(oAL); await _context.SaveChangesAsync().ConfigureAwait(false); Response.Cookies.Append("SurveyState", "Started"); //### Response.Cookies.Append("SurveyAttempLogId", oAL.Id); //### // go to survey return RedirectToPage("/CSS_SLG/Survey", new { id = quizSection.Id }); } try { //# get current attempt-log sALID = Request.Cookies["SurveyAttempLogId"]; //### if (string.IsNullOrEmpty(sALID)) throw new ApplicationException("Bad Attempt-Log cookie"); oAL = await _context.AttemptLogs.FirstOrDefaultAsync(a => a.Id == sALID).ConfigureAwait(true); if (oAL == null) throw new ApplicationException("Bad Attempt-Log"); //# update comment etc. string sComment = AttemptLogExtraData.SurveyComment; // get response if ((UserType == "norm") || (UserType == "test")) oAL.AttemptExtra = sComment; else { // update json data, comment for anon and guest AttemptLogExtraData = JsonSerializer.Deserialize(oAL.AttemptExtra); // fetch current data AttemptLogExtraData.SurveyComment = sComment; // update comment oAL.AttemptExtra = JsonSerializer.Serialize(AttemptLogExtraData); // store updated data } if (sAction == "Continue") { // save data and go to survey await _context.SaveChangesAsync().ConfigureAwait(false); Response.Cookies.Append("SurveyState", "Started"); //### return RedirectToPage("/CSS_SLG/Survey", new { id = quizSection.Id }); } //# action=finish, move data and score DateTime dtsFinish = DateTime.Now; // fetch responses var vResp = await _context.Responses.Include(r => r.QOption).Include(r => r.QItem).ThenInclude(i => i.QSection) .Where(r => r.AttemptLogId == sALID).ToListAsync().ConfigureAwait(true); ResponseLog oRL; int nScore = 0; // loop through responses and fill log foreach(var item in vResp) { oRL = new ResponseLog(); oRL.Id = Guid.NewGuid().ToString(); oRL.AttemptLogId = sALID; oRL.ResponseDTS = item.ResponseDTS; oRL.SectionNo = item.QItem.QSection.SectionNo; oRL.SectionText = item.QItem.QSection.SectionText; oRL.ItemNo = item.QItem.ItemNo; oRL.ItemText = item.QItem.ItemText; oRL.ResponseText = item.QOption.OptionText + ((item.ResponseExtra == null) ? "" : ": " + item.ResponseExtra); // build response text oRL.ResponseScore = item.QOption.OptionWeight; nScore += item.QOption.OptionWeight; //### posible check for existing record? _context.ResponseLogs.Add(oRL); // delete response _context.Responses.Remove(item); } //# save logs oAL.AttemptFinishDTS = dtsFinish; oAL.AttemptGrade = nScore; await _context.SaveChangesAsync().ConfigureAwait(false); Response.Cookies.Append("SurveyState", "Finished"); } catch (ApplicationException ex) { return RedirectToAction("OnGetAsync", new { message = ex.Message }); } catch (Exception) { throw; } return RedirectToAction("OnGetAsync"); } // end of Post(s)o private string SetUserType() { if (!User.Identity.IsAuthenticated) return "anon"; // anonymous if (User.IsInRole("Guest")) return "guest"; // guest if (User.IsInRole("Test")) return "test"; // test return "norm"; // normal } // end of UserType()s } }