The IMS LTI™ outcomes service allows consumers (such as Learning Management Systems) and providers (such as an online test) to send score information back and forth. Teachers love this! No more manually entering grades into the gradebook.
In this post, I show how to use my .NET LtiLibrary to add consumer outcomes support. My previous post, Quickly add LTI consumer functionality to your ASP.NET MVC web site, describes how to add the LtiLibrary project to your solution.
Add WebApi support to your web site
Use the Package Manager to add WebApi support to your web site project,
Then add a WebApiConfig class to the App_Start folder. If you already have one, be sure to enable the XmlSerializer (LTI outcomes use XML formatting),
using System.Web.Http; namespace WebApplication1 { public static class WebApiConfig { public static void Register(HttpConfiguration config) { // Use XmlSerializer instead of DataContractSerializer config.Formatters.XmlFormatter.UseXmlSerializer = true; config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); } } }
And finally, be sure to call WebApiConfig.Register when the web site starts,
using System.Web.Http; using System.Web.Mvc; using System.Web.Optimization; using System.Web.Routing; namespace WebApplication1 { public class MvcApplication : System.Web.HttpApplication { protected void Application_Start() { // This needs to appear before the non-api routes WebApiConfig.Register(GlobalConfiguration.Configuration); AreaRegistration.RegisterAllAreas(); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); BundleConfig.RegisterBundles(BundleTable.Bundles); } } }
Implement an OutcomesController
LtiLibrary contains an abstract OutcomesControllerBase with 4 methods that you need to override:
- GetConsumerSecrets – Return the list of secrets for the given OAuth consumer key. These will be used to validate the outcomes service call from the provider.
- DeleteResult – Delete the specified score.
- ReadResult – Read the specified score.
- ReplaceResult – Save the specific score.
Here is a simple example that works with the IMS LTI™ test tool,
using System.Collections.Generic; namespace WebApplication1.Controllers { public class OutcomesController : LtiLibrary.Consumer.OutcomesControllerBase { private static double? Score; protected override bool DeleteResult(LtiLibrary.Consumer.Result result) { Score = null; return true; } protected override IList<string> GetConsumerSecrets(string consumerKey) { return consumerKey.Equals("12345") ? new List<string> { "secret" } : new List<string>(); } protected override bool ReadResult(LtiLibrary.Consumer.Result result) { result.DoubleValue = Score; return true; } protected override bool ReplaceResult(LtiLibrary.Consumer.Result result) { Score = result.DoubleValue; return true; } } }
Tell the provider that you support outcomes
The last step is to tell the provider that you support outcomes. You do this by adding two values to the LTI request: the endpoint URL of the outcomes service, and the result ID which you can think of as the grade cell ID in the grade book. For example,
public ActionResult Launch() { var request = new LtiLibrary.Consumer.LtiOutboundRequest { ConsumerKey = "12345", ConsumerSecret = "secret", ContextId = "1", ResourceLinkId = "1", Url = "http://www.imsglobal.org/developers/LTI/test/v1p1/tool.php" }; // Add outcomes support var urlHelper = new UrlHelper(this.HttpContext.Request.RequestContext); var relativeUrl = urlHelper.HttpRouteUrl("DefaultApi", new { controller = "outcomes" }); request.LisOutcomeServiceUrl = new Uri(this.HttpContext.Request.Url, relativeUrl).AbsoluteUri; request.LisResultSourcedId = "1"; return View(request.GetLtiRequestModel()); }
Launch
If you launch the IMS LTI™ test tool, you will see a new option to test outcomes,
What’s Next?
Check out the sample Consumer in LTI Samples to see a more robust use of LtiLibrary. If you are a publisher, the sample Provider shows how to use LtiLibrary to handle LTI launch requests and even send grades back to the consumer.
what if my website is webforms not MVC
Hello Sarah,
There is a WebForms sample in the SimpleLti project (see the WebForms folder). There are two versions of LtiSamples, the older, but more stable one is on CodePlex,
http://ltisamples.codeplex.com/SourceControl/latest
The new, but in the process of being refactored is on GitHub,
https://github.com/andyfmiller/LtiSamples
The SimpleLti project in both works, but the more complete Provider and Consumer samples only work in the CodePlex version. I should have them working on GitHub within a week or two.
I meant how can implement an outcome page with webforms not with MVC
You should be able to use the OutcomesClient (LtiLibrary.Core.Outcomes.v1) from a WebForm codebehind in the Tool Provider. If you are implementing the Tool Consumer side, then you can definitely add an ApiController such as OutcomesControllerBase (LtiLibrary.AspNet.Outcomes.v1) to a WebForms application (http://www.asp.net/web-api/overview/getting-started-with-aspnet-web-api/using-web-api-with-aspnet-web-forms) to listen for Outcomes. Your override of OutcomesControllerBase should store the outcomes in your database so that you can display them in your app.