A line item is equivalent to a column in a gradebook; it is able to hold the results associated with a specific activity for a set of users. The activity is expected to be associated with a single LTI context within the tool consumer, so there is a one-to-many relationship between contexts and line items.
Inheritance: LtiLibrary.Core.Common.JsonLdObject
 public void PostLineItemReturnsValidLineItem()
 {
     var controller = new LineItemsController();
     ControllerSetup.RegisterContext(controller, "LineItems");
     var lineitem = new LineItem
     {
         LineItemOf = new Context {  ContextId = LineItemsController.ContextId },
         ReportingMethod = "res:Result"
     };
     var result = controller.Post(lineitem);
     Assert.Equal(HttpStatusCode.Created, result.Result.StatusCode);
     var lineItem = JsonConvert.DeserializeObject<LineItem>(result.Result.Content.ReadAsStringAsync().Result);
     Assert.NotNull(lineItem);
     Assert.Equal(LineItemsController.LineItemId, lineItem.Id.ToString());
 }
        public LineItemsController()
        {
            OnDeleteLineItem = context =>
            {
                if (string.IsNullOrEmpty(context.Id) || _lineItem == null || !_lineItem.Id.Equals(context.Id))
                {
                    context.StatusCode = HttpStatusCode.NotFound;
                }
                else
                {
                    _lineItem = null;
                    context.StatusCode = HttpStatusCode.OK;
                }
                return Task.FromResult<object>(null);
            };

            OnGetLineItem = context =>
            {
                if (string.IsNullOrEmpty(context.Id) || _lineItem == null || !_lineItem.Id.Equals(context.Id))
                {
                    context.StatusCode = HttpStatusCode.NotFound;
                }
                else
                {
                    context.LineItem = _lineItem;
                    context.StatusCode = HttpStatusCode.OK;
                }
                return Task.FromResult<object>(null);
            };

            OnGetLineItems = context =>
            {
                if (_lineItem == null ||
                    (!string.IsNullOrEmpty(context.ActivityId) &&
                     !context.ActivityId.Equals(_lineItem.AssignedActivity.ActivityId)))
                {
                    context.StatusCode = HttpStatusCode.NotFound;
                }
                else
                {
                    context.LineItemContainerPage = new LineItemContainerPage
                    {
                        ExternalContextId = LtiConstants.LineItemContainerContextId,
                        Id = Request.RequestUri,
                        LineItemContainer = new LineItemContainer
                        {
                            MembershipSubject = new LineItemMembershipSubject
                            {
                                ContextId = _lineItem.LineItemOf.ContextId,
                                LineItems = new[] { _lineItem }
                            }
                        }
                    };
                    context.StatusCode = HttpStatusCode.OK;
                }
                return Task.FromResult<object>(null);
            };

            OnPostLineItem = context =>
            {
                if (_lineItem != null)
                {
                    context.StatusCode = HttpStatusCode.BadRequest;
                    return Task.FromResult<object>(null);
                }

                context.LineItem.Id = new Uri(LineItemId, UriKind.Relative);
                context.LineItem.Results = new Uri(Request.RequestUri.AbsoluteUri + "/" + LineItemId + "/results");
                _lineItem = context.LineItem;
                context.StatusCode = HttpStatusCode.Created;
                return Task.FromResult<object>(null);
            };

            OnPutLineItem = context =>
            {
                if (context.LineItem == null || _lineItem == null || !_lineItem.Id.Equals(context.LineItem.Id))
                {
                    context.StatusCode = HttpStatusCode.NotFound;
                }
                else
                {
                    _lineItem = context.LineItem;
                    context.StatusCode = HttpStatusCode.OK;
                }
                return Task.FromResult<object>(null);
            };
        }
        public async Task<HttpResponseMessage> Put(LineItem lineItem)
        {
            try
            {
                var context = new PutLineItemContext(lineItem);

                var mediaType =
                    Request.Headers.Accept.Contains(
                        new MediaTypeWithQualityHeaderValue(LtiConstants.LineItemResultsMediaType))
                        ? LtiConstants.LineItemResultsMediaType
                        : LtiConstants.LineItemMediaType;

                if (mediaType.Equals(LtiConstants.LineItemResultsMediaType))
                {
                    await OnPutLineItemWithResults(context);
                }
                else
                {
                    await OnPutLineItem(context);
                }

                await OnPutLineItem(context);

                return Request.CreateResponse(context.StatusCode);
            }
            catch (Exception ex)
            {
                return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, ex);
            }
        }
        public async Task<HttpResponseMessage> Post(string contextId, LineItem lineItem)
        {
            try
            {
                var context = new PostLineItemContext(contextId, lineItem);

                await OnPostLineItem(context);

                return context.StatusCode == HttpStatusCode.Created
                    ? Request.CreateResponse(context.StatusCode, context.LineItem, new LineItemFormatter(), LtiConstants.LineItemMediaType) 
                    : Request.CreateResponse(context.StatusCode);
            }
            catch (Exception ex)
            {
                return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, ex);
            }
        }
        public async Task<HttpResponseMessage> Put(LineItem lineItem)
        {
            try
            {
                var context = new PutLineItemContext(lineItem);

                await OnPutLineItem(context);

                return Request.CreateResponse(context.StatusCode);
            }
            catch (Exception ex)
            {
                return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, ex);
            }
        }
 public PutLineItemContext(LineItem lineItem)
 {
     LineItem = lineItem;
     StatusCode = HttpStatusCode.OK;
 }
