public static BasicResult DeleteScore(string serviceUrl, string consumerKey, string consumerSecret, string lisResultSourcedId)
        {
            var imsxEnvelope = new imsx_POXEnvelopeType
            {
                imsx_POXHeader = new imsx_POXHeaderType {Item = new imsx_RequestHeaderInfoType()},
                imsx_POXBody = new imsx_POXBodyType {Item = new deleteResultRequest()}
            };

            var imsxHeader = (imsx_RequestHeaderInfoType) imsxEnvelope.imsx_POXHeader.Item;
            imsxHeader.imsx_version = imsx_GWSVersionValueType.V10;
            imsxHeader.imsx_messageIdentifier = Guid.NewGuid().ToString();

            var imsxBody = (deleteResultRequest) imsxEnvelope.imsx_POXBody.Item;
            imsxBody.resultRecord = new ResultRecordType
            {
                sourcedGUID = new SourcedGUIDType {sourcedId = lisResultSourcedId}
            };

            try
            {
                var webRequest = CreateLtiOutcomesRequest(
                    imsxEnvelope,
                    serviceUrl,
                    consumerKey,
                    consumerSecret);
                var webResponse = webRequest.GetResponse() as HttpWebResponse;
                return ParseDeleteResultResponse(webResponse);
            }
            catch (Exception ex)
            {
                return new BasicResult(false, ex.ToString());
            }
        }
Example #2
0
        public static bool DeleteScore(string serviceUrl, string consumerKey, string consumerSecret, string lisResultSourcedId)
        {
            var imsxEnvelope = new imsx_POXEnvelopeType();

            imsxEnvelope.imsx_POXHeader      = new imsx_POXHeaderType();
            imsxEnvelope.imsx_POXHeader.Item = new imsx_RequestHeaderInfoType();
            imsxEnvelope.imsx_POXBody        = new imsx_POXBodyType();
            imsxEnvelope.imsx_POXBody.Item   = new deleteResultRequest();

            var imsxHeader = imsxEnvelope.imsx_POXHeader.Item as imsx_RequestHeaderInfoType;

            imsxHeader.imsx_version           = imsx_GWSVersionValueType.V10;
            imsxHeader.imsx_messageIdentifier = Guid.NewGuid().ToString();

            var imsxBody = imsxEnvelope.imsx_POXBody.Item as deleteResultRequest;

            imsxBody.resultRecord                       = new ResultRecordType();
            imsxBody.resultRecord.sourcedGUID           = new SourcedGUIDType();
            imsxBody.resultRecord.sourcedGUID.sourcedId = lisResultSourcedId;

            try
            {
                var webRequest = CreateLtiOutcomesRequest(
                    imsxEnvelope,
                    serviceUrl,
                    consumerKey,
                    consumerSecret);
                var webResponse = webRequest.GetResponse() as HttpWebResponse;
                return(ParseDeleteResultResponse(webResponse));
            }
            catch (Exception)
            {
                return(false);
            }
        }
        public async Task <IActionResult> Post([ModelBinder(BinderType = typeof(ImsxXmlMediaTypeModelBinder))] imsx_POXEnvelopeType request)
        {
            if (request == null)
            {
                return(BadRequest("Empty request."));
            }

            var requestHeader = request.imsx_POXHeader.Item as imsx_RequestHeaderInfoType;

            if (requestHeader == null)
            {
                return(BadRequest("Invalid request header."));
            }

            // All requests come in the same basic body element
            var requestBody = request.imsx_POXBody;

            // Delete Result
            if (requestBody.Item is deleteResultRequest)
            {
                return(await HandleDeleteResultRequest(requestHeader, requestBody));
            }
            if (requestBody.Item is readResultRequest)
            {
                return(await HandleReadResultRequest(requestHeader, requestBody));
            }
            if (requestBody.Item is replaceResultRequest)
            {
                return(await HandleReplaceResultRequest(requestHeader, requestBody));
            }
            return(BadRequest("Request type not supported."));
        }
        /// <summary>
        /// Create a simple, but complete response envelope. The status is set to success.
        /// </summary>
        /// <param name="responseItem">The ismx response element.</param>
        /// <param name="messageRefId">The request message ID.</param>
        /// <param name="description">The status description.</param>
        /// <returns>A response envelope.</returns>
        private static ImsxXmlMediaTypeResult CreateSuccessResponse(object responseItem, string messageRefId, string description)
        {
            var response = new imsx_POXEnvelopeType
            {
                imsx_POXHeader = new imsx_POXHeaderType {
                    Item = new imsx_ResponseHeaderInfoType()
                }
            };

            var item = (imsx_ResponseHeaderInfoType)response.imsx_POXHeader.Item;

            item.imsx_version           = imsx_GWSVersionValueType.V10;
            item.imsx_messageIdentifier = Guid.NewGuid().ToString();
            item.imsx_statusInfo        = new imsx_StatusInfoType();

            var status = item.imsx_statusInfo;

            status.imsx_codeMajor            = imsx_CodeMajorType.success;
            status.imsx_severity             = imsx_SeverityType.status;
            status.imsx_description          = description;
            status.imsx_messageRefIdentifier = messageRefId;

            response.imsx_POXBody = new imsx_POXBodyType {
                Item = responseItem
            };
            return(new ImsxXmlMediaTypeResult(response));
        }
