Example #1
0
        [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] // catching all exceptions in order to return http response code
        private void RenderPackageContent(string resPath)
        {
            // If this is the primary resource of the current activity, then process it for rendering, including (in the case of
            // LRM content) injecting script to notify client script of page load.
            if (IsPrimaryResource(resPath))
            {
                // If the resPath is empty or it matches the xmlBase value of the resource of the current activity,
                // that means it's asking for the default resource associated with the current
                // activity. Check if there is one. If there isn't, then show a message that indicates the content can't be shown
                // because there's no resource.
                if (Session.CurrentActivityResourceType == ResourceType.None)
                {
                    RegisterError(ResHelper.GetMessage(IUDICO.TestingSystem.Localization.getMessage("CON_ResourceNotFoundTitle")),
                                  ResHelper.GetMessage(IUDICO.TestingSystem.Localization.getMessage("CON_ResourceNotFoundMsg")), false);
                    return;
                }

                // If the entry point for the current activity is an absolute Uri, then we should not be here (the
                // hidden frame should have loaded the absolute Uri into the content frame).
                if (Session.CurrentActivityEntryPoint.IsAbsoluteUri)
                {
                    RegisterError(ResHelper.GetMessage(IUDICO.TestingSystem.Localization.getMessage("CON_ResourceNotFoundTitle")),
                                  ResHelper.GetMessage(IUDICO.TestingSystem.Localization.getMessage("CON_ResourceNotFoundMsg")), false);
                    return;
                }

                bool fileNotFound = false;  // Check if we got an exception indicating the file could not be found
                try
                {
                    string        filePath = Session.CurrentActivityEntryPoint.OriginalString.Replace("%20", " ");
                    RenderContext context  = new RenderContext(filePath, Response);

                    StringBuilder scriptBlock = new StringBuilder(1000);

                    // Initialize the hidden control and script for the page
                    InitHiddenControlInfo(context, scriptBlock);

                    // Allow application to modify the context.
                    UpdateRenderContext(context, scriptBlock, Session);

                    FinishOnLoadScript(scriptBlock);

                    // Save script to context, if neeed
                    if (scriptBlock.Length > 0)
                    {
                        context.Script = scriptBlock.ToString();
                    }

                    // Clear any previous page information and render the page
                    Session.Render(context);

                    // When the primary resource is rendered, the session may be changed, so save any changes.
                    if (!SessionIsReadOnly)
                    {
                        Session.CommitChanges();
                    }
                }
                catch (FileNotFoundException)
                {
                    fileNotFound = true;
                }
                catch (DirectoryNotFoundException)
                {
                    fileNotFound = true;
                }
                if (fileNotFound)
                {
                    // The entry point defined in the package was a relative Uri but does not map to a file in the package.
                    RegisterError(ResHelper.GetMessage(IUDICO.TestingSystem.Localization.getMessage("CON_ResourceNotFoundTitle")),
                                  ResHelper.GetMessage(IUDICO.TestingSystem.Localization.getMessage("CON_ResourceNotFoundMsg")), false);
                    return;
                }
            }
            else
            {
                long pageId;
                if (IsPrimaryResourceOfLrmActivity(resPath, out pageId))
                {
                    // If this is LRM content and is a request for the primary resource of another activity, then
                    // move to that activity and render a 'please wait'
                    // message that tells the frameset about the new activity.

                    ProcessNavigationRequests(Session);

                    string activityId = "ITEM" + FramesetUtil.GetStringInvariant(pageId);
                    Session.MoveToActivity(activityId);

                    if (!SessionIsReadOnly)
                    {
                        Session.CommitChanges();
                    }

                    Response.Clear();
                    Response.Redirect(GetRedirectLocation());
                }
                else
                {
                    // There was a relative path provided. Write it to the output stream. If this method fails because the path was not
                    // in the package or could not be accessed for some reason, return an error code.
                    try
                    {
                        RenderContext context = new RenderContext(resPath.Replace("%20", " "), Response);
                        UpdateRenderContext(context, null, Session);
                        Session.Render(context);

                        // Session is not changed in non-Execute views, so no need to call CommitChanges().
                    }
                    catch (ThreadAbortException)
                    {
                        // Do nothing
                    }
                    catch (FileNotFoundException)
                    {
                        Response.StatusCode        = 404;
                        Response.StatusDescription = "Not Found";
                    }
                    catch (HttpException)
                    {
                        // Something wrong with the http connection, so in this case do not set the response
                        // headers.
                    }
                    catch
                    {
                        // This could fail for any number of reasons: invalid content that
                        // refers to non-existant file, or a problem somewhere in the server
                        // code. Return generic error code.
                        Response.StatusCode        = 500;
                        Response.StatusDescription = "Internal Server Error";
                    }
                }
            }
        }