Esempio n. 7
0
 /// <summary>
 /// Create a new LineItem instance within the server.
 /// </summary>
 /// <param name="lineItem">The LineItem to create within the server.</param>
 /// <param name="serviceUrl">The LineItem container REST endpoint.</param>
 /// <param name="consumerKey">The OAuth consumer key to use to form the Authorization header.</param>
 /// <param name="consumerSecret">The OAuth consumer secret to use to form the Authorization header.</param>
 /// <returns>If successful, the LineItem with @id and results filled in.</returns>
 /// <remarks>
 /// https://www.imsglobal.org/specs/ltiomv2p0/specification-3
 /// When a line item is created, a result for each user is deemed to be created with a status value of “Initialized”.
 /// Thus, there is no need to actually create a result with a POST request; the first connection to a result may be a
 /// PUT or a GET request.When a line item is created, a result for each user is deemed to be created with a status value
 /// of “Initialized”.  Thus, there is no need to actually create a result with a POST request; the first connection to a
 /// result may be a PUT or a GET request.
 /// </remarks>
 public static async Task <OutcomeResponse <LineItem> > PostLineItem(LineItem lineItem, string serviceUrl, string consumerKey,
                                                                     string consumerSecret)
 {
     return(await PostOutcome(lineItem, serviceUrl, consumerKey, consumerSecret, LtiConstants.LineItemMediaType));
 }
Esempio n. 8
0
 /// <summary>
 /// Update a particular LineItem instance within the server.
 /// </summary>
 /// <param name="lineItem">The LineItem to be updated within the server.</param>
 /// <param name="serviceUrl">The LineItem REST endpoint.</param>
 /// <param name="consumerKey">The OAuth consumer key to use to form the Authorization header.</param>
 /// <param name="consumerSecret">The OAuth consumer secret to use to form the Authorization header.</param>
 /// <returns>No content is returned.</returns>
 public static async Task <OutcomeResponse> PutLineItemWithResults(LineItem lineItem, string serviceUrl, string consumerKey, string consumerSecret)
 {
     return(await PutOutcome(lineItem, serviceUrl, consumerKey, consumerSecret, LtiConstants.LineItemResultsMediaType));
 }