Example #5
0
        /// <summary>
        /// Create a simple, but complete response envelope. The status is set to success.
        /// </summary>
        private static async Task <ObjectResult> CreateSuccessResponse()
        {
            var response = new imsx_POXEnvelopeType
            {
                imsx_POXHeader = new imsx_POXHeaderType {
                    Item = new imsx_ResponseHeaderInfoType()
                },
                imsx_POXBody = new imsx_POXBodyType {
                    Item = new readResultResponse()
                }
            };

            var item = (imsx_ResponseHeaderInfoType)response.imsx_POXHeader.Item;

            item.imsx_version           = imsx_GWSVersionValueType.V10;
            item.imsx_messageIdentifier = Guid.NewGuid().ToString();
            item.imsx_statusInfo        = new imsx_StatusInfoType();

            var status = item.imsx_statusInfo;

            status.imsx_codeMajor = imsx_CodeMajorType.success;
            status.imsx_severity  = imsx_SeverityType.status;

            using (var ms = new MemoryStream())
            {
                ImsxResponseSerializer.Serialize(ms, response);
                using (var reader = new StreamReader(ms))
                {
                    ms.Position = 0;
                    return(new ObjectResult(await reader.ReadToEndAsync()));
                }
            }
        }
Example #6
0
        private static HttpWebRequest CreateLtiOutcomesRequest(imsx_POXEnvelopeType imsxEnvelope, string url, string consumerKey, string consumerSecret)
        {
            var webRequest = (HttpWebRequest)WebRequest.Create(url);

            webRequest.Method      = "POST";
            webRequest.ContentType = "application/xml";

            var parameters = new NameValueCollection();

            parameters.AddParameter(OAuthConstants.ConsumerKeyParameter, consumerKey);
            parameters.AddParameter(OAuthConstants.NonceParameter, Guid.NewGuid().ToString());
            parameters.AddParameter(OAuthConstants.SignatureMethodParameter, OAuthConstants.SignatureMethodHmacSha1);
            parameters.AddParameter(OAuthConstants.VersionParameter, OAuthConstants.Version10);

            // Calculate the timestamp
            var ts        = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
            var timestamp = Convert.ToInt64(ts.TotalSeconds);

            parameters.AddParameter(OAuthConstants.TimestampParameter, timestamp);

            // Calculate the body hash
            using (var ms = new MemoryStream())
                using (var sha1 = new SHA1CryptoServiceProvider())
                {
                    ImsxRequestSerializer.Serialize(ms, imsxEnvelope);
                    ms.Position = 0;
                    ms.CopyTo(webRequest.GetRequestStream());

                    var hash   = sha1.ComputeHash(ms.ToArray());
                    var hash64 = Convert.ToBase64String(hash);
                    parameters.AddParameter(OAuthConstants.BodyHashParameter, hash64);
                }

            // Calculate the signature
            var signature = OAuthUtility.GenerateSignature(webRequest.Method, webRequest.RequestUri, parameters,
                                                           consumerSecret);

            parameters.AddParameter(OAuthConstants.SignatureParameter, signature);

            // Build the Authorization header
            var authorization = new StringBuilder(OAuthConstants.AuthScheme).Append(" ");

            foreach (var key in parameters.AllKeys)
            {
                authorization.AppendFormat("{0}=\"{1}\",", key, HttpUtility.UrlEncode(parameters[key]));
            }
            webRequest.Headers["Authorization"] = authorization.ToString(0, authorization.Length - 1);

            return(webRequest);
        }
        public virtual async Task <IActionResult> Post([ModelBinder(BinderType = typeof(ImsxXmlMediaTypeModelBinder))] imsx_POXEnvelopeType request)
        {
            if (request == null)
            {
                return(BadRequest("Empty request."));
            }

            // Check for required Authorization header with parameters dictated by the OAuth Body Hash Protocol
            if (!Request.IsAuthenticatedWithLti())
            {
                return(Unauthorized());
            }

            if (!(request.imsx_POXHeader.Item is imsx_RequestHeaderInfoType requestHeader))
            {
                return(BadRequest("Invalid request header."));
            }

            // All requests come in the same basic body element
            var requestBody = request.imsx_POXBody;

            // Delete Result
            switch (requestBody.Item)
            {
            case deleteResultRequest _:
                if (OnDeleteResultAsync == null)
                {
                    return(StatusCode(StatusCodes.Status404NotFound));
                }
                return(await HandleDeleteResultRequest(requestHeader, requestBody)
                       .ConfigureAwait(false));

            case readResultRequest _:
                if (OnReadResultAsync == null)
                {
                    return(StatusCode(StatusCodes.Status404NotFound));
                }
                return(await HandleReadResultRequest(requestHeader, requestBody)
                       .ConfigureAwait(false));

            case replaceResultRequest _:
                if (OnReplaceResultAsync == null)
                {
                    return(StatusCode(StatusCodes.Status404NotFound));
                }
                return(await HandleReplaceResultRequest(requestHeader, requestBody)
                       .ConfigureAwait(false));
            }
            return(BadRequest("Request type not supported."));
        }
        public HttpResponseMessage Post(imsx_POXEnvelopeType request)
        {
            imsx_POXEnvelopeType response;

            if (request == null)
            {
                response = CreateCustomResponse(string.Empty,
                                                "Invalid request",
                                                imsx_CodeMajorType.failure);
            }
            else
            {
                var requestHeader = request.imsx_POXHeader.Item as imsx_RequestHeaderInfoType;
                if (requestHeader == null)
                {
                    response = CreateCustomResponse(string.Empty,
                                                    "Invalid request header",
                                                    imsx_CodeMajorType.failure);
                }
                else
                {
                    // All requests come in the same basic body element
                    var requestBody = request.imsx_POXBody;

                    // Delete Result
                    if (requestBody.Item is deleteResultRequest)
                    {
                        response = HandleDeleteResultRequest(requestHeader, requestBody);
                    }
                    else if (requestBody.Item is readResultRequest)
                    {
                        response = HandleReadResultRequest(requestHeader, requestBody);
                    }
                    else if (requestBody.Item is replaceResultRequest)
                    {
                        response = HandleReplaceResultRequest(requestHeader, requestBody);
                    }
                    else
                    {
                        response = CreateCustomResponse(requestHeader.imsx_messageIdentifier,
                                                        "Request is not supported",
                                                        imsx_CodeMajorType.unsupported);
                    }
                }
            }
            return(Request.CreateResponse(HttpStatusCode.OK, response, new ImsxXmlMediaTypeFormatter()));
        }