Example #2
0
        [SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")] // it's not worth changing this now
        public void ProcessPageLoad(PackageStore packageStore,
                                    bool firstRendering,                                  // frameset is being initialized
                                    bool isPostBack,                                      // page was posted
                                    TryGetViewInfo TryGetViewInfo,
                                    TryGetAttemptInfo TryGetAttemptInfo,
                                    TryGetActivityInfo TryGetActivityInfo,
                                    GetResourcePath GetResourcePath,
                                    AppendContentFrameDetails appendContentFrameDetails,
                                    UpdateRenderContext updateRenderContext,
                                    ProcessPostedData ProcessPostedData,
                                    ProcessViewRequest ProcessViewRequest,
                                    ProcessPostedDataComplete ProcessPostedDataComplete,
                                    RegisterError registerError,
                                    GetErrorInfo getErrorInfo,
                                    GetFramesetMsg getFramesetMsg)
        {
            RegisterError             = registerError;
            UpdateRenderContext       = updateRenderContext;
            GetErrorInfo              = getErrorInfo;
            AppendContentFrameDetails = appendContentFrameDetails;
            GetFramesetMsg            = getFramesetMsg;

            m_isPostedPage = isPostBack;

            // If this is the first time the page is being rendered, just show 'please wait' and return.
            if (firstRendering)
            {
                // Initial page rendering, show "please wait"
                WritePleaseWaitToResponse(Response);
                Response.End();
                return;
            }

            SessionView view;

            // Get View information. It determines what else to look for.
            if (!TryGetViewInfo(true, out view))
            {
                return;
            }

            // There is something to display, so process the request...

            AttemptItemIdentifier attemptId;

            if (!TryGetAttemptInfo(true, out attemptId))
            {
                return;
            }

            StoredLearningSession slsSession = new StoredLearningSession(view, attemptId, packageStore);

            if (!ProcessViewRequest(view, slsSession))
            {
                return;
            }

            Session = slsSession;

            if (slsSession.View == SessionView.Execute)
            {
                // Check if the session can be executed...

                if (slsSession.AttemptStatus != AttemptStatus.Active)
                {
                    RegisterError(GetFramesetMsg(FramesetStringId.CannotDisplayContentTitle),
                                  GetFramesetMsg(FramesetStringId.SessionIsNotActiveMsg), false);
                    return;
                }

                if (!slsSession.CurrentActivityIsActive)
                {
                    RegisterError(GetFramesetMsg(FramesetStringId.SelectActivityTitleHtml),
                                  GetFramesetMsg(FramesetStringId.SelectActivityMessageHtml), true);
                    return;
                }
            }
            else if (slsSession.View == SessionView.Review)
            {
                // Get information about which activity to review, then make that the current activity.

                long activityId = -1;   // make compiler happy
                if (!TryGetActivityInfo(true, out activityId))
                {
                    return;
                }

                // Move to the requested activity. Under normal conditions, this should always succeed, since the frameset should be
                // giving this page a valid activity id.
                MoveToActivity(slsSession, activityId);
            }

            else if (slsSession.View == SessionView.RandomAccess)
            {
                // Get information about which activity to edit, then make that the current activity.

                long activityId = -1;   // make compiler happy
                if (!TryGetActivityInfo(true, out activityId))
                {
                    return;
                }

                // Move to the requested activity. Under normal conditions, this should always succeed, since the frameset should be
                // giving this page a valid activity id.
                MoveToActivity(slsSession, activityId);
            }

            if (isPostBack /* && !SessionEnded */)
            {
                //Process information from posted content
                if (!this.SessionIsReadOnly)
                {
                    HttpFileCollection files = Request.Files;
                    int numFiles             = files.Count;
                    Dictionary <string, HttpPostedFile> newFileCollection = new Dictionary <string, HttpPostedFile>(numFiles);

                    // Allow the application to process the form data
                    if (!ProcessPostedData(slsSession, Request, newFileCollection))
                    {
                        return;
                    }

                    // Allow MLC to process the form data
                    Session.ProcessFormData(Request.Form, newFileCollection);

                    // Allow application to do final processing after all posted data is processed.
                    ProcessPostedDataComplete(Session);

                    // If there was an error in processing form data, end the processing. This allows, for instance, to
                    // save the data, display an error and not have commands (such as 'move to next activity') executed.
                    if (HasError)
                    {
                        Session.CommitChanges();
                        return;
                    }
                }

                // Issue with Review view: where to get activity id? From URL or posted data?

                // Find out what the commands are and do them.
                ICollection <CommandInfo> commands = GetCommands();
                foreach (CommandInfo cmdInfo in commands)
                {
                    switch (cmdInfo.Command)
                    {
                    case Commands.DoNext:
                    {
                        // When leaving a current activity, we must allow navigation requests the SCO has made to be
                        // executed. If that results in changing the current activity, then do not also ask for another
                        // move.
                        if (!ProcessNavigationRequests(Session))
                        {
                            if (Session.IsMoveToNextValid())
                            {
                                MoveToNextActivity(Session);
                                ActivityHasChanged = true;
                            }
                        }
                        else
                        {
                            ActivityHasChanged = true;
                        }

                        if (!ActivityHasChanged)
                        {
                            // Moving to the next activity is not valid.

                            WriteError(ResHelper.Format(GetFramesetMsg(FramesetStringId.MoveToNextFailedHtml), ThemeFolderPath), true);
                        }
                    }
                    break;

                    case Commands.DoPrevious:
                    {
                        if (!ProcessNavigationRequests(Session))
                        {
                            if (Session.IsMoveToPreviousValid())
                            {
                                MoveToPreviousActivity(Session);
                                ActivityHasChanged = true;
                            }
                        }
                        else
                        {
                            ActivityHasChanged = true;
                        }


                        if (!ActivityHasChanged)
                        {
                            // Moving to the previous activity is not valid.
                            WriteError(ResHelper.Format(GetFramesetMsg(FramesetStringId.MoveToPreviousFailedHtml), ThemeFolderPath), true);
                        }
                    }
                    break;

                    case Commands.DoChoice:
                    case Commands.DoTocChoice:
                    {
                        // These commands are used to navigate to activities, and to navigate to the final 'submit' page.
                        // In SCORM content, these commands do different things. In LRM content (which is what we are
                        // in, since this is the posted page), they have identical effects.

                        // First check whether this is a request for the submit page or an activity.

                        string cmdData = cmdInfo.CommandData;
                        if (String.CompareOrdinal(cmdData, SubmitId) == 0)
                        {
                            // Requesting submit page. Do not change the current activity, but mark it as changed so that
                            // it appears to the user that it has changed.
                            ActivityHasChanged = true;
                            string title = GetFramesetMsg(FramesetStringId.SubmitPageTitleHtml);
                            string message;
                            string saveBtn = GetFramesetMsg(FramesetStringId.SubmitPageSaveButtonHtml);
                            if (Session.HasCurrentActivity)
                            {
                                message = GetFramesetMsg(FramesetStringId.SubmitPageMessageHtml);
                            }
                            else
                            {
                                message = GetFramesetMsg(FramesetStringId.SubmitPageMessageNoCurrentActivityHtml);
                            }
                            WriteSubmitPage(title, message, saveBtn);
                        }
                        else
                        {
                            long activityId;
                            if (long.TryParse(cmdData, out activityId))
                            {
                                // If the requested activity is the current activity, then do not do the navigation.
                                // We skip it because moving to the activity basically exits the current attempt and creates
                                // a new one. That new one also increments the attempt count. If we don't do the move, we
                                // pretend it was done. This will force the content frame to be reloaded with the current
                                // activity.
                                if (IsCurrentActiveActivity(activityId))
                                {
                                    ActivityHasChanged = true;
                                }
                                else
                                {
                                    if (!ProcessNavigationRequests(Session))
                                    {
                                        if (Session.IsMoveToActivityValid(activityId))
                                        {
                                            MoveToActivity(Session, activityId);
                                            ActivityHasChanged = true;
                                        }
                                    }
                                    else
                                    {
                                        ActivityHasChanged = true;
                                    }
                                }
                            }
                        }

                        if (!ActivityHasChanged)
                        {
                            // Moving to the selected activity is not valid.

                            WriteError(ResHelper.Format(GetFramesetMsg(FramesetStringId.MoveToActivityFailedHtml), ThemeFolderPath), true);
                        }
                    }
                    break;

                    case Commands.DoSave:
                    {
                        // Do nothing. The information will be saved since the page was posted.
                    }
                    break;

                    case Commands.DoSubmit:
                    {
                        if (Session.View == SessionView.Execute)
                        {
                            ProcessNavigationRequests(Session);
                            Session.Exit();
                        }

                        ActivityHasChanged = true;
                    }
                    break;
                    }
                }
            }

            // If an error has been registered (and it's not the submit
            // page rendering), don't attempt to render the content.
            if (HasError && !SubmitPageDisplayed)
            {
                if (!SessionIsReadOnly)
                {
                    Session.CommitChanges();
                }
                return;
            }

            // There was no error, so go ahead and render the content from the package.
            // If the current activity has changed in the processing of this page, then render the current activity's resource.
            // Otherwise, ask the application which resource to read.
            if (ActivityHasChanged)
            {
                // If the activity has changed, we render the content page without rendering the content. The page will then
                // reload the content frame with the new activity.
                if (!SessionIsReadOnly)
                {
                    Session.CommitChanges();
                }
            }
            else
            {
                // Render the requested file in the current activity.
                RenderPackageContent(GetResourcePath());

                // If there was no error, end the response. Otherwise, we wait and render the error on the page.
                if (!HasError)
                {
                    Response.End();
                }
            }
        }
Example #3
0
        /// <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(parent.parent.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();");
            }
        }