Esempio n. 9
0
        public LineItemsController()
        {
            OnDeleteLineItem = context =>
            {
                if (string.IsNullOrEmpty(context.Id) || _lineItem == null || !_lineItem.Id.Equals(context.Id))
                {
                    context.StatusCode = HttpStatusCode.NotFound;
                }
                else
                {
                    _lineItem = null;
                    context.StatusCode = HttpStatusCode.OK;
                }
                return Task.FromResult<object>(null);
            };

            OnGetLineItem = context =>
            {
                if (string.IsNullOrEmpty(context.Id) || _lineItem == null || !_lineItem.Id.Equals(context.Id))
                {
                    context.StatusCode = HttpStatusCode.NotFound;
                }
                else
                {
                    context.LineItem = _lineItem;
                    context.StatusCode = HttpStatusCode.OK;
                }
                return Task.FromResult<object>(null);
            };

            OnGetLineItems = context =>
            {
                if (_lineItem == null ||
                    (!string.IsNullOrEmpty(context.ActivityId) &&
                     !context.ActivityId.Equals(_lineItem.AssignedActivity.ActivityId)))
                {
                    context.StatusCode = HttpStatusCode.NotFound;
                }
                else
                {
                    var id = new UriBuilder(Request.RequestUri) {Query = "firstPage"};
                    context.LineItemContainerPage = new LineItemContainerPage
                    {
                        Id = id.Uri,
                        LineItemContainer = new LineItemContainer
                        {
                            MembershipSubject = new Context
                            {
                                ContextId = _lineItem.LineItemOf.ContextId,
                                LineItems = new[] { _lineItem }
                            }
                        }
                    };
                    context.StatusCode = HttpStatusCode.OK;
                }
                return Task.FromResult<object>(null);
            };

            OnPostLineItem = context =>
            {
                if (_lineItem != null)
                {
                    context.StatusCode = HttpStatusCode.BadRequest;
                    return Task.FromResult<object>(null);
                }

                context.LineItem.Id = new Uri(LineItemId, UriKind.Relative);
                context.LineItem.Results = new Uri(Request.RequestUri, "results");
                _lineItem = context.LineItem;
                context.StatusCode = HttpStatusCode.Created;
                return Task.FromResult<object>(null);
            };

            OnPutLineItem = context =>
            {
                if (context.LineItem == null || _lineItem == null || !_lineItem.Id.Equals(context.LineItem.Id))
                {
                    context.StatusCode = HttpStatusCode.NotFound;
                }
                else
                {
                    _lineItem = context.LineItem;
                    context.StatusCode = HttpStatusCode.OK;
                }
                return Task.FromResult<object>(null);
            };
        }
 public PostLineItemContext(string contextId, LineItem lineItem)
 {
     ContextId = contextId;
     LineItem = lineItem;
     StatusCode = HttpStatusCode.OK;
 }