Example #9
0
        public static async Task<BasicResult> PostScoreAsync(string serviceUrl, string consumerKey, string consumerSecret, string lisResultSourcedId, double? score)
        {
            var imsxEnvelope = new imsx_POXEnvelopeType
            {
                imsx_POXHeader = new imsx_POXHeaderType {Item = new imsx_RequestHeaderInfoType()},
                imsx_POXBody = new imsx_POXBodyType {Item = new replaceResultRequest()}
            };

            var imsxHeader = (imsx_RequestHeaderInfoType) imsxEnvelope.imsx_POXHeader.Item;
            imsxHeader.imsx_version = imsx_GWSVersionValueType.V10;
            imsxHeader.imsx_messageIdentifier = Guid.NewGuid().ToString();

            var imsxBody = (replaceResultRequest) imsxEnvelope.imsx_POXBody.Item;
            imsxBody.resultRecord = new ResultRecordType
            {
                sourcedGUID = new SourcedGUIDType {sourcedId = lisResultSourcedId},
                result = new ResultType
                {
                    resultScore = new TextType
                    {
                        language = LtiConstants.ScoreLanguage,
                        textString = score?.ToString(new CultureInfo(LtiConstants.ScoreLanguage))
                    }
                }
            };
            // The LTI 1.1 specification states in 6.1.1. that the score in replaceResult should
            // always be formatted using “en” formatting
            // (http://www.imsglobal.org/LTI/v1p1p1/ltiIMGv1p1p1.html#_Toc330273034).

            try
            {
                var webRequest = CreateLtiOutcomesRequest(
                    imsxEnvelope,
                    serviceUrl,
                    consumerKey,
                    consumerSecret);
                using (var webResponse = await webRequest.GetResponseAsync())
                {
                    return ParsePostResultResponse(webResponse);
                }
            }
            catch (Exception ex)
            {
                return new BasicResult(false, ex.ToString());
            }
        }
        public HttpResponseMessage Post(imsx_POXEnvelopeType request)
        {
            imsx_POXEnvelopeType response;
            if (request == null)
            {
                response = CreateCustomResponse(string.Empty,
                    "Invalid request",
                    imsx_CodeMajorType.failure);
            }
            else
            {
                var requestHeader = request.imsx_POXHeader.Item as imsx_RequestHeaderInfoType;
                if (requestHeader == null)
                {
                    response = CreateCustomResponse(string.Empty,
                        "Invalid request header",
                        imsx_CodeMajorType.failure);
                }
                else
                {
                    // All requests come in the same basic body element
                    var requestBody = request.imsx_POXBody;

                    // Delete Result
                    if (requestBody.Item is deleteResultRequest)
                    {
                        response = HandleDeleteResultRequest(requestHeader, requestBody);
                    }
                    else if (requestBody.Item is readResultRequest)
                    {
                        response = HandleReadResultRequest(requestHeader, requestBody);
                    }
                    else if (requestBody.Item is replaceResultRequest)
                    {
                        response = HandleReplaceResultRequest(requestHeader, requestBody);
                    }
                    else
                    {
                        response = CreateCustomResponse(requestHeader.imsx_messageIdentifier,
                            "Request is not supported",
                            imsx_CodeMajorType.unsupported);
                    }
                }
            }
            return Request.CreateResponse(HttpStatusCode.OK, response, new ImsxXmlMediaTypeFormatter());
        }
Example #11
0
 /// <summary>
 /// Serialize the <see cref="imsx_POXEnvelopeType"/> into a <see cref="Encoding.UTF8"/> encoded string.
 /// </summary>
 /// <param name="imsxEnvelope"></param>
 /// <returns></returns>
 private static async Task <string> GetXmlAsync(imsx_POXEnvelopeType imsxEnvelope)
 {
     using (var ms = new MemoryStream())
     {
         using (var writer =
                    XmlWriter.Create(ms, new XmlWriterSettings
         {
             Async = true,
             Encoding = Encoding.UTF8,
             Indent = true
         }))
         {
             ImsxRequestSerializer.Serialize(writer, imsxEnvelope);
             await writer.FlushAsync();
         }
         return(Encoding.UTF8.GetString(ms.ToArray()));
     }
 }
Example #12
0
        public static bool PostScore(string serviceUrl, string consumerKey, string consumerSecret, string lisResultSourcedId, double?score)
        {
            var imsxEnvelope = new imsx_POXEnvelopeType();

            imsxEnvelope.imsx_POXHeader      = new imsx_POXHeaderType();
            imsxEnvelope.imsx_POXHeader.Item = new imsx_RequestHeaderInfoType();
            imsxEnvelope.imsx_POXBody        = new imsx_POXBodyType();
            imsxEnvelope.imsx_POXBody.Item   = new replaceResultRequest();

            var imsxHeader = imsxEnvelope.imsx_POXHeader.Item as imsx_RequestHeaderInfoType;

            imsxHeader.imsx_version           = imsx_GWSVersionValueType.V10;
            imsxHeader.imsx_messageIdentifier = Guid.NewGuid().ToString();

            var imsxBody = imsxEnvelope.imsx_POXBody.Item as replaceResultRequest;

            imsxBody.resultRecord                               = new ResultRecordType();
            imsxBody.resultRecord.sourcedGUID                   = new SourcedGUIDType();
            imsxBody.resultRecord.sourcedGUID.sourcedId         = lisResultSourcedId;
            imsxBody.resultRecord.result                        = new ResultType();
            imsxBody.resultRecord.result.resultScore            = new TextType();
            imsxBody.resultRecord.result.resultScore.language   = CultureInfo.CurrentCulture.Name;
            imsxBody.resultRecord.result.resultScore.textString = score.ToString();

            try
            {
                var webRequest = CreateLtiOutcomesRequest(
                    imsxEnvelope,
                    serviceUrl,
                    consumerKey,
                    consumerSecret);
                var webResponse = webRequest.GetResponse() as HttpWebResponse;
                return(ParsePostResultResponse(webResponse));
            }
            catch (Exception)
            {
                return(false);
            }
        }