Example #4
0
        [SuppressMessage("Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods")] // parameter is validated
        private void WriteTocEntry(HtmlStringWriter sw, TableOfContentsElement currentElement)
        {
            FramesetUtil.ValidateNonNullParameter("sw", sw);
            FramesetUtil.ValidateNonNullParameter("currentElement", currentElement);

            string     activityId         = FramesetUtil.GetStringInvariant(currentElement.ActivityId);
            bool       elementHasChildren = currentElement.Children.Count > 0;
            HtmlString activityIdHtml     = new PlainTextString(activityId).ToHtmlString();
            HtmlString titleHtml          = new PlainTextString(currentElement.Title).ToHtmlString();

            // If the current element is visible or is an invisible leaf node, then render it. (If it's an
            // invisible leaf node, the node will exist but not be visible.)
            if (RenderThisNode(currentElement))
            {
                sw.AddAttribute(HtmlTextWriterAttribute.Class, new PlainTextString("NodeParent"));
                sw.AddAttribute("activityId", activityIdHtml);
                sw.AddAttribute("isValidChoice", (currentElement.IsValidChoiceNavigationDestination ? "true" : "false"));
                sw.AddAttribute(HtmlTextWriterAttribute.Id, ResHelper.FormatInvariant("div{0}", activityIdHtml));
                sw.RenderBeginTag(HtmlTextWriterTag.Div); // #Div1

                if (currentElement.IsVisible)
                {
                    sw.AddAttribute(HtmlTextWriterAttribute.Id, ResHelper.FormatInvariant("icon{0}", activityIdHtml));
                    if (currentElement.HasVisibleChildren)
                    {
                        sw.AddAttribute(HtmlTextWriterAttribute.Src, "Theme/Minus.png");
                    }
                    else
                    {
                        sw.AddAttribute(HtmlTextWriterAttribute.Src, "Theme/Leaf.png");
                    }
                    sw.AddAttribute(HtmlTextWriterAttribute.Align, "absMiddle");
                    sw.RenderBeginTag(HtmlTextWriterTag.Img);
                    sw.RenderEndTag();

                    sw.AddAttribute(HtmlTextWriterAttribute.Src, "Theme/1px.gif");
                    sw.AddAttribute(HtmlTextWriterAttribute.Align, "absMiddle");
                    sw.RenderBeginTag(HtmlTextWriterTag.Img);
                    sw.RenderEndTag();
                    sw.WriteLine();

                    sw.AddAttribute(HtmlTextWriterAttribute.Href, "javascript:void(0)");
                    sw.AddAttribute(HtmlTextWriterAttribute.Id, ResHelper.FormatInvariant("a{0}", activityIdHtml));
                    if (!currentElement.IsValidChoiceNavigationDestination)
                    {
                        sw.AddAttribute(HtmlTextWriterAttribute.Disabled, "true");
                        sw.AddAttribute("class", "disable");
                    }

                    sw.AddAttribute(
                        HtmlTextWriterAttribute.Style,
                        ResHelper.FormatInvariant("FONT-WEIGHT: normal;visibility:{0}", (currentElement.IsVisible ? "visible" : "hidden")));
                    sw.AddAttribute(HtmlTextWriterAttribute.Title, titleHtml);
                    sw.RenderBeginTag(HtmlTextWriterTag.A);
                    sw.WriteHtml(titleHtml);
                    sw.RenderEndTag();
                }
            }

            // Write sub-elements (regardless of whether or not this node is rendered)
            if (elementHasChildren)
            {
                sw.WriteLine();
                bool clusterStarted = false;
                if (currentElement.IsVisible)
                {
                    sw.AddAttribute(
                        HtmlTextWriterAttribute.Id, ResHelper.FormatInvariant("divCluster{0}", activityIdHtml));
                    sw.AddAttribute(
                        HtmlTextWriterAttribute.Style, "MARGIN-TOP: 5px; DISPLAY: block; MARGIN-LEFT: 18px;");
                    sw.RenderBeginTag(HtmlTextWriterTag.Div);
                    clusterStarted = true;
                }

                foreach (TableOfContentsElement childElement in currentElement.Children)
                {
                    this.WriteTocEntry(sw, childElement);
                }

                if (clusterStarted)
                {
                    sw.RenderEndTag(); // end div
                    sw.WriteLine();
                }
            }

            if (RenderThisNode(currentElement))
            {
                sw.RenderEndTag(); // div (see #Div1, above)
                sw.WriteLine();
            }
        }