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()); } }
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)); }
/// <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())); } } }
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())); }
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()); }
/// <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())); } }
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); } }
/// <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); }
/// <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 }; } }
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()}; } }
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; }
/// <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 }); } }
/// <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 }); } }
/// <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; }