Example #13
0
        /// <summary>
        /// Create a simple, but complete response envelope. The status is set to success.
        /// </summary>
        /// <param name="messageRefId">The request message ID.</param>
        /// <param name="description">The status description.</param>
        /// <returns>A response envelope.</returns>
        private static imsx_POXEnvelopeType CreateSuccessResponse(string messageRefId, string description)
        {
            var response = new imsx_POXEnvelopeType();

            response.imsx_POXHeader      = new imsx_POXHeaderType();
            response.imsx_POXHeader.Item = new imsx_ResponseHeaderInfoType();

            var item = response.imsx_POXHeader.Item as imsx_ResponseHeaderInfoType;

            item.imsx_version           = imsx_GWSVersionValueType.V10;
            item.imsx_messageIdentifier = Guid.NewGuid().ToString();
            item.imsx_statusInfo        = new imsx_StatusInfoType();

            var status = item.imsx_statusInfo;

            status.imsx_codeMajor            = imsx_CodeMajorType.success;
            status.imsx_severity             = imsx_SeverityType.status;
            status.imsx_description          = description;
            status.imsx_messageRefIdentifier = messageRefId;

            response.imsx_POXBody = new imsx_POXBodyType();
            return(response);
        }
Example #14
0
        /// <summary>
        /// Send an Outcomes 1.0 ReadScore request and return the LisResult.
        /// </summary>
        /// <param name="client">The HttpClient that will be used to process the request.</param>
        /// <param name="serviceUrl">The URL to send the request to.</param>
        /// <param name="consumerKey">The OAuth key to sign the request.</param>
        /// <param name="consumerSecret">The OAuth secret to sign the request.</param>
        /// <param name="lisResultSourcedId">The LisResult to read.</param>
        /// <param name="signatureMethod">The signatureMethod. Defaults to <see cref="SignatureMethod.HmacSha1"/></param>
        /// <returns>A <see cref="ClientResponse"/>.</returns>
        public static async Task<ClientResponse<Result>> ReadResultAsync(HttpClient client, string serviceUrl, string consumerKey, string consumerSecret, 
            string lisResultSourcedId, SignatureMethod signatureMethod = SignatureMethod.HmacSha1)
        {
            try
            {
                var imsxEnvelope = new imsx_POXEnvelopeType
                {
                    imsx_POXHeader = new imsx_POXHeaderType { Item = new imsx_RequestHeaderInfoType() },
                    imsx_POXBody = new imsx_POXBodyType { Item = new readResultRequest() }
                };

                var imsxHeader = (imsx_RequestHeaderInfoType)imsxEnvelope.imsx_POXHeader.Item;
                imsxHeader.imsx_version = imsx_GWSVersionValueType.V10;
                imsxHeader.imsx_messageIdentifier = Guid.NewGuid().ToString();

                var imsxBody = (readResultRequest)imsxEnvelope.imsx_POXBody.Item;
                imsxBody.resultRecord = new ResultRecordType
                {
                    sourcedGUID = new SourcedGUIDType { sourcedId = lisResultSourcedId }
                };

                var outcomeResponse = new ClientResponse<Result>();
                try
                {
                    client.DefaultRequestHeaders.Accept.Clear();
                    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(LtiConstants.ImsxOutcomeMediaType));

                    // Create a UTF8 encoding of the request
                    var xml = await GetXmlAsync(imsxEnvelope).ConfigureAwait(false);
                    var xmlContent = new StringContent(xml, Encoding.UTF8, LtiConstants.ImsxOutcomeMediaType);
                    await SecuredClient.SignRequest
                        (client, HttpMethod.Post, serviceUrl, xmlContent, consumerKey, consumerSecret, signatureMethod)
                        .ConfigureAwait(false);

                    // Post the request and check the response
                    using (var response = await client.PostAsync(serviceUrl, xmlContent).ConfigureAwait(false))
                    {
                        outcomeResponse.StatusCode = response.StatusCode;
                        if (response.IsSuccessStatusCode)
                        {
                            var imsxResponseEnvelope = (imsx_POXEnvelopeType)ImsxResponseSerializer.Deserialize
                                (await response.Content.ReadAsStreamAsync().ConfigureAwait(false));
                            var imsxResponseHeader = (imsx_ResponseHeaderInfoType)imsxResponseEnvelope.imsx_POXHeader.Item;
                            var imsxResponseStatus = imsxResponseHeader.imsx_statusInfo.imsx_codeMajor;

                            if (imsxResponseStatus == imsx_CodeMajorType.success)
                            {
                                var imsxResponseBody = (readResultResponse)imsxResponseEnvelope.imsx_POXBody.Item;
                                if (imsxResponseBody?.result == null)
                                {
                                    outcomeResponse.Response = new Result { Score = null };
                                }
                                else
                                {
                                    // The TP is supposed to use "en" language format, but this allows
                                    // a little bit of misbehaving. If the TP does not include a language, "en" will
                                    // be used. If the TP does include a language (even a non-en language), it will
                                    // be used.
                                    var cultureInfo = new CultureInfo(imsxResponseBody.result.resultScore.language??"en");
                                    outcomeResponse.Response = double.TryParse(imsxResponseBody.result.resultScore.textString, NumberStyles.Number, cultureInfo, out var result) 
                                        ? new Result { Score = result, SourcedId = lisResultSourcedId } 
                                        : new Result { Score = null, SourcedId = lisResultSourcedId };
                                }
                            }
                            else
                            {
                                outcomeResponse.StatusCode = HttpStatusCode.BadRequest;
                            }
                        }
#if DEBUG
                        outcomeResponse.HttpRequest = await response.RequestMessage.ToFormattedRequestStringAsync
                            (new StringContent(xml, Encoding.UTF8, LtiConstants.ImsxOutcomeMediaType))
                            .ConfigureAwait(false);
#endif
                        outcomeResponse.HttpResponse = await response.ToFormattedResponseStringAsync()
                            .ConfigureAwait(false);
                    }
                }
                catch (HttpRequestException ex)
                {
                    outcomeResponse.Exception = ex;
                    outcomeResponse.StatusCode = HttpStatusCode.BadRequest;
                }
                catch (Exception ex)
                {
                    outcomeResponse.Exception = ex;
                    outcomeResponse.StatusCode = HttpStatusCode.InternalServerError;
                }
                return outcomeResponse;
            }
            catch (Exception ex)
            {
                return new ClientResponse<Result>
                {
                    Exception = ex,
                    StatusCode = HttpStatusCode.InternalServerError
                };
            }
        }