Esempio n. 11
0
 public async Task<ActionResult> Outcomes(LineItemModel model, string submit)
 {
     switch (submit)
     {
         case "Delete LineItem":
             var deleteLineItemResponse = await OutcomesClient.DeleteLineItem(
                 model.LineItemServiceUrl,
                 model.ConsumerKey,
                 model.ConsumerSecret);
             model.HttpRequest = deleteLineItemResponse.HttpRequest;
             model.HttpResponse = deleteLineItemResponse.HttpResponse;
             switch (deleteLineItemResponse.StatusCode)
             {
                 case HttpStatusCode.OK:
                     model.LineItem = null;
                     ModelState.Clear();
                     ViewBag.Message = "200 LineItem deleted";
                     break;
                 case HttpStatusCode.Unauthorized:
                     ViewBag.Message = "401 Not authorized";
                     break;
                 case HttpStatusCode.NotFound:
                     ViewBag.Message = "404 Not found";
                     break;
                 case HttpStatusCode.InternalServerError:
                     ViewBag.Message = "500 Internal server error";
                     break;
                 default:
                     ViewBag.Message = Convert.ToInt32(deleteLineItemResponse.StatusCode) + " " + deleteLineItemResponse.StatusCode;
                     break;
             }
             break;
         case "Get LineItem":
             var getLineItemResponse = await OutcomesClient.GetLineItem(
                 model.LineItemServiceUrl,
                 model.ConsumerKey,
                 model.ConsumerSecret);
             model.HttpRequest = getLineItemResponse.HttpRequest;
             model.HttpResponse = getLineItemResponse.HttpResponse;
             switch (getLineItemResponse.StatusCode)
             {
                 case HttpStatusCode.OK:
                     model.LineItem = getLineItemResponse.Outcome;
                     ModelState.Clear();
                     ViewBag.Message = "200 LineItem received";
                     break;
                 case HttpStatusCode.Unauthorized:
                     ViewBag.Message = "401 Not authorized";
                     break;
                 case HttpStatusCode.NotFound:
                     ViewBag.Message = "404 Not found";
                     break;
                 case HttpStatusCode.InternalServerError:
                     ViewBag.Message = "500 Internal server error";
                     break;
                 default:
                     ViewBag.Message = Convert.ToInt32(getLineItemResponse.StatusCode) + " " + getLineItemResponse.StatusCode;
                     break;
             }
             break;
         case "Get LineItems":
             var getLineItemsResponse = await OutcomesClient.GetLineItemPage(
                 model.LineItemsServiceUrl,
                 model.ConsumerKey,
                 model.ConsumerSecret);
             model.HttpRequest = getLineItemsResponse.HttpRequest;
             model.HttpResponse = getLineItemsResponse.HttpResponse;
             switch (getLineItemsResponse.StatusCode)
             {
                 case HttpStatusCode.OK:
                     ViewBag.Message = "200 LineItems received";
                     break;
                 case HttpStatusCode.Unauthorized:
                     ViewBag.Message = "401 Not authorized";
                     break;
                 case HttpStatusCode.NotFound:
                     ViewBag.Message = "404 Not found";
                     break;
                 case HttpStatusCode.InternalServerError:
                     ViewBag.Message = "500 Internal server error";
                     break;
                 default:
                     ViewBag.Message = Convert.ToInt32(getLineItemsResponse.StatusCode) + " " + getLineItemsResponse.StatusCode;
                     break;
             }
             break;
         case "Post LineItem":
             var postLineItem = new LineItem
             {
                 ReportingMethod = "res:totalScore",
                 LineItemOf = new Context { ContextId = model.ContextId},
                 AssignedActivity = new Activity { ActivityId = model.LineItem.AssignedActivity.ActivityId},
                 ScoreContraints = new NumericLimits {  NormalMaximum = 100, ExtraCreditMaximum = 10, TotalMaximum = 110}
             };
             var postLineItemResponse = await OutcomesClient.PostLineItem(
                 postLineItem,
                 model.LineItemsServiceUrl,
                 model.ConsumerKey,
                 model.ConsumerSecret);
             model.HttpRequest = postLineItemResponse.HttpRequest;
             model.HttpResponse = postLineItemResponse.HttpResponse;
             switch (postLineItemResponse.StatusCode)
             {
                 case HttpStatusCode.Created:
                     model.LineItem = postLineItemResponse.Outcome;
                     ModelState.Clear();
                     ViewBag.Message = "201 LineItem added";
                     break;
                 case HttpStatusCode.BadRequest:
                     ViewBag.Message = "400 Bad Request";
                     break;
                 case HttpStatusCode.Unauthorized:
                     ViewBag.Message = "401 Not authorized";
                     break;
                 case HttpStatusCode.InternalServerError:
                     ViewBag.Message = "500 Internal server error";
                     break;
                 default:
                     ViewBag.Message = Convert.ToInt32(postLineItemResponse.StatusCode) + " " + postLineItemResponse.StatusCode;
                     break;
             }
             break;
         case "Put LineItem":
             var putLineItem = new LineItem
             {
                 Id = model.LineItem.Id,
                 ReportingMethod = "res:totalScore",
                 LineItemOf = new Context { ContextId = model.ContextId },
                 AssignedActivity = new Activity { ActivityId = model.LineItem.AssignedActivity.ActivityId },
                 ScoreContraints = new NumericLimits { NormalMaximum = 100, ExtraCreditMaximum = 10, TotalMaximum = 110 },
                 Results = model.LineItem.Results
             };
             var putLineItemResponse = await OutcomesClient.PutLineItem(
                 putLineItem,
                 model.LineItemsServiceUrl,
                 model.ConsumerKey,
                 model.ConsumerSecret);
             model.HttpRequest = putLineItemResponse.HttpRequest;
             model.HttpResponse = putLineItemResponse.HttpResponse;
             switch (putLineItemResponse.StatusCode)
             {
                 case HttpStatusCode.OK:
                     ViewBag.Message = "200 LineItem updated";
                     break;
                 case HttpStatusCode.Unauthorized:
                     ViewBag.Message = "401 Not authorized";
                     break;
                 case HttpStatusCode.NotFound:
                     ViewBag.Message = "404 Not found";
                     break;
                 case HttpStatusCode.InternalServerError:
                     ViewBag.Message = "500 Internal server error";
                     break;
                 default:
                     ViewBag.Message = Convert.ToInt32(putLineItemResponse.StatusCode) + " " + putLineItemResponse.StatusCode;
                     break;
             }
             break;
     }
     return View(model);
 }