[SuppressMessage("Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods")] // parameter is validated protected void WriteError(PlainTextString message, bool allowReloadCurrentActivity) { FramesetUtil.ValidateNonNullParameter("message", message); string msgToDisplay; // If the message will contain a link to reload the current activity, then add the link to have the // framesetMgr load the activity. We have to do this (rather than a get request) since we need to // re-initialize the RTE object at this point. if (allowReloadCurrentActivity) { JScriptString js = new JScriptString( ResHelper.FormatInvariant( "API_GetFramesetManager().DoChoice(\"{0}\");", FramesetUtil.GetStringInvariant(this.mSession.CurrentActivityId))); string origMessage = message.ToString(); StringBuilder sb = new StringBuilder(origMessage.Length * 2); sb.Append( ResHelper.Format( "{0}<br><br><a href='{1}' >{2}</a>", origMessage, js.ToJavascriptProtocol(), Localization.GetMessage("HID_ReloadCurrentContent"))); msgToDisplay = sb.ToString(); } else { msgToDisplay = message.ToString(); } this.RegisterError( Localization.GetMessage("HID_ServerErrorTitle"), msgToDisplay, false); }
/// <summary> /// Allow application to process posted data. /// </summary> public bool ProcessPostedData(LearningSession session, HttpRequest request, Dictionary <string, HttpPostedFile> fileCollection) { // Verify that posted files map to files that actually exist. HttpFileCollection files = request.Files; StringBuilder messageBuffer = new StringBuilder(); bool firstError = true; foreach (string fileId in files) { HttpPostedFile postedFile = files[fileId]; string filename = postedFile.FileName; // If contentLength == 0 and fileName == emptyString, then this is probably a posting after // the initial file posting. (For instance, to remove the file.) This is a valid file and is added to the // collection. // If the contentLength == 0 and fileName != emptyString, then user is trying to attach a file // that has no contents. This is not allowed. if ((String.IsNullOrEmpty(filename) && (postedFile.ContentLength == 0)) || (!String.IsNullOrEmpty(filename) && (postedFile.ContentLength > 0))) { fileCollection.Add(fileId, postedFile); } else { // This is not a valid file. if (firstError) { messageBuffer.Append(IUDICO.TestingSystem.Localization.getMessage("CON_AttachedFileDoesNotExistHtml")); messageBuffer.Append("\r\n<br><br><ul>\r\n"); firstError = false; } messageBuffer.AppendFormat("<li>{0}</li>", HttpUtility.HtmlEncode(filename)); } } if (!firstError) { messageBuffer.Append("</ul><br>"); messageBuffer.Append(IUDICO.TestingSystem.Localization.getMessage("CON_FileAttachmentErrorEndHtml")); // Add information for the 'Continue' link JScriptString js = new JScriptString(ResHelper.FormatInvariant("API_GetFramesetManager().DoChoice(\"{0}\");", FramesetUtil.GetStringInvariant(session.CurrentActivityId))); messageBuffer.AppendFormat(CultureInfo.CurrentCulture, "<br><br><a href='{0}' >{1}</a>", js.ToJavascriptProtocol(), HttpUtility.HtmlEncode(IUDICO.TestingSystem.Localization.getMessage("HID_ReloadCurrentContent"))); RegisterError(IUDICO.TestingSystem.Localization.getMessage("CON_FileAttachmentErrorTitleHtml"), messageBuffer.ToString(), false); } return(true); }
// Register with framemanager that loading is complete. This needs to be the final script in the buffer. private void FinishOnLoadScript(StringBuilder scriptBlock) { // Don't do the script block if the content is not LRM. if (Session.CurrentActivityResourceType != ResourceType.Lrm) { return; } // Add the form to post. Need to do it here because we have just allowed the application to set the form // name. scriptBlock.Append("frameMgr.SetPostableForm(document.forms[0]);\r\n"); // Register that the frame loading is complete. This is required so as to notify the frameset of activity id, and // other UI status. scriptBlock.AppendFormat("frameMgr.RegisterFrameLoad({0});\r\n ", JScriptString.QuoteString("frameContent", false)); if (m_isPostedPage) { // Set PostIsComplete. THIS MUST BE THE LAST VALUE SET! scriptBlock.AppendLine("frameMgr.PostIsComplete();"); } }
/// <summary> /// Process the posted data before it is saved by the shared code. This allows checking the file attachments /// and making sure they meet the requirements of the SlkSettings. /// </summary> public bool ProcessPostedData(LearningSession session, HttpRequest request, Dictionary <string, HttpPostedFile> files) { // Save initial value of FinalPoints m_initialTotalPoints = session.TotalPoints; // Check the files for validity and fill in the output collection HttpFileCollection attachedFiles = Request.Files; int numFilesAttached = attachedFiles.Count; if (numFilesAttached > 0) { // Check if posted data meets requirements in SlkSettings. Additionally, check if there are files // that refer to files that do not exist (i.e. have 0 length). int maxKb = SlkStore.Settings.MaxAttachmentKilobytes; ICollection <string> attachmentTypes = SlkStore.Settings.ApprovedAttachmentTypes; List <string> invalidFileAttachments = new List <string>(numFilesAttached); List <string> invalidFileSize = new List <string>(numFilesAttached); List <string> filesDontExist = new List <string>(numFilesAttached); // Keep track of whether there is at least bool hasInvalidFileAttachment = false; bool hasInvalidFileSize = false; bool fileExists = true; // Go through posted files and test if they meet requirements foreach (string fileKey in attachedFiles) { HttpPostedFile file = attachedFiles[fileKey]; bool fileIsValid = true; // is this file a valid file attachment? string filename = file.FileName; // If the filename is empty, the file wasn't actually attached. if (!String.IsNullOrEmpty(filename)) { if (file.ContentLength == 0) { filesDontExist.Add(filename); fileExists = false; fileIsValid = false; } else if ((file.ContentLength / 1024) > maxKb) { invalidFileSize.Add(filename); hasInvalidFileSize = true; fileIsValid = false; } if (!attachmentTypes.Contains(Path.GetExtension(filename))) { invalidFileAttachments.Add(filename); hasInvalidFileAttachment = true; fileIsValid = false; } } // else: The file was valid on a previous posting, so consider it valid here if (fileIsValid) { // Add it to the returned list of valid files files.Add(fileKey, file); } } // if any of the posted files are invalid, then we need to write the message if (hasInvalidFileSize || hasInvalidFileAttachment || !fileExists) { StringBuilder message = new StringBuilder(1000); if (hasInvalidFileAttachment) { message.Append(ResHelper.GetMessage(SlkFrameset.CON_InvalidFileExtensionMsgHtml)); message.Append("<br><br><ul>"); foreach (string filename in invalidFileAttachments) { message.AppendFormat("<li>{0}</li>", SlkUtilities.GetHtmlEncodedText(filename)); } message.Append("</ul>"); } if (hasInvalidFileSize) { message.AppendFormat(ResHelper.GetMessage(SlkFrameset.CON_MaxFileSizeExceededMsgHtml, Convert.ToString(maxKb, CultureInfo.CurrentCulture.NumberFormat))); message.Append("<br><br><ul>"); foreach (string filename in invalidFileSize) { message.AppendFormat("<li>{0}</li>", SlkUtilities.GetHtmlEncodedText(filename)); } message.Append("</ul>"); } if (!fileExists) { message.AppendFormat(SlkFrameset.CON_FilesDontExistHtml); message.Append("<br><br><ul>"); foreach (string filename in filesDontExist) { message.AppendFormat("<li>{0}</li>", SlkUtilities.GetHtmlEncodedText(filename)); } message.Append("</ul>"); } // If one of the cases that relates to SLK settings is true, then tell user that there are settings // that affect the error if (hasInvalidFileSize || hasInvalidFileAttachment) { message.AppendFormat(CultureInfo.InvariantCulture, "{0}<br><br>", ResHelper.GetMessage(SlkFrameset.CON_InvalidFileAttachmentMsgHtml)); } message.Append(FramesetResources.CON_FileAttachmentErrorEndHtml); // Add information for the 'Continue' link JScriptString js = new JScriptString(ResHelper.FormatInvariant("API_GetFramesetManager().DoChoice(\"{0}\");", FramesetUtil.GetStringInvariant(session.CurrentActivityId))); message.AppendFormat(CultureInfo.InvariantCulture, "<br><br><a href='{0}' >{1}</a>", js.ToJavascriptProtocol(), HttpUtility.HtmlEncode(FramesetResources.HID_ReloadCurrentContent)); RegisterError(SlkFrameset.CON_InvalidFileAttachmentTitleHtml, message.ToString(), false); } } return(true); }
public void UpdateRenderContext(RenderContext context, StringBuilder scriptBlock, LearningSession session) { // Set values other than OutputStream and RelativePath context.EmbeddedUIResourcePath = new Uri(SlkEmbeddedUIPath, "Images/"); SetMimeTypeMapping(context.MimeTypeMapping); SetIisCompatibilityModeExtensions(context.IisCompatibilityModeExtensions); // If this is not the primary resource, nothing else matters. if (scriptBlock == null) { return; } LearnerAssignmentProperties la = GetLearnerAssignment(); switch (AssignmentView) { case AssignmentView.Execute: { context.ShowCorrectAnswers = false; context.ShowReviewerInformation = false; } break; case AssignmentView.StudentReview: { context.ShowCorrectAnswers = la.Assignment.ShowAnswersToLearners; context.ShowReviewerInformation = false; } break; case AssignmentView.InstructorReview: { context.ShowCorrectAnswers = true; context.ShowReviewerInformation = true; } break; case AssignmentView.Grading: { context.ShowCorrectAnswers = true; context.ShowReviewerInformation = true; } break; } // Update hidden controls and script to include assignment information if there is script // information to be written. Only write script in LRM content. if ((scriptBlock != null) && (session.CurrentActivityResourceType == ResourceType.Lrm)) { WriteSlkMgrInit(scriptBlock); scriptBlock.AppendLine("slkMgr = Slk_GetSlkManager();"); context.FormHiddenControls.Add(HiddenFieldNames.LearnerAssignmentId, FramesetUtil.GetStringInvariant(la.LearnerAssignmentId.GetKey())); scriptBlock.AppendFormat("slkMgr.LearnerAssignmentId = document.getElementById({0}).value;\r\n", JScriptString.QuoteString(HiddenFieldNames.LearnerAssignmentId, false)); context.FormHiddenControls.Add(HiddenFieldNames.LearnerAssignmentStatus, SlkUtilities.GetLearnerAssignmentState(la.Status)); scriptBlock.AppendFormat("slkMgr.Status = document.getElementById({0}).value;\r\n", JScriptString.QuoteString(HiddenFieldNames.LearnerAssignmentStatus, false)); // Set the change in final points. This can only happen in grading. if (AssignmentView == AssignmentView.Grading) { string finalPointsValue = "null"; float? finalPoints = la.FinalPoints; if (finalPoints != null) { // FinalPoints is invariant culture finalPointsValue = Convert.ToString(finalPoints.Value, CultureInfo.InvariantCulture.NumberFormat); } scriptBlock.AppendFormat("slkMgr.FinalPoints = {0};\r\n", finalPointsValue); } // Send information about total points (ie, computed points on the client). if (session != null) { if (session.TotalPoints != null) { // TotalPoints is passed in current culture, as a string JScriptString totalPointsValue = JScriptString.QuoteString(Convert.ToString(session.TotalPoints, CultureInfo.CurrentCulture.NumberFormat), false); scriptBlock.AppendFormat("slkMgr.ComputedPoints = {0};\r\n", totalPointsValue); } else { scriptBlock.Append("slkMgr.ComputedPoints = \"\";\r\n"); } if (session.SuccessStatus != SuccessStatus.Unknown) { scriptBlock.AppendFormat("slkMgr.PassFail = {0};\r\n", JScriptString.QuoteString(((session.SuccessStatus == SuccessStatus.Passed) ? "passed" : "failed"), false)); } } } }
// it's not worth changing this now private void InitHiddenControlInfo() { HiddenControlInfo hiddenCtrlInfo; Collection<HiddenControlInfo> hiddenControlInfos = this.HiddenControls; StringBuilder sb; // If the session is attempt-based, then write attempt information if (this.Session != null) { hiddenCtrlInfo = new HiddenControlInfo(); hiddenCtrlInfo.Id = new PlainTextString(HiddenFieldNames.AttemptId); hiddenCtrlInfo.Value = new PlainTextString(FramesetUtil.GetString(this.Session.AttemptId)); hiddenCtrlInfo.FrameManagerInitializationScript = new JScriptString( ResHelper.FormatInvariant( "frameMgr.SetAttemptId(document.getElementById({0}).value);", JScriptString.QuoteString(HiddenFieldNames.AttemptId, false))); hiddenControlInfos.Add(hiddenCtrlInfo); } // If the session has ended (that is, is suspended, completed or abandoned), then just // tell the framesetmgr and return. Nothing else is required on the client. if (this.SessionIsEnded) { hiddenCtrlInfo = new HiddenControlInfo(); hiddenCtrlInfo.Id = null; // no data to save hiddenCtrlInfo.Value = null; hiddenCtrlInfo.FrameManagerInitializationScript = new JScriptString( ResHelper.Format( "frameMgr.TrainingComplete({0}, {1});", JScriptString.QuoteString(this.mSessionEndedMsgTitle, false), JScriptString.QuoteString(this.mSessionEndedMsg, false))); hiddenControlInfos.Add(hiddenCtrlInfo); hiddenCtrlInfo = new HiddenControlInfo(); hiddenCtrlInfo.Id = null; // no data to save hiddenCtrlInfo.Value = null; hiddenCtrlInfo.FrameManagerInitializationScript = new JScriptString(ResHelper.Format("frameMgr.ShowStatisticResults();")); hiddenControlInfos.Add(hiddenCtrlInfo); return; } // Write view to display. hiddenCtrlInfo = new HiddenControlInfo(); hiddenCtrlInfo.Id = new PlainTextString(HiddenFieldNames.View); hiddenCtrlInfo.Value = new PlainTextString(FramesetUtil.GetString(this.Session.View)); hiddenCtrlInfo.FrameManagerInitializationScript = new JScriptString( ResHelper.FormatInvariant( "frameMgr.SetView(document.getElementById({0}).value);", JScriptString.QuoteString(HiddenFieldNames.View, false))); hiddenControlInfos.Add(hiddenCtrlInfo); // Write frame and form to post. They depend on whether this is LRM content or SCORM content. If the submit // page is being displayed, it is always this hidden frame that is posted. PlainTextString frameName; JScriptString postableFormScript; hiddenCtrlInfo = new HiddenControlInfo(); hiddenCtrlInfo.Id = new PlainTextString(HiddenFieldNames.PostFrame); // Post the content frame on the next post if LRM content is being displayed. if (!this.mSaveOnly && !this.SubmitPageDisplayed && !this.HasError && (this.Session.HasCurrentActivity && (this.Session.CurrentActivityResourceType == ResourceType.Lrm))) { frameName = new PlainTextString("frameContent"); postableFormScript = new JScriptString("frameMgr.SetPostableForm(GetContentFrame().contentWindow.document.forms[0]);"); } else { // Post hidden frame if there is no current activity, if the current activity is not LRM content, or // if there is an error being displayed. This may happen if the current // activity was exited or suspended and a new activity was not automagically determined. frameName = new PlainTextString("frameHidden"); postableFormScript = new JScriptString("frameMgr.SetPostableForm(document.forms[0]);"); } hiddenCtrlInfo.Value = frameName; hiddenCtrlInfo.FrameManagerInitializationScript = new JScriptString( ResHelper.FormatInvariant( "frameMgr.SetPostFrame(document.getElementById({0}).value);", JScriptString.QuoteString(HiddenFieldNames.PostFrame, false))); hiddenControlInfos.Add(hiddenCtrlInfo); // Set postable form. hiddenCtrlInfo = new HiddenControlInfo(); hiddenCtrlInfo.FrameManagerInitializationScript = postableFormScript; hiddenControlInfos.Add(hiddenCtrlInfo); // If a new activity has been identified, then instruct frameMgr to reinitialize the RTE. // BE CAREFUL to do this before setting any other data related to the rte! if (this.ActivityHasChanged && !this.SubmitPageDisplayed) { hiddenCtrlInfo = new HiddenControlInfo(); hiddenCtrlInfo.Id = null; // No need to save data. Just write the script command hiddenCtrlInfo.Value = null; string initNewActivity = "false"; if (this.Session.HasCurrentActivity) { initNewActivity = (this.CurrentActivityRequiresRte ? "true" : "false"); } hiddenCtrlInfo.FrameManagerInitializationScript = new JScriptString(ResHelper.FormatInvariant("frameMgr.InitNewActivity( {0} );", initNewActivity)); hiddenControlInfos.Add(hiddenCtrlInfo); } // Write the current activity Id if it has changed. // Write "SUBMIT" if the submit page is being shown. Otherwise, write -1 if there isn't a current activity. hiddenCtrlInfo = new HiddenControlInfo(); hiddenCtrlInfo.Id = new PlainTextString(HiddenFieldNames.ActivityId); PlainTextString setValue; // the value to set in the frameMgr for the current activity id. if (this.SubmitPageDisplayed) { setValue = new PlainTextString(SubmitId); } else { // Only set the actual activity id if this is the first rendering or if it has changed in this rendering, // and if there is a current activity. if (this.mIsFramesetInitialization || this.ActivityHasChanged) { setValue = new PlainTextString( this.Session.HasCurrentActivity ? FramesetUtil.GetStringInvariant(this.Session.CurrentActivityId) : "-1"); } else { setValue = new PlainTextString("-1"); } } // The value of the field is always the current activity id. The value the frameMgr gets is the value of the TOC element. hiddenCtrlInfo.Value = new PlainTextString( this.Session.HasCurrentActivity ? FramesetUtil.GetStringInvariant(this.Session.CurrentActivityId) : "-1"); hiddenCtrlInfo.FrameManagerInitializationScript = new JScriptString( ResHelper.FormatInvariant( "frameMgr.SetActivityId({0});", JScriptString.QuoteString(setValue, false))); hiddenControlInfos.Add(hiddenCtrlInfo); // Write the navigation control state. Format of the control state is a series of T (to show) or F (to hide) // values, separated by semi-colons. The order of controls is: // showNext, showPrevious, showAbandon, showExit, showSave hiddenCtrlInfo = new HiddenControlInfo(); // Issue: What is the hidden field used for? hiddenCtrlInfo.Id = new PlainTextString(HiddenFieldNames.ShowUI); sb = new StringBuilder(10); sb.Append((this.Session.ShowNext) ? "T" : "F"); sb.Append(";"); sb.Append((this.Session.ShowPrevious) ? "T" : "F"); sb.Append(";"); sb.Append((this.Session.ShowAbandon) ? "T" : "F"); sb.Append(";"); sb.Append((this.Session.ShowExit) ? "T" : "F"); sb.Append(";"); sb.Append((this.Session.ShowSave) ? "T" : "F"); sb.Append(";"); hiddenCtrlInfo.Value = new PlainTextString(sb.ToString()); sb = new StringBuilder(1000); sb.Append(string.Empty); if (this.SubmitPageDisplayed) { // If the submit page is being displayed, don't show UI elements sb.Append( ResHelper.FormatInvariant( "frameMgr.SetNavVisibility( {0}, {1}, {2}, {3}, {4});", ("false"), // showNext ("false"), // showPrevious ("false"), // showAbandon ("false"), // showExit ("false"))); // showSave } else { sb.Append( ResHelper.FormatInvariant( "frameMgr.SetNavVisibility( {0}, {1}, {2}, {3}, {4});", (this.Session.ShowNext ? "true" : "false"), (this.Session.ShowPrevious ? "true" : "false"), (this.Session.ShowAbandon ? "true" : "false"), (this.Session.ShowExit ? "true" : "false"), (this.Session.ShowSave ? "true" : "false"))); } hiddenCtrlInfo.FrameManagerInitializationScript = new JScriptString(sb.ToString()); hiddenControlInfos.Add(hiddenCtrlInfo); // If there was an error, write it to the client. Note that if the submit page is being rendered, this code // will execute, as it appears in the same form as an error message. if (!string.IsNullOrEmpty(this.ErrorMessage)) { hiddenCtrlInfo = new HiddenControlInfo(); hiddenCtrlInfo.Id = new PlainTextString(HiddenFieldNames.ErrorMessage); hiddenCtrlInfo.Value = this.ErrorMessage; if (string.IsNullOrEmpty(this.ErrorTitle)) { hiddenCtrlInfo.FrameManagerInitializationScript = new JScriptString( ResHelper.Format( "frameMgr.SetErrorMessage(document.getElementById({0}).value);", JScriptString.QuoteString(HiddenFieldNames.ErrorMessage, false))); } else { hiddenCtrlInfo.FrameManagerInitializationScript = new JScriptString( ResHelper.Format( "frameMgr.SetErrorMessage(document.getElementById({0}).value, {1}, {2});", JScriptString.QuoteString(HiddenFieldNames.ErrorMessage, false), JScriptString.QuoteString(this.ErrorTitle, false), this.ErrorAsInfo ? "true" : "false")); } hiddenControlInfos.Add(hiddenCtrlInfo); } // If this is the first time rendering the frameset, need to write initialization information. if (this.mIsFramesetInitialization) { hiddenCtrlInfo = new HiddenControlInfo(); hiddenCtrlInfo.Id = new PlainTextString(HiddenFieldNames.Title); hiddenCtrlInfo.Value = this.GetSessionTitle(this.Session).ToHtmlString().ToString(); hiddenCtrlInfo.FrameManagerInitializationScript = new JScriptString( ResHelper.Format( "frameMgr.SetTitle(document.getElementById({0}).value);", JScriptString.QuoteString(HiddenFieldNames.Title, false))); hiddenControlInfos.Add(hiddenCtrlInfo); } else { // Only update the toc when this is not the first rendering of the frameset. (The first time, the toc page itself // will get it correct. hiddenCtrlInfo = new HiddenControlInfo(); hiddenCtrlInfo.Id = new PlainTextString(HiddenFieldNames.TocState); hiddenCtrlInfo.Value = new PlainTextString(this.GetTocStates()); hiddenCtrlInfo.FrameManagerInitializationScript = new JScriptString( ResHelper.FormatInvariant( "frameMgr.SetTocNodes(document.getElementById({0}).value);", JScriptString.QuoteString(HiddenFieldNames.TocState, false))); hiddenControlInfos.Add(hiddenCtrlInfo); } // Write content href value (value to GET into content frame) -- only if it's required hiddenCtrlInfo = new HiddenControlInfo(); hiddenCtrlInfo.Id = new PlainTextString(HiddenFieldNames.ContentHref); sb = new StringBuilder(4096); // If we need to load the content frame because the current activity changed, or we need to render the content // frame URL because there was an error, then figure out the content frame URL. if (this.LoadContentFrame || this.HasError) { // The activity has changed, so find the new Url for the content frame. if (this.Session.HasCurrentActivity) { sb.Append(this.GetContentFrameUrl()); } } hiddenCtrlInfo.Value = new PlainTextString(new UrlString(sb.ToString()).ToAscii()); hiddenCtrlInfo.FrameManagerInitializationScript = new JScriptString( ResHelper.Format( "frameMgr.SetContentFrameUrl(document.getElementById({0}).value);", JScriptString.QuoteString(HiddenFieldNames.ContentHref, false))); hiddenControlInfos.Add(hiddenCtrlInfo); // Write the data model information, only if the current activity requires it. if (!this.SubmitPageDisplayed && this.CurrentActivityRequiresRte) { // There are 3 controls to update: the data model values and the map between n and id for interactions and objectives RteDataModelConverter converter = RteDataModelConverter.Create(this.Session); DataModelValues dataModelValues = converter.GetDataModelValues(this.FormatDataModelValueForClient); hiddenCtrlInfo = new HiddenControlInfo(); hiddenCtrlInfo.Id = new PlainTextString(HiddenFieldNames.ObjectiveIdMap); hiddenCtrlInfo.Value = dataModelValues.ObjectiveIdMap; hiddenCtrlInfo.FrameManagerInitializationScript = null; hiddenControlInfos.Add(hiddenCtrlInfo); hiddenCtrlInfo = new HiddenControlInfo(); hiddenCtrlInfo.Id = new PlainTextString(HiddenFieldNames.DataModel); hiddenCtrlInfo.Value = dataModelValues.Values; StringBuilder initCommand = new StringBuilder(1000); initCommand.AppendLine( ResHelper.Format( "var hidDM = document.getElementById({0});", JScriptString.QuoteString(HiddenFieldNames.DataModel, false))); initCommand.AppendLine( ResHelper.Format( "var hidObjectiveMap = document.getElementById({0});", JScriptString.QuoteString(HiddenFieldNames.ObjectiveIdMap, false))); initCommand.Append("frameMgr.InitDataModelValues(hidDM.value, hidObjectiveMap.value);"); initCommand.AppendFormat("hidDM.value = {0};", JScriptString.QuoteString(string.Empty, false)); initCommand.AppendFormat("hidObjectiveMap.value = {0};", JScriptString.QuoteString(string.Empty, false)); hiddenCtrlInfo.FrameManagerInitializationScript = new JScriptString(initCommand.ToString()); hiddenControlInfos.Add(hiddenCtrlInfo); } // If there was an IsMove*Valid request, send the response if (this.mIsNavValidResponse != null) { hiddenCtrlInfo = new HiddenControlInfo(); hiddenCtrlInfo.Id = new PlainTextString(HiddenFieldNames.IsNavigationValidResponse); hiddenCtrlInfo.Value = this.mIsNavValidResponse.ClientFieldResponse; hiddenCtrlInfo.FrameManagerInitializationScript = new JScriptString( ResHelper.FormatInvariant( "frameMgr.SetIsNavigationValid(document.getElementById({0}).value);", JScriptString.QuoteString(HiddenFieldNames.IsNavigationValidResponse, false))); hiddenControlInfos.Add(hiddenCtrlInfo); } if (this.mIsPostedPage) { // Set PostIsComplete. THIS MUST BE THE LAST VALUE SET! hiddenCtrlInfo = new HiddenControlInfo(); hiddenCtrlInfo.FrameManagerInitializationScript = new JScriptString("frameMgr.PostIsComplete();"); hiddenControlInfos.Add(hiddenCtrlInfo); } }
/// <summary> /// Write the script to initialize the frameset manager. /// </summary> public void WriteFrameMgrInit() { // If the page did not load successfully, just make sure the error string gets written. if (!this.mPageLoadSuccessful) { // If there is an error, then write it. Basically, there are cases where the page did not // load enough to write out the message earlier. if (!string.IsNullOrEmpty(this.ErrorMessage)) { JScriptString js = new JScriptString( ResHelper.Format( "frameMgr.SetErrorMessage({0});", JScriptString.QuoteString(this.ErrorMessage, false))); this.Response.Write(js.ToString()); this.Response.Write("\r\n"); } if (this.mIsPostedPage) { // Clear any state waiting for additional information JScriptString js = new JScriptString("frameMgr.WaitForContentCompleted(0);"); this.Response.Write(js.ToString()); this.Response.Write("\r\n"); } return; } foreach (HiddenControlInfo ctrlInfo in this.mHiddenControlInfos) { // Some cases do not have code to initialize frameMgr if (ctrlInfo.FrameManagerInitializationScript != null) { this.Response.Write(ctrlInfo.FrameManagerInitializationScript.ToString()); this.Response.Write("\r\n"); } } }
[SuppressMessage("Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods")] // parameter is validated protected void WriteError(PlainTextString message, bool allowReloadCurrentActivity) { FramesetUtil.ValidateNonNullParameter("message", message); string msgToDisplay; // If the message will contain a link to reload the current activity, then add the link to have the // framesetMgr load the activity. We have to do this (rather than a get request) since we need to // re-initialize the RTE object at this point. if (allowReloadCurrentActivity) { JScriptString js = new JScriptString(ResHelper.FormatInvariant("API_GetFramesetManager().DoChoice(\"{0}\");", FramesetUtil.GetStringInvariant(m_session.CurrentActivityId))); string origMessage = message.ToString(); StringBuilder sb = new StringBuilder(origMessage.Length * 2); sb.Append(ResHelper.Format("{0}<br><br><a href='{1}' >{2}</a>",origMessage, js.ToJavascriptProtocol(), IUDICO.TestingSystem.Localization.getMessage("HID_ReloadCurrentContent"))); msgToDisplay = sb.ToString(); } else { msgToDisplay = message.ToString(); } RegisterError(IUDICO.TestingSystem.Localization.getMessage("HID_ServerErrorTitle"), msgToDisplay, false); }
/// <summary> /// Allow application to process posted data. /// </summary> public bool ProcessPostedData(LearningSession session, HttpRequest request, Dictionary<string, HttpPostedFile> fileCollection) { // Verify that posted files map to files that actually exist. HttpFileCollection files = request.Files; StringBuilder messageBuffer = new StringBuilder(); bool firstError = true; foreach (string fileId in files) { HttpPostedFile postedFile = files[fileId]; string filename = postedFile.FileName; // If contentLength == 0 and fileName == emptyString, then this is probably a posting after // the initial file posting. (For instance, to remove the file.) This is a valid file and is added to the // collection. // If the contentLength == 0 and fileName != emptyString, then user is trying to attach a file // that has no contents. This is not allowed. if ((String.IsNullOrEmpty(filename) && (postedFile.ContentLength == 0)) || (!String.IsNullOrEmpty(filename) && (postedFile.ContentLength > 0))) { fileCollection.Add(fileId, postedFile); } else { // This is not a valid file. if (firstError) { messageBuffer.Append(IUDICO.TestingSystem.Localization.getMessage("CON_AttachedFileDoesNotExistHtml")); messageBuffer.Append("\r\n<br><br><ul>\r\n"); firstError = false; } messageBuffer.AppendFormat("<li>{0}</li>", HttpUtility.HtmlEncode(filename)); } } if (!firstError) { messageBuffer.Append("</ul><br>"); messageBuffer.Append(IUDICO.TestingSystem.Localization.getMessage("CON_FileAttachmentErrorEndHtml")); // Add information for the 'Continue' link JScriptString js = new JScriptString(ResHelper.FormatInvariant("API_GetFramesetManager().DoChoice(\"{0}\");", FramesetUtil.GetStringInvariant(session.CurrentActivityId))); messageBuffer.AppendFormat(CultureInfo.CurrentCulture, "<br><br><a href='{0}' >{1}</a>", js.ToJavascriptProtocol(), HttpUtility.HtmlEncode(IUDICO.TestingSystem.Localization.getMessage("HID_ReloadCurrentContent"))); RegisterError(IUDICO.TestingSystem.Localization.getMessage("CON_FileAttachmentErrorTitleHtml"), messageBuffer.ToString(), false); } return true; }
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] // exceptions caught, added to event log protected void Page_Load(object sender, EventArgs e) { try { SlkUtilities.RetryOnDeadlock(delegate() { //Initialize data that may need to be reset on retry Response.Clear(); ClearError(); m_sessionEnded = false; m_hiddenHelper = new HiddenHelper(Request, Response, SlkEmbeddedUIPath); m_hiddenHelper.ProcessPageLoad(SlkStore.PackageStore, GetSessionTitle, TryGetSessionView, TryGetAttemptId, AppendContentFrameDetails, RegisterError, GetErrorInfo, ProcessSessionEnd, ProcessViewRequest, GetMessage, IsPostBack); // Send assignment information to client. If the session has ended, then force a reload of the current // assignment properties. Otherwise, the cached value will have required info so no need to re-query database. LearnerAssignmentProperties la = GetLearnerAssignment(SessionEnded); // Add assignment information to the hidden controls HiddenControlInfo hiddenCtrlInfo = new HiddenControlInfo(); hiddenCtrlInfo.Id = new PlainTextString(HiddenFieldNames.LearnerAssignmentId); hiddenCtrlInfo.Value = new PlainTextString(FramesetUtil.GetStringInvariant(la.LearnerAssignmentId.GetKey())); hiddenCtrlInfo.FrameManagerInitializationScript = new JScriptString(ResHelper.Format("slkMgr.LearnerAssignmentId = document.getElementById({0}).value;", JScriptString.QuoteString(HiddenFieldNames.LearnerAssignmentId, false))); m_hiddenHelper.HiddenControls.Add(hiddenCtrlInfo); // Learner assignment status ('not started', 'in progress', etc) hiddenCtrlInfo = new HiddenControlInfo(); hiddenCtrlInfo.Id = new PlainTextString(HiddenFieldNames.LearnerAssignmentStatus); hiddenCtrlInfo.Value = new PlainTextString(SlkUtilities.GetLearnerAssignmentState(la.Status)); hiddenCtrlInfo.FrameManagerInitializationScript = new JScriptString(ResHelper.Format("slkMgr.Status = document.getElementById({0}).value;", JScriptString.QuoteString(HiddenFieldNames.LearnerAssignmentStatus, false))); m_hiddenHelper.HiddenControls.Add(hiddenCtrlInfo); hiddenCtrlInfo = new HiddenControlInfo(); if (la.FinalPoints != null) { // finalPoints is passed in invariant culture, as a float hiddenCtrlInfo.FrameManagerInitializationScript = new JScriptString(ResHelper.Format("slkMgr.FinalPoints = {0};", Convert.ToString(la.FinalPoints, CultureInfo.InvariantCulture.NumberFormat))); } else { hiddenCtrlInfo.FrameManagerInitializationScript = new JScriptString("slkMgr.FinalPoints = null;"); } m_hiddenHelper.HiddenControls.Add(hiddenCtrlInfo); // Send information about total points (ie, computed points on the client). This is called 'graded score' in // grading page. LearningSession session = m_hiddenHelper.Session; if (session != null) { hiddenCtrlInfo = new HiddenControlInfo(); if (session.TotalPoints != null) { // TotalPoints is passed in current culture, as a string JScriptString totalPointsValue = JScriptString.QuoteString(Convert.ToString(session.TotalPoints, CultureInfo.CurrentCulture.NumberFormat), false); hiddenCtrlInfo.FrameManagerInitializationScript = new JScriptString(ResHelper.Format("slkMgr.ComputedPoints = {0};", totalPointsValue)); } else { hiddenCtrlInfo.FrameManagerInitializationScript = new JScriptString("slkMgr.ComputedPoints = \"\";"); } m_hiddenHelper.HiddenControls.Add(hiddenCtrlInfo); if (session.SuccessStatus != SuccessStatus.Unknown) { hiddenCtrlInfo = new HiddenControlInfo(); hiddenCtrlInfo.FrameManagerInitializationScript = new JScriptString(ResHelper.Format("slkMgr.PassFail = {0};\r\n", JScriptString.QuoteString(((session.SuccessStatus == SuccessStatus.Passed) ? "passed" : "failed"), false))); m_hiddenHelper.HiddenControls.Add(hiddenCtrlInfo); } } }); } catch (Exception ex) { ClearError(); // Unexpected exceptions are not shown to user SlkStore.LogError(FramesetResources.FRM_UnknownExceptionMsg, ex.ToString()); RegisterError(ResHelper.GetMessage(FramesetResources.FRM_UnknownExceptionTitle), ResHelper.GetMessage(SlkFrameset.FRM_UnexpectedExceptionMsg), false); } }
SuppressMessage("Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods")] // parameter is validated public void ProcessSessionEnd(LearningSession session, ref string messageTitle, ref string message) { FramesetUtil.ValidateNonNullParameter("session", session); // If we have already been here, then there is nothing more to do. if (SessionEnded) { return; } LearnerAssignmentProperties la = GetLearnerAssignment(); // Session ending results in message shown to the user. if (session.View == SessionView.Execute) { StoredLearningSession slsSession = session as StoredLearningSession; if (slsSession != null) { // The rollup and/or sequencing process may have changed the state of the attempt. If so, there are some cases // that cannot continue so show an error message. switch (slsSession.AttemptStatus) { case AttemptStatus.Abandoned: messageTitle = SlkFrameset.HID_SessionAbandonedTitle; message = SlkFrameset.HID_ExecuteViewAbandonedSessionMsg; SessionEnded = true; break; case AttemptStatus.Completed: messageTitle = SlkFrameset.HID_SessionCompletedTitle; message = SlkFrameset.HID_ExecuteViewCompletedSessionMsg; SessionEnded = true; break; case AttemptStatus.Suspended: messageTitle = SlkFrameset.HID_SessionSuspendedTitle; message = SlkFrameset.HID_ExecuteViewSuspendedSessionMsg; // Do not set SessionEnded -- the session being suspended does not warrant ending the learner assignment break; } } if (SessionEnded) { // Call FinishLearnerAssignment since the attempt has already been completed. SlkStore.FinishLearnerAssignment(LearnerAssignmentGuidId); } } else if (session.View == SessionView.RandomAccess) { messageTitle = SlkFrameset.HID_GradingFinishedTitle; message = SlkFrameset.HID_GradingFinishedMessage; StringBuilder sb = new StringBuilder(1000); sb.Append(message); sb.Append("<br><script>"); // Write the assignment status to slkFrameMgr WriteSlkMgrInit(sb); sb.AppendLine("slkMgr = Slk_GetSlkManager();"); sb.AppendFormat("slkMgr.LearnerAssignmentId = {0};\r\n", JScriptString.QuoteString(FramesetUtil.GetStringInvariant(la.LearnerAssignmentId.GetKey()), false)); sb.AppendFormat("slkMgr.Status = {0};\r\n", JScriptString.QuoteString(SlkUtilities.GetLearnerAssignmentState(la.Status), false)); if (AssignmentView == AssignmentView.Grading) { string finalPointsValue = "null"; float? finalPoints = la.FinalPoints; if (finalPoints != null) { finalPointsValue = Convert.ToString(finalPoints.Value, CultureInfo.InvariantCulture.NumberFormat); } sb.AppendFormat("slkMgr.FinalPoints = {0};\r\n", finalPointsValue); } // Send information about total points (ie, computed points on the client). if (session != null) { if (session.TotalPoints != null) { sb.AppendFormat("slkMgr.ComputedPoints = {0};\r\n", JScriptString.QuoteString(Convert.ToString(session.TotalPoints, CultureInfo.CurrentCulture.NumberFormat), false)); } else { sb.AppendFormat("slkMgr.ComputedPoints = \"\";\r\n"); } if (session.SuccessStatus != SuccessStatus.Unknown) { sb.AppendFormat("slkMgr.PassFail = {0};\r\n", JScriptString.QuoteString(((session.SuccessStatus == SuccessStatus.Passed) ? "passed" : "failed"), false)); } } } }
/// <summary> /// Initialize information for the hidden controls and script. This sets up the information to create hidden fields in the form /// and to update the framesetMgr on page load. /// </summary> private void InitHiddenControlInfo(RenderContext context, StringBuilder onLoadScript) { // Should only do this if this is LRM content. Other content does not allow writing to the page. if (Session.CurrentActivityResourceType != ResourceType.Lrm) { return; } IDictionary <string, string> controls = context.FormHiddenControls; // Write the script to define frameMgr in script. WriteFindFrameMgr(onLoadScript); // If the session is attempt-based, then write attempt information if (Session != null) { controls.Add(HiddenFieldNames.AttemptId, FramesetUtil.GetStringInvariant(Session.AttemptId.GetKey())); onLoadScript.AppendFormat("frameMgr.SetAttemptId(document.getElementById({0}).value);\r\n", JScriptString.QuoteString(HiddenFieldNames.AttemptId, false)); } // If the session has ended (that is, is suspended, completed or abandoned), then we're // done. Just return. if (SessionIsEnded) { return; } // Write view to display. controls.Add(HiddenFieldNames.View, FramesetUtil.GetString(Session.View)); onLoadScript.AppendFormat("frameMgr.SetView(document.getElementById({0}).value);\r\n", JScriptString.QuoteString(HiddenFieldNames.View, false)); // Write frame to post. controls.Add(HiddenFieldNames.PostFrame, "frameContent"); onLoadScript.AppendFormat("frameMgr.SetPostFrame(document.getElementById({0}).value);\r\n", JScriptString.QuoteString(HiddenFieldNames.PostFrame, false)); // Set contentFrameUrl to be null. This prevents the content frame from being re-loaded. onLoadScript.Append("frameMgr.SetContentFrameUrl(null);\r\n"); // If a new activity has been identified, then instruct frameMgr to reinitialize the RTE. // BE CAREFUL to do this before setting any other data related to the rte! if (ActivityHasChanged) { string initNewActivity = "false"; if (Session.HasCurrentActivity) { initNewActivity = (CurrentActivityRequiresRte ? "true" : "false"); } onLoadScript.AppendFormat("frameMgr.InitNewActivity( {0} );\r\n", initNewActivity); } // Write the current activity Id. Write -1 if there isn't one. controls.Add(HiddenFieldNames.ActivityId, (Session.HasCurrentActivity ? FramesetUtil.GetStringInvariant(Session.CurrentActivityId) : "-1")); onLoadScript.AppendFormat("frameMgr.SetActivityId(document.getElementById({0}).value);\r\n", JScriptString.QuoteString(HiddenFieldNames.ActivityId, false)); // Write the navigation control state. Format of the control state is a series of T (to show) or F (to hide) // values, separated by semi-colons. The order of controls is: // showNext, showPrevious, showAbandon, showExit, showSave StringBuilder sb = new StringBuilder(10); sb.Append((Session.ShowNext) ? "T" : "F"); sb.Append(";"); sb.Append((Session.ShowPrevious) ? "T" : "F"); sb.Append(";"); sb.Append((Session.ShowAbandon) ? "T" : "F"); sb.Append(";"); sb.Append((Session.ShowExit) ? "T" : "F"); sb.Append(";"); sb.Append((Session.ShowSave) ? "T" : "F"); sb.Append(";"); onLoadScript.AppendFormat("frameMgr.SetNavVisibility( {0}, {1}, {2}, {3}, {4});\r\n", (Session.ShowNext ? "true" : "false"), (Session.ShowPrevious ? "true" : "false"), (Session.ShowAbandon ? "true" : "false"), (Session.ShowExit ? "true" : "false"), (Session.ShowSave ? "true" : "false")); controls.Add(HiddenFieldNames.ShowUI, sb.ToString()); context.Script = onLoadScript.ToString(); }
/// <summary>Write initialization code for frameset manager. </summary> /// <remarks> /// This method is called in three possible cases: /// 1. An error condition occurred /// 2. The submit page is being displayed. Note that in this case, since the submit page is registered as displaying an /// error condition, HasError will be true. /// 3. The current activity has changed and we display this page mainly so that the 'please wait' information can be /// displayed and the client can issue a GET request to load the new activity. /// </remarks> public void WriteFrameMgrInit() { // Write frame to post. When displaying an error (which is the case, since we are here) the hidden frame is posted next Response.Write("frameMgr.SetPostFrame('frameHidden');\r\n"); Response.Write("frameMgr.SetPostableForm(window.top.frames[MAIN_FRAME].document.getElementById(HIDDEN_FRAME).contentWindow.document.forms[0]);\r\n"); if (HasError || SubmitPageDisplayed) { // Set the content frame URL to be null. This means the content frame will not be re-loaded by the frameMgr. Response.Write("frameMgr.SetContentFrameUrl(null); \r\n"); } // If there is no session, we can't do anything else if (Session == null) { return; } if ((ActivityHasChanged) && (!SubmitPageDisplayed)) { // Reload the content frame with the new activity. Response.Write(String.Format(CultureInfo.CurrentCulture, "frameMgr.SetContentFrameUrl(\"{0}\"); \r\n", GetContentFrameUrl())); // The new activity may be scorm content, so reinitialize the rte, if needed Response.Write(ResHelper.Format("frameMgr.InitNewActivity( {0} );\r\n", (CurrentActivityRequiresRte ? "true" : "false"))); } Response.Write(ResHelper.Format("frameMgr.SetAttemptId('{0}');\r\n", FramesetUtil.GetStringInvariant(Session.AttemptId.GetKey()))); // Write view to display. Response.Write(String.Format(CultureInfo.CurrentCulture, "frameMgr.SetView('{0}');\r\n", FramesetUtil.GetString(Session.View))); // Write the current activity Id. Write -1 if there isn't one. string activityId; if (SubmitPageDisplayed) { activityId = SubmitId; } else { activityId = (Session.HasCurrentActivity ? FramesetUtil.GetStringInvariant(Session.CurrentActivityId) : "-1"); } Response.Write(String.Format(CultureInfo.InvariantCulture, "frameMgr.SetActivityId({0});\r\n", JScriptString.QuoteString(activityId, true))); // Write nav visibility, in case it's changed since the hidden frame was rendered if (SubmitPageDisplayed) { // If the submit page is being displayed, don't show UI elements Response.Write(String.Format(CultureInfo.CurrentCulture, "frameMgr.SetNavVisibility( {0}, {1}, {2}, {3}, {4});", ("false"), // showNext ("false"), // showPrevious ("false"), // showAbandon ("false"), // showExit (Session.ShowSave ? "true" : "false"))); // If the submit page is now being displayed, make sure the frameset isn't waiting for another commit Response.Write("frameMgr.WaitForContentCompleted(0);\r\n"); } else { Response.Write(String.Format(CultureInfo.CurrentCulture, "frameMgr.SetNavVisibility( {0}, {1}, {2}, {3}, {4});\r\n", (Session.ShowNext ? "true" : "false"), (Session.ShowPrevious ? "true" : "false"), (Session.ShowAbandon ? "true" : "false"), (Session.ShowExit ? "true" : "false"), (Session.ShowSave ? "true" : "false"))); } // Register that the frame loading is complete. This is required so as to notify the frameset of activity id, and // other UI status. Response.Write(String.Format(CultureInfo.InvariantCulture, "frameMgr.RegisterFrameLoad({0});\r\n ", JScriptString.QuoteString("frameContent", false))); if (m_isPostedPage) { // Set PostIsComplete. THIS MUST BE THE LAST VALUE SET! Response.Write("frameMgr.PostIsComplete();"); } }