Example #15
0
        public static async Task<LisResult> ReadScoreAsync(string serviceUrl, string consumerKey, string consumerSecret, string lisResultSourcedId)
        {
            var imsxEnvelope = new imsx_POXEnvelopeType
            {
                imsx_POXHeader = new imsx_POXHeaderType {Item = new imsx_RequestHeaderInfoType()},
                imsx_POXBody = new imsx_POXBodyType {Item = new readResultRequest()}
            };

            var imsxHeader = (imsx_RequestHeaderInfoType) imsxEnvelope.imsx_POXHeader.Item;
            imsxHeader.imsx_version = imsx_GWSVersionValueType.V10;
            imsxHeader.imsx_messageIdentifier = Guid.NewGuid().ToString();

            var imsxBody = (readResultRequest) imsxEnvelope.imsx_POXBody.Item;
            imsxBody.resultRecord = new ResultRecordType
            {
                sourcedGUID = new SourcedGUIDType {sourcedId = lisResultSourcedId}
            };

            try
            {
                var webRequest = CreateLtiOutcomesRequest(
                    imsxEnvelope,
                    serviceUrl,
                    consumerKey,
                    consumerSecret);
                using (var webResponse = await webRequest.GetResponseAsync())
                {
                    return ParseReadResultResponse(webResponse);
                }
            }
            catch (Exception ex)
            {
                return new LisResult {IsValid = false, Message = ex.ToString()};
            }
        }
Example #16
0
        public imsx_POXEnvelopeType Post(imsx_POXEnvelopeType request)
        {
            imsx_POXEnvelopeType response = null;

            if (request == null)
            {
                response = CreateCustomResponse(string.Empty,
                                                "Invalid request",
                                                imsx_CodeMajorType.failure);
            }
            else
            {
                var requestHeader = request.imsx_POXHeader.Item as imsx_RequestHeaderInfoType;
                if (requestHeader == null)
                {
                    response = CreateCustomResponse(string.Empty,
                                                    "Invalid request header",
                                                    imsx_CodeMajorType.failure);
                }
                else
                {
                    // Authenticate and authorize the request
                    var isAuthorized = false;
                    try
                    {
                        Authorize();
                        isAuthorized = true;
                    }
                    catch (LtiException ex)
                    {
                        response = CreateCustomResponse(requestHeader.imsx_messageIdentifier,
                                                        ex.Message,
                                                        imsx_CodeMajorType.failure);
                    }

                    if (isAuthorized)
                    {
                        // All requests come in the same basic body element
                        var requestBody = request.imsx_POXBody;

                        // Delete Result
                        if (requestBody.Item is deleteResultRequest)
                        {
                            response = HandleDeleteResultRequest(requestHeader, requestBody);
                        }
                        else if (requestBody.Item is readResultRequest)
                        {
                            response = HandleReadResultRequest(requestHeader, requestBody);
                        }
                        else if (requestBody.Item is replaceResultRequest)
                        {
                            response = HandleReplaceResultRequest(requestHeader, requestBody);
                        }
                        else
                        {
                            response = CreateCustomResponse(requestHeader.imsx_messageIdentifier,
                                                            "Request is not supported",
                                                            imsx_CodeMajorType.unsupported);
                        }
                    }
                }
            }
            return(response);
        }
 public ImsxXmlMediaTypeResult(imsx_POXEnvelopeType value) : base(value)
 {
     // This formatter produces an imsx_POXEnvelopeType with an imsx_POXEnvelopeResponse
     Formatters.Add(new ImsxXmlMediaTypeOutputFormatter());
 }
        private static HttpWebRequest CreateLtiOutcomesRequest(imsx_POXEnvelopeType imsxEnvelope, string url, string consumerKey, string consumerSecret)
        {
            var webRequest = (HttpWebRequest) WebRequest.Create(url);
            webRequest.Method = "POST";
            webRequest.ContentType = "application/xml";

            var parameters = new NameValueCollection();
            parameters.AddParameter(OAuthConstants.ConsumerKeyParameter, consumerKey);
            parameters.AddParameter(OAuthConstants.NonceParameter, Guid.NewGuid().ToString());
            parameters.AddParameter(OAuthConstants.SignatureMethodParameter, OAuthConstants.SignatureMethodHmacSha1);
            parameters.AddParameter(OAuthConstants.VersionParameter, OAuthConstants.Version10);

            // Calculate the timestamp
            var ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
            var timestamp = Convert.ToInt64(ts.TotalSeconds);
            parameters.AddParameter(OAuthConstants.TimestampParameter, timestamp);

            // Calculate the body hash
            using (var ms = new MemoryStream())
            using (var sha1 = new SHA1CryptoServiceProvider())
            {
                ImsxRequestSerializer.Serialize(ms, imsxEnvelope);
                ms.Position = 0;
                ms.CopyTo(webRequest.GetRequestStream());

                var hash = sha1.ComputeHash(ms.ToArray());
                var hash64 = Convert.ToBase64String(hash);
                parameters.AddParameter(OAuthConstants.BodyHashParameter, hash64);
            }

            // Calculate the signature
            var signature = OAuthUtility.GenerateSignature(webRequest.Method, webRequest.RequestUri, parameters,
                consumerSecret);
            parameters.AddParameter(OAuthConstants.SignatureParameter, signature);

            // Build the Authorization header
            var authorization = new StringBuilder(OAuthConstants.AuthScheme).Append(" ");
            foreach (var key in parameters.AllKeys)
            {
                authorization.AppendFormat("{0}=\"{1}\",", key, WebUtility.UrlEncode(parameters[key]));
            }
            webRequest.Headers["Authorization"] = authorization.ToString(0, authorization.Length - 1);

            return webRequest;
        }
