/// <summary>
        /// Send the non-elearning content to the response. Non-elearning content is any content other than
        /// scorm or lrm content. It is an error to call this method when the current learner assignment is elearning content.
        /// In some cases, this method will end the response.
        /// </summary>
        private void SendNonElearningContent()
        {
            // Get the cached learner assignment properties
            LearnerAssignmentProperties la = GetLearnerAssignment();

            SharePointFileLocation spFileLocation;

            if (!SharePointFileLocation.TryParse(la.Assignment.Location, out spFileLocation))
            {
                // location was not valid
                RegisterError(SlkFrameset.FRM_DocumentNotFoundTitleHtml, SlkFrameset.FRM_DocumentNotFound, false);
                return;
            }

            // Find the location of the document in the Sharepoint Document Library and go there
            string documentUrl = GetNonElearningDocumentUrl(spFileLocation);

            // Special case handling for HTML files:
            //   * Launch directly from the document library, not from the Cache
            //   * Add the LearnerAssignmentId to the Query portion of the URL so that we pass the learning context down to the content
            // This enables us to have more advanced behavior (CMI Tracking, scoring, completion status) for "Non-ELearning" documents.
            // It is a first step towards a more comprehensive strategy for adding educational workflow to all types of documents.
            if (documentUrl.EndsWith("html", StringComparison.OrdinalIgnoreCase) || documentUrl.EndsWith("htm", StringComparison.OrdinalIgnoreCase))
            {
                string redirectUrl = String.Format("{0}?{1}={2}", documentUrl, FramesetQueryParameter.LearnerAssignmentId, LearnerAssignmentGuidId.ToString());
                Response.Clear();
                Response.Redirect(redirectUrl, true); // ends response
            }

            string framesetPath = GetFramesetPath();

            Response.Clear();

            using (CachedSharePointFile cachedFile = new CachedSharePointFile(SlkStore.SharePointCacheSettings, spFileLocation, true))
            {
                // If the current request URL does not include the file name of the file, then this request is the first frameset rendering.
                // That means this will redirect to a URL that does include the filename of the file. This redirection allows the browser to
                // properly handle the content.
                if (String.IsNullOrEmpty(framesetPath))
                {
                    string redirectUrl = GetNonElearningFrameUrl(cachedFile.FileName);
                    cachedFile.Dispose();
                    Response.Redirect(redirectUrl, true);   // ends response
                }

                // This is the first actual access of the file. If it doesn't exist, the exception will be caught by the Page_load method.
                SetMimeType(cachedFile.FileName);

                // If this file is using IIS Compability mode, then we get the stream from the cached file and write it to the
                // response, otherwise, use TransmitFile.
                if (UseCompatibilityMode(cachedFile.FileName))
                {
                    WriteIisCompatibilityModeToResponse(cachedFile.GetFileStream());
                }
                else
                {
                    cachedFile.TransmitFile(Response);
                }
            }
        }
Esempio n. 2
0
        /// <summary>Copies the original file to the student's drop box.</summary>
        /// <returns>The url of the file.</returns>
        public AssignmentFile CopyFileToDropBox()
        {
            AssignmentFile assignmentFile = null;

            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
                SharePointFileLocation fileLocation;
                if (!SharePointFileLocation.TryParse(assignmentProperties.Location, out fileLocation))
                {
                    throw new SafeToDisplayException(SlkFrameset.FRM_DocumentNotFound);
                }

                using (SPSite sourceSite = new SPSite(fileLocation.SiteId))
                {
                    using (SPWeb sourceWeb = sourceSite.OpenWeb(fileLocation.WebId))
                    {
                        SPFile file = sourceWeb.GetFile(fileLocation.FileId);
                        if (file.Exists == false)
                        {
                            string message = string.Format(CultureInfo.CurrentUICulture, culture.Resources.AssignmentFileDoesNotExist, fileLocation.FileId, assignmentProperties.Title);
                            store.LogError(message);
                            throw new SafeToDisplayException(message);
                        }

                        if (MustCopyFileToDropBox(file.Name))
                        {
                            try
                            {
                                assignmentFile = SaveFile(file);
                            }
                            catch (SPException)
                            {
                                // Retry in case a temporary error
                                try
                                {
                                    assignmentFile = SaveFile(file);
                                }
                                catch (SPException e)
                                {
                                    string message = string.Format(CultureInfo.CurrentUICulture, culture.Resources.DropBoxFailedToCopyFile, file.Name, assignmentProperties.Title, e.Message);
                                    store.LogError(message);
                                    string safeMessage = string.Format(CultureInfo.CurrentUICulture, culture.Resources.DropBoxFailedToCopyFile, file.Name, assignmentProperties.Title, string.Empty);
                                    throw new SafeToDisplayException(safeMessage);
                                }
                            }
                        }
                    }
                }
            });

            return assignmentFile;
        }