Example #19
0
        /// <summary>
        /// Send an Outcomes 1.0 ReplaceResult request.
        /// </summary>
        /// <param name="client">The HttpClient that will be used to process the request.</param>
        /// <param name="serviceUrl">The URL to send the request to.</param>
        /// <param name="consumerKey">The OAuth key to sign the request.</param>
        /// <param name="consumerSecret">The OAuth secret to sign the request.</param>
        /// <param name="lisResultSourcedId">The LisResult to receive the score.</param>
        /// <param name="score">The score.</param>
        /// <returns>A <see cref="ClientResponse"/>.</returns>
        public static async Task <ClientResponse> ReplaceResultAsync(HttpClient client, string serviceUrl, string consumerKey, string consumerSecret, string lisResultSourcedId, double?score)
        {
            try
            {
                var imsxEnvelope = new imsx_POXEnvelopeType
                {
                    imsx_POXHeader = new imsx_POXHeaderType {
                        Item = new imsx_RequestHeaderInfoType()
                    },
                    imsx_POXBody = new imsx_POXBodyType {
                        Item = new replaceResultRequest()
                    }
                };

                var imsxHeader = (imsx_RequestHeaderInfoType)imsxEnvelope.imsx_POXHeader.Item;
                imsxHeader.imsx_version           = imsx_GWSVersionValueType.V10;
                imsxHeader.imsx_messageIdentifier = Guid.NewGuid().ToString();

                var imsxBody = (replaceResultRequest)imsxEnvelope.imsx_POXBody.Item;
                imsxBody.resultRecord = new ResultRecordType
                {
                    sourcedGUID = new SourcedGUIDType {
                        sourcedId = lisResultSourcedId
                    },
                    result = new ResultType
                    {
                        resultScore = new TextType
                        {
                            language = LtiConstants.ScoreLanguage,
                            // The LTI 1.1 specification states in 6.1.1. that the score in replaceResult should
                            // always be formatted using “en” formatting
                            // (http://www.imsglobal.org/LTI/v1p1p1/ltiIMGv1p1p1.html#_Toc330273034).
                            textString = score?.ToString(new CultureInfo(LtiConstants.ScoreLanguage))
                        }
                    }
                };

                var outcomeResponse = new ClientResponse();
                try
                {
                    client.DefaultRequestHeaders.Accept.Clear();
                    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(LtiConstants.ImsxOutcomeMediaType));

                    // Create a UTF8 encoding of the request
                    var xml = await GetXmlAsync(imsxEnvelope);

                    var xmlContent = new StringContent(xml, Encoding.UTF8, LtiConstants.ImsxOutcomeMediaType);
                    await SecuredClient.SignRequest(client, HttpMethod.Post, serviceUrl, xmlContent, consumerKey, consumerSecret);

                    // Post the request and check the response
                    using (var response = await client.PostAsync(serviceUrl, xmlContent))
                    {
                        outcomeResponse.StatusCode = response.StatusCode;
                        if (response.IsSuccessStatusCode)
                        {
                            var imsxResponseEnvelope = (imsx_POXEnvelopeType)ImsxResponseSerializer.Deserialize(await response.Content.ReadAsStreamAsync());
                            var imsxResponseHeader   = (imsx_ResponseHeaderInfoType)imsxResponseEnvelope.imsx_POXHeader.Item;
                            var imsxResponseStatus   = imsxResponseHeader.imsx_statusInfo.imsx_codeMajor;

                            outcomeResponse.StatusCode = imsxResponseStatus == imsx_CodeMajorType.success
                                ? HttpStatusCode.OK
                                : HttpStatusCode.BadRequest;
                        }
#if DEBUG
                        outcomeResponse.HttpRequest = await response.RequestMessage.ToFormattedRequestStringAsync(new StringContent(xml, Encoding.UTF8, LtiConstants.ImsxOutcomeMediaType));

                        outcomeResponse.HttpResponse = await response.ToFormattedResponseStringAsync();
#endif
                    }
                }
                catch (HttpRequestException ex)
                {
                    outcomeResponse.Exception  = ex;
                    outcomeResponse.StatusCode = HttpStatusCode.BadRequest;
                }
                catch (Exception ex)
                {
                    outcomeResponse.Exception  = ex;
                    outcomeResponse.StatusCode = HttpStatusCode.InternalServerError;
                }
                return(outcomeResponse);
            }
            catch (Exception ex)
            {
                return(new ClientResponse
                {
                    Exception = ex,
                    StatusCode = HttpStatusCode.InternalServerError
                });
            }
        }
Example #20
0
        /// <summary>
        /// Send an Outcomes 1.0 ReplaceResult request.
        /// </summary>
        /// <param name="client">The HttpClient that will be used to process the request.</param>
        /// <param name="serviceUrl">The URL to send the request to.</param>
        /// <param name="consumerKey">The OAuth key to sign the request.</param>
        /// <param name="consumerSecret">The OAuth secret to sign the request.</param>
        /// <param name="lisResultSourcedId">The LisResult to receive the score.</param>
        /// <param name="score">The score.</param>
        /// <param name="text">Optional text data (Canvas extension)</param>
        /// <param name="url">Optional url data</param>
        /// <param name="ltiLaunchUrl">Optional LTI launch URL data</param>
        /// <param name="signatureMethod">The signatureMethod. Defaults to <see cref="SignatureMethod.HmacSha1"/></param>
        /// <returns>A <see cref="ClientResponse"/>.</returns>
        public static async Task <ClientResponse> ReplaceResultAsync(HttpClient client, string serviceUrl, string consumerKey, string consumerSecret,
                                                                     string lisResultSourcedId, double?score, string text = null, string url = null, string ltiLaunchUrl = null, SignatureMethod signatureMethod = SignatureMethod.HmacSha1)
        {
            try
            {
                var imsxEnvelope = new imsx_POXEnvelopeType
                {
                    imsx_POXHeader = new imsx_POXHeaderType {
                        Item = new imsx_RequestHeaderInfoType()
                    },
                    imsx_POXBody = new imsx_POXBodyType {
                        Item = new replaceResultRequest()
                    }
                };

                var imsxHeader = (imsx_RequestHeaderInfoType)imsxEnvelope.imsx_POXHeader.Item;
                imsxHeader.imsx_version           = imsx_GWSVersionValueType.V10;
                imsxHeader.imsx_messageIdentifier = Guid.NewGuid().ToString();

                var imsxBody = (replaceResultRequest)imsxEnvelope.imsx_POXBody.Item;
                imsxBody.resultRecord = new ResultRecordType
                {
                    sourcedGUID = new SourcedGUIDType {
                        sourcedId = lisResultSourcedId
                    },
                    result = new ResultType
                    {
                        resultScore = new TextType
                        {
                            language = LtiConstants.ScoreLanguage,
                            // The LTI 1.1 specification states in 6.1.1. that the score in replaceResult should
                            // always be formatted using “en” formatting
                            // (http://www.imsglobal.org/LTI/v1p1p1/ltiIMGv1p1p1.html#_Toc330273034).
                            textString = score?.ToString(new CultureInfo(LtiConstants.ScoreLanguage))
                        }
                    }
                };

                // If any ResultData is supplied, add the ResultData element
                if (!string.IsNullOrEmpty(text + url + ltiLaunchUrl))
                {
                    var resultData = imsxBody.resultRecord.result.ResultData = new DataType();
                    resultData.LtiLaunchUrl = ltiLaunchUrl;
                    resultData.Text         = text;
                    resultData.Url          = url;
                }

                var outcomeResponse = new ClientResponse();
                try
                {
                    // Create a UTF8 encoding of the request
                    var xml = await GetXmlAsync(imsxEnvelope).ConfigureAwait(false);

                    var xmlContent = new StringContent(xml, Encoding.UTF8, LtiConstants.ImsxOutcomeMediaType);
                    HttpRequestMessage webRequest = new HttpRequestMessage(HttpMethod.Post, serviceUrl)
                    {
                        Content = xmlContent
                    };
                    webRequest.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(LtiConstants.ImsxOutcomeMediaType));
                    await SecuredClient.SignRequest(client, webRequest, consumerKey, consumerSecret, signatureMethod)
                    .ConfigureAwait(false);

                    // Post the request and check the response
                    using (var response = await client.SendAsync(webRequest).ConfigureAwait(false))
                    {
                        outcomeResponse.StatusCode = response.StatusCode;
                        if (response.IsSuccessStatusCode)
                        {
                            var imsxResponseEnvelope = (imsx_POXEnvelopeType)ImsxResponseSerializer.Deserialize
                                                           (await response.Content.ReadAsStreamAsync().ConfigureAwait(false));
                            var imsxResponseHeader = (imsx_ResponseHeaderInfoType)imsxResponseEnvelope.imsx_POXHeader.Item;
                            var imsxResponseStatus = imsxResponseHeader.imsx_statusInfo.imsx_codeMajor;

                            outcomeResponse.StatusCode = imsxResponseStatus == imsx_CodeMajorType.success
                                ? HttpStatusCode.OK
                                : HttpStatusCode.BadRequest;
                            outcomeResponse.Severity  = imsxResponseHeader.imsx_statusInfo.imsx_severity;
                            outcomeResponse.MinorCode = imsxResponseHeader.imsx_statusInfo.imsx_codeMinor;
                        }
#if DEBUG
                        outcomeResponse.HttpRequest = await response.RequestMessage.ToFormattedRequestStringAsync
                                                          (new StringContent(xml, Encoding.UTF8, LtiConstants.ImsxOutcomeMediaType)).ConfigureAwait(false);
#endif
                        outcomeResponse.HttpResponse = await response.ToFormattedResponseStringAsync().ConfigureAwait(false);
                    }
                }
                catch (HttpRequestException ex)
                {
                    outcomeResponse.Exception  = ex;
                    outcomeResponse.StatusCode = HttpStatusCode.BadRequest;
                }
                catch (Exception ex)
                {
                    outcomeResponse.Exception  = ex;
                    outcomeResponse.StatusCode = HttpStatusCode.InternalServerError;
                }
                return(outcomeResponse);
            }
            catch (Exception ex)
            {
                return(new ClientResponse
                {
                    Exception = ex,
                    StatusCode = HttpStatusCode.InternalServerError
                });
            }
        }