Esempio n. 3
0
    public static void RunProgram(string classWebUrl)
    {
        Stack <IDisposable> disposer = new Stack <IDisposable>();

        try
        {
            // "log in" to SLK as the current user, and set <memberships> to information about
            // the instructors and learners in the class Web site (i.e. the SPWeb with URL
            // <classWebUrl>)
            SPSite spSite = new SPSite(classWebUrl);
            disposer.Push(spSite);
            SPWeb spWeb = spSite.OpenWeb();
            disposer.Push(spWeb);
            SlkStore       slkStore    = SlkStore.GetStore(spWeb);
            SlkMemberships memberships = slkStore.GetMemberships(spWeb, null, null);

            // make sure there's at least one instructor and one learner on the class Web; these
            // roles are defined by the "SLK Instructor" and "SLK Learner" permissions (as defined
            // in the SharePoint Learning Kit configuration page in SharePoint Central
            // Administration)
            if (memberships.Instructors.Count == 0)
            {
                throw new Exception("Class Web must have at least one instructor");
            }
            if (memberships.Learners.Count == 0)
            {
                throw new Exception("Class Web must have at least one learner");
            }

            // arbitrarily choose the first instructor in the class as the user who will create
            // the assignments
            SlkUser primaryInstructor = memberships.Instructors[0];

            // set <classWeb> to the SPWeb of the SharePoint Web site that the new assignment will
            // be associated with; "log into" this Web site as the instructor retrieved above
            SPSite classSite = new SPSite(classWebUrl, primaryInstructor.SPUser.UserToken);
            disposer.Push(classSite);
            SPWeb classWeb = classSite.OpenWeb();
            disposer.Push(classWeb);

            // set <slkStore> to the SharePoint Learning Kit store associated with the SPSite of
            // <classWeb>
            slkStore = SlkStore.GetStore(classWeb);

            // set <packageLocations> to the SharePointPackageStore-format location strings
            // corresponding to each element of <PackageUrls>; "log into" these Web sites as the
            // instructor retrieved above
            string[] packageLocations = new string[PackageUrls.Length];
            for (int packageIndex = 0; packageIndex < packageLocations.Length; packageIndex++)
            {
                // set <packageWeb> to the SPWeb of the SharePoint Web site containing the package
                // or document to assign
                string packageUrl  = PackageUrls[packageIndex];
                SPSite packageSite = new SPSite(packageUrl, primaryInstructor.SPUser.UserToken);
                disposer.Push(packageSite);
                SPWeb packageWeb = packageSite.OpenWeb();
                disposer.Push(packageWeb);

                // set <spFile> to the SPFile of the package or document to assign
                SPFile spFile = packageWeb.GetFile(packageUrl);

                // set the current element of <packageLocation> to the SharePointPackageStore
                // format location string that uniquely identifies the current version of the
                // <spFile>
                packageLocations[packageIndex] = new SharePointFileLocation(
                    packageWeb, spFile.UniqueId, spFile.UIVersion).ToString();
            }

            // create a random number generator
            s_random = new Random(RandomNumberSeed);

            // set <maxNumberOfLearners> to the number of learners in the class
            int maxNumberOfLearners = memberships.Learners.Count;

            // set <learners> to an array of learners of this class; for each assignment, we'll
            // shuffle this array and choose a subset to be learners on the assignment
            SlkUser[] learners = new SlkUser[memberships.Learners.Count];
            memberships.Learners.CopyTo(learners, 0);

            // display table header
            Console.WriteLine("Assign. No. of    Due       Not");
            Console.WriteLine("ID      Learners  Date      Started Active Completed Final");
            Console.WriteLine("----------------------------------------------------------");

            // create assignments as specified by the constants at the top of this source file
            for (int assignmentIndex = 0; assignmentIndex < NumberOfAssignments; assignmentIndex++)
            {
                // set <fraction> to be proportional to <assignmentIndex>, between 0.0 and 1.0
                double fraction = (double)assignmentIndex / NumberOfAssignments;

                // randomly choose an e-learning package or non-e-learning document to be assigned
                string packageLocation = packageLocations[s_random.Next(0, PackageUrls.Length)];

                // get some information about the package/document; set <isNonELearning> to true if
                // if it's a non-e-learning document; NOTE: this is oversimplified code -- proper
                // production code should handle error conditions more carefully
                SPFile spFile = SlkUtilities.GetSPFileFromPackageLocation(packageLocation);
                bool   isNonELearning;
                SharePointFileLocation spFileLocation;
                SharePointFileLocation.TryParse(packageLocation, out spFileLocation);
                using (SharePointPackageReader spPackageReader =
                           new SharePointPackageReader(slkStore.SharePointCacheSettings, spFileLocation))
                {
                    isNonELearning = PackageValidator.Validate(spPackageReader).HasErrors;
                }

                // set <assignmentProperties> to the default assignment properties for the package
                // or document being assigned; some of these properties will be overridden below
                LearningStoreXml packageWarnings;
                int?organizationIndex = (isNonELearning ? (int?)null : 0);
                AssignmentProperties assignmentProperties =
                    slkStore.GetNewAssignmentDefaultProperties(
                        classWeb, packageLocation, organizationIndex, SlkRole.Instructor,
                        out packageWarnings);

                // randomly generate a title for the assignment
                assignmentProperties.Title = CreateRandomTitle();

                // set the due date of the assignment based on <fraction>,
                // <OldestAssignmentDaysAgo>, and <NewestAssignmentDaysFromNow>
                assignmentProperties.DueDate = DateTime.Now.AddDays(
                    (OldestAssignmentDaysAgo + NewestAssignmentDaysFromNow)
                    * fraction - OldestAssignmentDaysAgo);

                // set the start date of the assignment to be a day earlier than the earliest
                // due date
                assignmentProperties.StartDate = DateTime.Today.AddDays(
                    -OldestAssignmentDaysAgo - 1);

                // randomly set Points Possible
                if ((assignmentProperties.PointsPossible == null) &&
                    (s_random.NextDouble() > FractionOfBlankPointsPossible))
                {
                    const int divideBy = 4;
                    const int maxValue = 100;
                    assignmentProperties.PointsPossible = (float)Math.Round(
                        s_random.NextDouble() * divideBy * maxValue) / maxValue;
                }

                // make all instructors of this class (i.e. all SharePoint users that have the SLK
                // Instructor permission) be instructors on this assignment
                assignmentProperties.Instructors.Clear();
                foreach (SlkUser slkUser in memberships.Instructors)
                {
                    assignmentProperties.Instructors.Add(slkUser);
                }

                // shuffle <learners>
                for (int learnerIndex = 0; learnerIndex < learners.Length; learnerIndex++)
                {
                    int     otherLearnerIndex = s_random.Next(0, learners.Length);
                    SlkUser temp = learners[learnerIndex];
                    learners[learnerIndex]      = learners[otherLearnerIndex];
                    learners[otherLearnerIndex] = temp;
                }

                // randomly choose a number of learners for this assignment
                int numberOfLearners = s_random.Next(
                    Math.Min(maxNumberOfLearners, MinLearnersPerAssignment),
                    maxNumberOfLearners + 1);

                // copy the first <numberOfLearners> learners to <assignmentProperties>
                assignmentProperties.Learners.Clear();
                for (int learnerIndex = 0; learnerIndex < numberOfLearners; learnerIndex++)
                {
                    assignmentProperties.Learners.Add(learners[learnerIndex]);
                }

                // create the assignment
                AssignmentItemIdentifier assignmentId = slkStore.CreateAssignment(classWeb,
                                                                                  packageLocation, organizationIndex, SlkRole.Instructor, assignmentProperties);

                // set <gradingPropertiesList> to information about the learner assignments of the
                // new assignment; in particular, we need the learner assignment IDs
                AssignmentProperties basicAssignmentProperties;
                ReadOnlyCollection <GradingProperties> gradingPropertiesList =
                    slkStore.GetGradingProperties(assignmentId, out basicAssignmentProperties);

                // adjust the status of each learner assignment of this assignment according to
                // the rules specified in constants at the top of this source file
                int[] newStatusCount = new int[(int)LearnerAssignmentState.Final + 1];
                for (int learnerIndex = 0;
                     learnerIndex < gradingPropertiesList.Count;
                     learnerIndex++)
                {
                    // set <gradingProperties> to information about this learner assignment
                    GradingProperties gradingProperties = gradingPropertiesList[learnerIndex];

                    // set <newStatus> to the new status of the assignment, applying the rules
                    // specified in constants at the top of this source file
                    if (fraction > 1 - FractionOfAssignmentsNotStarted)
                    {
                        gradingProperties.Status = LearnerAssignmentState.NotStarted;
                    }
                    else
                    if (fraction < FractionOfAssignmentsAllFinal)
                    {
                        gradingProperties.Status = LearnerAssignmentState.Final;
                    }
                    else
                    {
                        gradingProperties.Status = (LearnerAssignmentState)
                                                   s_random.Next(0, (int)LearnerAssignmentState.Final + 1);
                    }

                    // if we're transitioning learner assignment to Final state, optionally
                    // assign a final points value
                    if ((gradingProperties.Status == LearnerAssignmentState.Final) &&
                        (assignmentProperties.PointsPossible != null))
                    {
                        if (s_random.NextDouble() < FractionOfOverriddenFinalPoints)
                        {
                            const int divideBy = 4;
                            gradingProperties.FinalPoints = (float)Math.Round(
                                s_random.NextDouble() * divideBy *
                                assignmentProperties.PointsPossible.Value) / divideBy;
                        }
                    }

                    // update statistics
                    newStatusCount[(int)gradingProperties.Status]++;
                }

                // save changes to the assignment
                string warnings = slkStore.SetGradingProperties(assignmentId,
                                                                gradingPropertiesList);
                Debug.Assert(warnings == null, warnings);

                // display feedback
                Console.WriteLine("{0,-8}{1,-10}{2,-10:d}{3,-8}{4,-7}{5,-10}{6,-6}",
                                  assignmentId.GetKey(), assignmentProperties.Learners.Count,
                                  assignmentProperties.DueDate, newStatusCount[0], newStatusCount[1],
                                  newStatusCount[2], newStatusCount[3]);
            }
        }
        finally
        {
            // dispose of objects used by this method
            while (disposer.Count > 0)
            {
                disposer.Pop().Dispose();
            }
        }
    }
        /// Returns true if the correct version of the file exists in SharePoint.
        /// NOTE: This method checks file availability using elevated privileges. Be
        /// cautious when using this information in messages displayed to the user.
        private static bool FileExistsInSharePoint(string location)
        {
            SharePointFileLocation spFileLocation;
            bool fileExists = true;    // assume it exists

            if (SharePointFileLocation.TryParse(location, out spFileLocation))
            {
                SPSecurity.RunWithElevatedPrivileges(delegate()
                {
                    // If the site does not exist, this throws FileNotFound
                    using (SPSite spSite = new SPSite(spFileLocation.SiteId, SPContext.Current.Site.Zone))
                    {
                        // If the web does not exist, this throws FileNotFound
                        using (SPWeb spWeb = spSite.OpenWeb(spFileLocation.WebId))
                        {
                            SPFile spFile = spWeb.GetFile(spFileLocation.FileId);
                            if (!spFile.Exists)
                            {
                                fileExists = false;
                                return;
                            }
                            // The file exists. Now check if the right version exists.
                            DateTime lastModified;
                            if ((spFile.Versions.Count == 0) || spFile.UIVersion == spFileLocation.VersionId)
                            {
                                // The requested version is the currect one
                                if (spFile.UIVersion != spFileLocation.VersionId)
                                {
                                    fileExists = false;
                                    return;
                                }
                                // It exists: check its timestamp
                                lastModified = spFile.TimeLastModified;
                            }
                            else
                            {
                                // The specified version isn't the current one
                                SPFileVersion spFileVersion = spFile.Versions.GetVersionFromID(spFileLocation.VersionId);

                                if (spFileVersion == null)
                                {
                                    fileExists = false;
                                    return;
                                }

                                // There is no 'last modified' of a version, so use the time the version was created.
                                lastModified = spFileVersion.Created;
                            }

                            // If the timestamps are not the same, the file has been modified, so return false
                            if (lastModified.CompareTo(spFileLocation.Timestamp) != 0)
                            {
                                fileExists = false;
                                return;
                            }
                        }
                    }
                });
            }
            return(fileExists);
        }