Example #21
0
        /// <summary>
        /// Send an Outcomes 1.0 DeleteResult request.
        /// </summary>
        /// <param name="client">The HttpClient that will be used to process the request.</param>
        /// <param name="serviceUrl">The URL to send the request to.</param>
        /// <param name="consumerKey">The OAuth key to sign the request.</param>
        /// <param name="consumerSecret">The OAuth secret to sign the request.</param>
        /// <param name="sourcedId">The LisResultSourcedId to be deleted.</param>
        /// <returns>A <see cref="ClientResponse"/>.</returns>
        public static async Task <ClientResponse> DeleteResultAsync(HttpClient client, string serviceUrl, string consumerKey, string consumerSecret, string sourcedId)
        {
            try
            {
                var imsxEnvelope = new imsx_POXEnvelopeType
                {
                    imsx_POXHeader = new imsx_POXHeaderType {
                        Item = new imsx_RequestHeaderInfoType()
                    },
                    imsx_POXBody = new imsx_POXBodyType {
                        Item = new deleteResultRequest()
                    }
                };

                var imsxHeader = (imsx_RequestHeaderInfoType)imsxEnvelope.imsx_POXHeader.Item;
                imsxHeader.imsx_version           = imsx_GWSVersionValueType.V10;
                imsxHeader.imsx_messageIdentifier = Guid.NewGuid().ToString();

                var imsxBody = (deleteResultRequest)imsxEnvelope.imsx_POXBody.Item;
                imsxBody.resultRecord = new ResultRecordType
                {
                    sourcedGUID = new SourcedGUIDType {
                        sourcedId = sourcedId
                    }
                };

                var outcomeResponse = new ClientResponse();
                try
                {
                    client.DefaultRequestHeaders.Accept.Clear();
                    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(LtiConstants.ImsxOutcomeMediaType));

                    // Create a UTF8 encoding of the request
                    var xml = await GetXmlAsync(imsxEnvelope);

                    var xmlContent = new StringContent(xml, Encoding.UTF8, LtiConstants.ImsxOutcomeMediaType);
                    await SecuredClient.SignRequest(client, HttpMethod.Post, serviceUrl, xmlContent, consumerKey, consumerSecret);

                    // Post the request and check the response
                    using (var response = await client.PostAsync(serviceUrl, xmlContent))
                    {
                        outcomeResponse.StatusCode = response.StatusCode;
                        if (response.IsSuccessStatusCode)
                        {
                            var imsxResponseEnvelope = (imsx_POXEnvelopeType)ImsxResponseSerializer.Deserialize(await response.Content.ReadAsStreamAsync());
                            var imsxResponseHeader   = (imsx_ResponseHeaderInfoType)imsxResponseEnvelope.imsx_POXHeader.Item;
                            var imsxResponseStatus   = imsxResponseHeader.imsx_statusInfo.imsx_codeMajor;

                            outcomeResponse.StatusCode = imsxResponseStatus == imsx_CodeMajorType.success
                                ? HttpStatusCode.OK
                                : HttpStatusCode.BadRequest;
                        }
#if DEBUG
                        outcomeResponse.HttpRequest = await response.RequestMessage.ToFormattedRequestStringAsync(new StringContent(xml, Encoding.UTF8, LtiConstants.ImsxOutcomeMediaType));

                        outcomeResponse.HttpResponse = await response.ToFormattedResponseStringAsync();
#endif
                    }
                }
                catch (HttpRequestException ex)
                {
                    outcomeResponse.Exception  = ex;
                    outcomeResponse.StatusCode = HttpStatusCode.BadRequest;
                }
                catch (Exception ex)
                {
                    outcomeResponse.Exception  = ex;
                    outcomeResponse.StatusCode = HttpStatusCode.InternalServerError;
                }
                return(outcomeResponse);
            }
            catch (Exception ex)
            {
                return(new ClientResponse
                {
                    Exception = ex,
                    StatusCode = HttpStatusCode.InternalServerError
                });
            }
        }
        /// <summary>
        /// Create a simple, but complete response envelope. The status is set to success.
        /// </summary>
        /// <param name="messageRefId">The request message ID.</param>
        /// <param name="description">The status description.</param>
        /// <returns>A response envelope.</returns>
        private static imsx_POXEnvelopeType CreateSuccessResponse(string messageRefId, string description)
        {
            var response = new imsx_POXEnvelopeType
            {
                imsx_POXHeader = new imsx_POXHeaderType {Item = new imsx_ResponseHeaderInfoType()}
            };

            var item = (imsx_ResponseHeaderInfoType) response.imsx_POXHeader.Item;
            item.imsx_version = imsx_GWSVersionValueType.V10;
            item.imsx_messageIdentifier = Guid.NewGuid().ToString();
            item.imsx_statusInfo = new imsx_StatusInfoType();

            var status = item.imsx_statusInfo;
            status.imsx_codeMajor = imsx_CodeMajorType.success;
            status.imsx_severity = imsx_SeverityType.status;
            status.imsx_description = description;
            status.imsx_messageRefIdentifier = messageRefId;

            response.imsx_POXBody = new imsx_POXBodyType();
            return response;
        }