Skip to end of metadata
Go to start of metadata

Understanding the requirements

Based on the requirements we are going to be adding extensions to the ODS and to the DDS to include Transportation information to the dashboards. One of the extensions includes a new tab and view that will give us transportation information on the student.

Step 1. Integrating the "Transportation" tab to the menu

The plugin architecture follows many conventions to provide an easy to build upon framework. One of the conventions we will leverage is the way to register a menu link in the student tab area. To do this we will create an implementation of the IPluginManifest in the root of the EdFi.Dashboards.Plugins.Transportation.Web project. The code should look like the following code block:

Plugin Manifest Implementation
using System.Collections.Generic;
using EdFi.Dashboards.Core.Providers.Context;
using EdFi.Dashboards.Resource.Models.Common;
using EdFi.Dashboards.Resources.Models.Plugins;
using EdFi.Dashboards.Resources.Navigation;
using EdFi.Dashboards.Resources.Plugins;
namespace EdFi.Dashboards.Plugins.Transportation.Web
{
    public class PluginManifest : IPluginManifest
    {
        private readonly IStudentSchoolAreaLinks areaLinks;
        public PluginManifest(IStudentSchoolAreaLinks areaLinks)
        {
            this.areaLinks = areaLinks;
        }
        public string Name { get { return GetType().Assembly.GetName().Name; } }
        public string Version { get { return GetType().Assembly.GetName().Version.ToString(); } }
        public IEnumerable<PluginMenu> PluginMenus {
            get
            {
                var requestContext = EdFiDashboardContext.Current;
                if (requestContext.SchoolId.HasValue && requestContext.StudentUSI.HasValue)
                    return new List<PluginMenu>
                        {
                            new PluginMenu
                            {
                                Area = "StudentSchool",
                                ResourceModels = new List<ResourceModel>
                                {
                                    new ResourceModel
                                    {
                                        Text = "Transportation",
                                        Url = areaLinks.Resource(requestContext.SchoolId.Value, requestContext.StudentUSI.Value, "Transportation")
                                    }
                                }
                            }
                        };
                return new List<PluginMenu>();
            }
        }
    }
}

Notice that we are using dependency injection to resolve the IStudentSchoolAreaLinks dependency. This dependency provides the ability to create valid Urls for the application. Look at line 33 that depicts the usage of this component.

Now we need to let the DI container know that we want to wire up a implementation of the IPluginManifest. Lets modify the previously added Installer to include the manifest registration. Code should look like this:

Dependency Installer with plugin manifest registration
using Castle.MicroKernel.Registration;
using Castle.MicroKernel.SubSystems.Configuration;
using Castle.Windsor;
using EdFi.Dashboards.Presentation.Core.Plugins.Utilities.CastleWindsor;
using EdFi.Dashboards.Resources.Plugins;
namespace EdFi.Dashboards.Plugins.Transportation.Web.Utilities.CastleWindsor
{
    public class Installer : WebDefaultConventionInstaller<Marker_EdFi_Dasboards_Plugins_Transportation_Web>
    {
        public override void Install(IWindsorContainer container, IConfigurationStore store)
        {
            base.Install(container, store);
            // Register plugin manifest for menu integration.
            container.Register(Component.For<IPluginManifest>().ImplementedBy<PluginManifest>());
        }
    }
}

 

At this point if we compile, bring up the application and navigate to a student we should see a Transportation tab that is clickable and that will take us to the desired view.

 

We now have a bare bones plugin that works and that we can build upon.

 

Step 2. Creating the extension database table and a EdFi.Dashboards.Plugins.Transportation.Data project.

Based on the requirements we are going to need a repository so that we can store the data for the student's (transportation method, AM bus number and PM bus number).

Step 2.1 Create the required database objects

Create a new schema that will group all of the "Transportation plugin" needs in one place. We will name the schema "transportation" and grant the edfiPService user read access to it.

Create a new table that will live in the newly created schema and name it: "transportation.StudentSchoolTransportationInformation"

Student School Transportation Information Script
/*Create the schema for the transportation plugin*/
CREATE SCHEMA [transportation] AUTHORIZATION [dbo]

/*Grant the needed access*/
GRANT SELECT ON SCHEMA::[transportation] TO [edfiPService]

/*Create the table*/
/****** Object:  Table [transportation].[StudentSchoolTransportationInformation]    Script Date: 9/28/2015 12:08:06 PM ******/
CREATE TABLE [transportation].[StudentSchoolTransportationInformation](
	[StudentUSI] [int] NOT NULL,
	[SchoolId] [int] NOT NULL,
	[TransportationMethod] [nvarchar](50) NOT NULL,
	[AMBusNumber] [nvarchar](50) NULL,
	[PMBusNumber] [nvarchar](50) NULL,
 CONSTRAINT [PK_StudentSchoolTransportationInformation] PRIMARY KEY CLUSTERED 
(
	[StudentUSI] ASC,
	[SchoolId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

Once we have the design for this table and all of the surrounding objects, make sure to place the script in the ~\Ed-Fi-Plugins\Plugins\Transportation\Database\Structure\Dashboard\ path. The script should follow the naming convention: [scriptNumber]-[Description of the content]. So for this example we will name it "0001-Create Dashboard Transportation Extension.sql" 

 

Step 2.2 Create the EdFi.Dashboards.Plugins.Transportation.Data project

In visual studio add a new project named EdFi.Dashboards.Plugins.Transportation.Data. For the project type select class library. For the location select the location where we are developing the plugin ~\Ed-Fi-Plugins\Plugins\Transportation\Application\.

Note: Make sure you select the right version of the .Net Framework or your plugin will not load.

Once the project has been created follow the steps below:

  1. Add the following references: System.Data.Linq, Subsonic, Castle Windsor, EdFi.Dashboards.Presentation.Core
  2. Copy the "Entities" folder including all of its content and the app.config from the "EdFi.Dashboards.Extensions.Data" project. 
  3. Modify the app.config connection string to point to your local EdFi_Dashboard database. 
  4. Modify the Settings.ttinclude: 

    1. The Namespace string needs to be updated to reflect the plugin we are working on ("EdFi.Dashboards.Plugins.Transportation.Data.Entities").
    2. The IncludedSchemas array needs to be modified to only have the schema we created ("transportation").

  5. Run the T4 transformation.

  6. Add a marker interface to the Data project.

    Marker interface for the Data project
    namespace EdFi.Dashboards.Plugins.Transportation.Data
    {
        public interface Marker_EdFi_Dashboards_Plugins_Transportation_Data
        {
        }
    }
  7. Create an Installer.cs class in the "Utilities\CastleWindsor" path and inherit from RepositoryDefaultConventionInstaller closing the generic with the marker we just created.

    Installer
    using EdFi.Dashboards.Presentation.Core.Plugins.Utilities.CastleWindsor;
    namespace EdFi.Dashboards.Plugins.Transportation.Data.Utilities.CastleWindsor
    {
        public class Installer : RepositoryDefaultConventionInstaller<Marker_EdFi_Dashboards_Plugins_Transportation_Data>
        {
        }
    }
  8. Make sure everything compiles.

Step 3. Creating the Tests, Resources and Models

Now that we have the basic plugin artifacts and the data project in place we will continue by developing the services that will return the resources needed for our plugin.

Step 3.1 Create the Models

Follow the next instructions for the completion of the Resources.Models project:

  1. Within visual studio create a new class library project named EdFi.Dashboards.Plugins.Transportation.Resources.Models. (Be ware you might run into a path to long exception. If this occurs use Trans for short instead of Transportation.)
  2. Following the conventions for file locations create a StudentSchool folder and a TransportationModel.cs class within it. The model should reflect the requirements regarding the data that will be needed.

    Transportation Model
    using System;
    namespace EdFi.Dashboards.Plugins.Trans.Resources.Models.StudentSchool
    {
        [Serializable]
        public class TransportationModel
        {
            public long StudentUSI { get; set; }
            public int SchoolId { get; set; }
            public string MethodOfTransportation { get; set; }
            public string AMBusNumber { get; set; }
            public string PMBusNumber { get; set; }
        }
    }

 

Step 3.2 Create the Resources/Services and accompanying Tests 

Follow the next instructions for the completion of the Resources and Tests project:

  1. Within visual studio create a new class library project named EdFi.Dashboards.Plugins.Transportation.Resources. (Be ware you might run into a path to long exception. If this occurs use Trans for short instead of Transportation.)
  2. Add the following references: 
    1. EdFi.Dashboards.Plugins.Trans.Models
    2. EdFi.Dashboards.Plugins.Transportation.Data
    3. EdFi.Dashboards.Common
    4. EdFi.Dashboards.Data
    5. EdFi.Dashboards.Resources.Security.Common
    6. EdFi.Dashboards.SecurityTokenService.Authentication
  3. Following the conventions for file locations create a StudentSchool folder and a TransportationService.cs class within it. The TransportationService.cs file will contain the TransportationRequest class and the TransportationService classes.

    Transportation Service file
    using System.Linq;
    using EdFi.Dashboards.Common;
    using EdFi.Dashboards.Data.Repository;
    using EdFi.Dashboards.Plugins.Trans.Resources.Models.StudentSchool;
    using EdFi.Dashboards.Plugins.Transportation.Data.Entities;
    using EdFi.Dashboards.Resources.Security.Common;
    using EdFi.Dashboards.SecurityTokenService.Authentication;
    namespace EdFi.Dashboards.Plugins.Transportation.Resources.StudentSchool
    {
        public class TransportationRequest
        {
            public long StudentUSI { get; set; }
            public int SchoolId { get; set; }
        }
    public interface ITransportationService : IService<TransportationRequest, TransportationModel> { }
    
        public class TransportationService : ITransportationService
        {
            private readonly IRepository<StudentSchoolTransportationInformation> transportationInformationRepository;
            public TransportationService(IRepository<StudentSchoolTransportationInformation> transportationInformationRepository)
            {
                this.transportationInformationRepository = transportationInformationRepository;
            }
     
    		[CanBeAuthorizedBy(EdFiClaimTypes.ViewAllStudents, EdFiClaimTypes.ViewMyStudents)]
            public TransportationModel Get(TransportationRequest request)
            {
            	return new TransportationModel();
            }
        }
    }

    Note: Make sure to attribute the Get method with the appropriate security. "[CanBeAuthorizedBy(EdFiClaimTypes.ViewAllStudents, EdFiClaimTypes.ViewMyStudents)]"

  4. Within visual studio create a new class library project named EdFi.Dashboards.Plugins.Trans.Resources.Tests. (Be aware you might run into a path to long exception. If this occurs use Trans for short instead of Transportation.)
  5. Add the following references: 
    1. EdFi.Dashboards.Testing
    2. EdFi.Dashboards.Plugins.Transportation.Data
    3. EdFi.Dashboards.Plugins.Transportation.Resources
    4. EdFi.Dashboards.Common
    5. EdFi.Dashboards.Data
    6. Rhino.Mocks
    7. EdFi.Dashboards.Plugins.Trans.Resources.Models
    8. NUnit
    9. EdFi.Dashboards.Presentation.Core
    10. Castle Windsor
    11. EdFi.Dashboards.Resources.Security.Common
  6. Following the conventions for file locations create a StudentSchool folder and a TransportationServiceFixture.cs class within it. The TransportationServiceFixture.cs file will contain the tests for the TransportationService class.

    Unit test for Transportation Service
    using System.Collections.Generic;
    using System.Linq;
    using EdFi.Dashboards.Data.Repository;
    using EdFi.Dashboards.Plugins.Trans.Resources.Models.StudentSchool;
    using EdFi.Dashboards.Plugins.Transportation.Data.Entities;
    using EdFi.Dashboards.Plugins.Transportation.Resources.StudentSchool;
    using EdFi.Dashboards.Testing;
    using NUnit.Framework;
    using Rhino.Mocks;
    namespace EdFi.Dashboards.Plugins.Trans.Resources.Tests
    {
        public class TransportationServiceFixture
        {
            [TestFixture]
            public class When_requesting_student_trasnportation_information : TestFixtureBase
            {
                private const int suppliedStudentUSI =1;
                private const int suppliedSchoolId =10;
                private IQueryable<StudentSchoolTransportationInformation> suppliedStudentSchoolTransportationInformationData;
                // The service under test
                private TransportationService service;
                private TransportationModel actualModel;
    
                protected override void EstablishContext()
                {
                    suppliedStudentSchoolTransportationInformationData = GetSuppliedStudentSchoolTransportationInformationData();
                    // Set up the mocks
                    var suppliedStudentSchoolTransportationRepository = mocks.StrictMock<IRepository<StudentSchoolTransportationInformation>>();
                    Expect.Call(suppliedStudentSchoolTransportationRepository.GetAll()).Return(suppliedStudentSchoolTransportationInformationData);
                    service = new TransportationService(suppliedStudentSchoolTransportationRepository);
                }
                protected IQueryable<StudentSchoolTransportationInformation> GetSuppliedStudentSchoolTransportationInformationData()
                {
                    return new List<StudentSchoolTransportationInformation>
                    {
                        new StudentSchoolTransportationInformation{ StudentUSI = suppliedStudentUSI, SchoolId = suppliedSchoolId, TransportationMethod = "Bus", AMBusNumber = "123", PMBusNumber = "456"},
                        new StudentSchoolTransportationInformation{ StudentUSI = 99, SchoolId = suppliedSchoolId, TransportationMethod = "Should be filtered out becuse different StudentUSI", AMBusNumber = "123", PMBusNumber = "456"},
                        new StudentSchoolTransportationInformation{ StudentUSI = suppliedStudentUSI, SchoolId = 99, TransportationMethod = "Should be filtered out becuse different SchooId", AMBusNumber = "123", PMBusNumber = "456"},
                    }.AsQueryable();
                }
                protected override void ExecuteTest()
                {
                    actualModel = service.Get(new TransportationRequest{SchoolId = suppliedSchoolId, StudentUSI = suppliedStudentUSI});
                }
                [Test]
                public void Should_assign_all_properties_on_student_transportation_model()
                {
                    var suppliedDataToBind = suppliedStudentSchoolTransportationInformationData.Single(x=>x.SchoolId==suppliedSchoolId && x.StudentUSI==suppliedStudentUSI);
                    Assert.That(actualModel.SchoolId, Is.EqualTo(suppliedDataToBind.SchoolId));
                    Assert.That(actualModel.StudentUSI, Is.EqualTo(suppliedDataToBind.StudentUSI));
                    Assert.That(actualModel.MethodOfTransportation, Is.EqualTo(suppliedDataToBind.TransportationMethod));
                    Assert.That(actualModel.AMBusNumber, Is.EqualTo(suppliedDataToBind.AMBusNumber));
                    Assert.That(actualModel.PMBusNumber, Is.EqualTo(suppliedDataToBind.PMBusNumber));
                }
            }
        }
    }
  7. Run the test. (The expectation is that it fails.)
  8. Now that we have our test setup with the expected requirement lets continue to implement the service. The final implementation of the service should look as follows:

    Implemented Transportation Request
    using System.Linq;
    using EdFi.Dashboards.Common;
    using EdFi.Dashboards.Data.Repository;
    using EdFi.Dashboards.Plugins.Trans.Resources.Models.StudentSchool;
    using EdFi.Dashboards.Plugins.Transportation.Data.Entities;
    using EdFi.Dashboards.Resources.Security.Common;
    using EdFi.Dashboards.SecurityTokenService.Authentication;
    namespace EdFi.Dashboards.Plugins.Transportation.Resources.StudentSchool
    {
        public class TransportationRequest
        {
            public long StudentUSI { get; set; }
            public int SchoolId { get; set; }
        }
    public interface ITransportationService : IService<TransportationRequest, TransportationModel> { }
    
        public class TransportationService : ITransportationService
        {
            private readonly IRepository<StudentSchoolTransportationInformation> transportationInformationRepository;
            public TransportationService(IRepository<StudentSchoolTransportationInformation> transportationInformationRepository)
            {
                this.transportationInformationRepository = transportationInformationRepository;
            }
    		[CanBeAuthorizedBy(EdFiClaimTypes.ViewAllStudents, EdFiClaimTypes.ViewMyStudents)]
            public TransportationModel Get(TransportationRequest request)
            {
                var data = (from t in transportationInformationRepository.GetAll()
                            where t.SchoolId == request.SchoolId && t.StudentUSI==request.StudentUSI
                            select t).SingleOrDefault();
                if(data==null)
                    return new TransportationModel();
                var response = new TransportationModel
                {
                    StudentUSI = data.StudentUSI,
                    SchoolId = data.SchoolId,
                    MethodOfTransportation = data.TransportationMethod,
                    AMBusNumber = data.AMBusNumber,
                    PMBusNumber = data.PMBusNumber,
                };
                return response;
            }
        }
    }

    Note: Make sure to attribute the Get method with the appropriate security authorization claims. In This case users who have the "View All Students" and the "View My Students" claims should be allowed.

  9. Once the service has been fully implemented the test should pass.
  10. Create the marker interface for the Resources project.

    Marker Class for the Resources project
    namespace EdFi.Dashboards.Plugins.Transportation.Resources
    {
        public interface Marker_EdFi_Dashboards_Plugins_Transportation_Resources { }
    }
  11. Create the IoC instaler so that it picks up our interfaces and services.

    IoC Installer
    using EdFi.Dashboards.Presentation.Core.Plugins.Utilities.CastleWindsor;
    namespace EdFi.Dashboards.Plugins.Transportation.Resources.Utilities.CastleWindsor
    {
        public class Installer : ResourceDefaultConventionInstaller<Marker_EdFi_Dashboards_Plugins_Transportation_Resources>
        {
        }
    }
  12. Done

Step 4. Sewing it all together

Now that we have plugin integration, data structures, services and models we need to make them all interact. For this we are going to add a constructor to the controller and take a dependency on the service.

  1. Add the following references to the EdFi.Dashboards.Plugins.Transportation.Web project:

    1. EdFi.Dashboards.Plugins.Transportation.Resources
    2. EdFi.Dashboards.Plugins.Transportation.Resources.Models
    3. EdFi.Dashboards.Common
  2. Open the controller and modify it so it looks like this:

    Controller Updated
    using System.Web.Mvc;
    using EdFi.Dashboards.Plugins.Transportation.Resources.StudentSchool;
    namespace EdFi.Dashboards.Plugins.Transportation.Web.Areas.StudentSchool.Controllers
    {
        public class TransportationController : Controller
        {
            private readonly ITransportationService service;
            public TransportationController(ITransportationService service)
            {
                this.service = service;
            }
            public ActionResult Get(TransportationRequest request)
            {
                var model = service.Get(request);
                return View(model);
            }
        }
    }
  3. Update the view so that we have the model and a way of displaying it.

    Updated View
    @model EdFi.Dashboards.Plugins.Trans.Resources.Models.StudentSchool.TransportationModel
    @section ContentPlaceHolder1{
        <style>
            .round-container {
                background-color: #d2e2ef;
                border-radius: 5px;
                padding: 10px;
                margin-right: 20px;
                margin-bottom: 20px;
                display: -moz-inline-block;
                display: inline-block;
                zoom: 1;
                vertical-align: top;
                width: 740px;
            }
        </style>
        <div class="l-information-wrapper">
            <h2 class="title">Transportation Information</h2>
            <div class="round-container">
                <ul>
                    <li>
                        <span class="label">Method of Transportation:</span>
                        <span>@(Model.MethodOfTransportation)</span>
                    </li>
                    <li>
                        <span class="label">AM Bus Number:</span>
                        <span>@(Model.AMBusNumber)</span>
                    </li>
                    <li>
                        <span class="label">PM Bus Number:</span>
                        <span>@(Model.PMBusNumber)</span>
                    </li>
                </ul>
            </div>
        </div>
    }
  4. Add some fake data

    Fake data
    INSERT INTO [EdFi_Dashboard].[transportation].[StudentSchoolTransportationInformation] (StudentUSI, SchoolId ,TransportationMethod, AMBusNumber, PMBusNumber) VALUES (605319, 255901001, 'Bus','A1024','B7245');
    UPDATE [EdFi_Dashboard].[domain].[StudentInformation] set AddressLine1='106 sunfish St', City='Lakeway', State='TX' where [StudentUSI]=605319;
    UPDATE [EdFi_Dashboard].[domain].[SchoolInformation] set AddressLine1='3301 Serene Hills Dr', City='Lakeway', State='TX' where SchoolId=255901001;
    INSERT INTO [EdFi_Dashboard].[transportation].[StudentSchoolTransportationInformation] (StudentUSI, SchoolId ,TransportationMethod) VALUES (605486, 255901001, 'Car');
    UPDATE [EdFi_Dashboard].[domain].[StudentInformation] set AddressLine1='106 applegreen ln', City='Lakeway', State='TX' where [StudentUSI]=605486;
    
  5. Run the code and navigate to a student and click on the Transportation tab. If you are running on your local machine you should be able to click the following link to get to the student faster: https://localhost/EdFiDashboardDev/Districts/GrandBendISD/Schools/Grand-Bend-High-School/Students/Tara-D--Abbott-605319/Transportation

 

Reach Goal "Adding a map that shows student address and the route to school"

Based on the original requirements we want to include a map that shows the route of the student from his house to the school. To do this we are going to update the model, unit test, service and view. The student address is on the domain.StudentInformation table and the school address in in the domain.SchoolInformation one.

Lets start by following these steps:

  1. Update the model to contain the StudentAddress and the SchoolAddress as strings. Then continue to make appropriate changes to the unit test expectations.

    Model updates
    using System;
    namespace EdFi.Dashboards.Plugins.Trans.Resources.Models.StudentSchool
    {
        [Serializable]
        public class TransportationModel
        {
            public long StudentUSI { get; set; }
            public int SchoolId { get; set; }
            public string MethodOfTransportation { get; set; }
            public string AMBusNumber { get; set; }
            public string PMBusNumber { get; set; }
            public string StudentAddress { get; set; }
            public string SchoolAddress { get; set; }
        }
    }
  2. Update the service so it has the repository dependencies that are needed.

    Service with Dependencies
    using System.Linq;
    using System.Xml;
    using EdFi.Dashboards.Common;
    using EdFi.Dashboards.Data.Entities;
    using EdFi.Dashboards.Data.Repository;
    using EdFi.Dashboards.Plugins.Trans.Resources.Models.StudentSchool;
    using EdFi.Dashboards.Plugins.Transportation.Data.Entities;
    using EdFi.Dashboards.Resources.Security.Common;
    using EdFi.Dashboards.SecurityTokenService.Authentication;
    namespace EdFi.Dashboards.Plugins.Transportation.Resources.StudentSchool
    {
        public class TransportationRequest
        {
            public long StudentUSI { get; set; }
            public int SchoolId { get; set; }
        }
        public interface ITransportationService : IService<TransportationRequest, TransportationModel> { }
        public class TransportationService : ITransportationService
        {
            private readonly IRepository<StudentSchoolTransportationInformation> transportationInformationRepository;
            private readonly IRepository<StudentInformation> studentInformationRepository;
            private readonly IRepository<SchoolInformation> schoolInformationRepository;
            public TransportationService(IRepository<StudentSchoolTransportationInformation> transportationInformationRepository, IRepository<StudentInformation> studentInformationRepository, IRepository<SchoolInformation> schoolInformationRepository)
            {
                this.transportationInformationRepository = transportationInformationRepository;
                this.studentInformationRepository = studentInformationRepository;
                this.schoolInformationRepository = schoolInformationRepository;
            }
            [CanBeAuthorizedBy(EdFiClaimTypes.ViewAllStudents, EdFiClaimTypes.ViewMyStudents)]
            public TransportationModel Get(TransportationRequest request)
            {
                var data = (from t in transportationInformationRepository.GetAll()
                            where t.SchoolId == request.SchoolId && t.StudentUSI==request.StudentUSI
                            select t).SingleOrDefault();
                if(data==null)
                    return new TransportationModel();
                var response = new TransportationModel
                {
                    StudentUSI = data.StudentUSI,
                    SchoolId = data.SchoolId,
                    MethodOfTransportation = data.TransportationMethod,
                    AMBusNumber = data.AMBusNumber,
                    PMBusNumber = data.PMBusNumber,
                };
                return response;
            }
        }
    }
  3. Update the unit test to comply with the new logic and run the unit test

    Updated Test
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using EdFi.Dashboards.Data.Entities;
    using EdFi.Dashboards.Data.Repository;
    using EdFi.Dashboards.Plugins.Trans.Resources.Models.StudentSchool;
    using EdFi.Dashboards.Plugins.Transportation.Data.Entities;
    using EdFi.Dashboards.Plugins.Transportation.Resources.StudentSchool;
    using EdFi.Dashboards.Testing;
    using NUnit.Framework;
    using Rhino.Mocks;
    namespace EdFi.Dashboards.Plugins.Trans.Resources.Tests
    {
        public class TransportationServiceFixture
        {
            [TestFixture]
            public class When_requesting_student_trasnportation_information : TestFixtureBase
            {
                private const int suppliedStudentUSI =1;
                private const int suppliedSchoolId =10;
                private IQueryable<StudentSchoolTransportationInformation> suppliedStudentSchoolTransportationInformationData;
                private IQueryable<StudentInformation> suppliedStudentInformationData;
                private IQueryable<SchoolInformation> suppliedSchoolInformationData;
                // The service under test
                private TransportationService service;
                private TransportationModel actualModel;
    
                protected override void EstablishContext()
                {
                    suppliedStudentSchoolTransportationInformationData = GetSuppliedStudentSchoolTransportationInformationData();
                    suppliedStudentInformationData = GetSuppliedStudentInformationData();
                    suppliedSchoolInformationData = GetSuppliedSchoolInformationData();
                    // Set up the mocks
                    var suppliedStudentSchoolTransportationRepository = mocks.StrictMock<IRepository<StudentSchoolTransportationInformation>>();
                    var suppliedStudentInformationRepository = mocks.StrictMock<IRepository<StudentInformation>>();
                    var suppliedSchoolInformationRepository = mocks.StrictMock<IRepository<SchoolInformation>>();
                    Expect.Call(suppliedStudentSchoolTransportationRepository.GetAll()).Return(suppliedStudentSchoolTransportationInformationData);
                    Expect.Call(suppliedStudentInformationRepository.GetAll()).Return(suppliedStudentInformationData);
                    Expect.Call(suppliedSchoolInformationRepository.GetAll()).Return(suppliedSchoolInformationData);
                    service = new TransportationService(suppliedStudentSchoolTransportationRepository, suppliedStudentInformationRepository, suppliedSchoolInformationRepository);
                }
                protected IQueryable<StudentSchoolTransportationInformation> GetSuppliedStudentSchoolTransportationInformationData()
                {
                    return new List<StudentSchoolTransportationInformation>
                    {
                        new StudentSchoolTransportationInformation{ StudentUSI = suppliedStudentUSI, SchoolId = suppliedSchoolId, TransportationMethod = "Bus", AMBusNumber = "123", PMBusNumber = "456"},
                        new StudentSchoolTransportationInformation{ StudentUSI = 99, SchoolId = suppliedSchoolId, TransportationMethod = "Should be filtered out becuse different StudentUSI", AMBusNumber = "123", PMBusNumber = "456"},
                        new StudentSchoolTransportationInformation{ StudentUSI = suppliedStudentUSI, SchoolId = 99, TransportationMethod = "Should be filtered out becuse different SchooId", AMBusNumber = "123", PMBusNumber = "456"},
                    }.AsQueryable();
                }
                protected IQueryable<StudentInformation> GetSuppliedStudentInformationData()
                {
                    return new List<StudentInformation>
                    {
                        new StudentInformation{ StudentUSI = suppliedStudentUSI, AddressLine1 = "123 My Street", City = "City", State = "State", ZipCode = "12345"},
                        new StudentInformation{ StudentUSI = 99, AddressLine1 = "Should be filtered out becuse different StudentUSI"},
                    }.AsQueryable();
                }
                protected IQueryable<SchoolInformation> GetSuppliedSchoolInformationData()
                {
                    return new List<SchoolInformation>
                    {
                        new SchoolInformation{ SchoolId = suppliedSchoolId, AddressLine1 = "456 My Street", City = "City", State = "State", ZipCode = "12345"},
                        new SchoolInformation{ SchoolId = 99, AddressLine1 = "Should be filtered out becuse different SchoolId"},
                    }.AsQueryable();
                }
                protected override void ExecuteTest()
                {
                    actualModel = service.Get(new TransportationRequest{SchoolId = suppliedSchoolId, StudentUSI = suppliedStudentUSI});
                }
                [Test]
                public void Should_assign_all_properties_on_student_transportation_model_correctly()
                {
                    var suppliedDataToBind = suppliedStudentSchoolTransportationInformationData.Single(x=>x.SchoolId==suppliedSchoolId && x.StudentUSI==suppliedStudentUSI);
                    Assert.That(actualModel.SchoolId, Is.EqualTo(suppliedDataToBind.SchoolId));
                    Assert.That(actualModel.StudentUSI, Is.EqualTo(suppliedDataToBind.StudentUSI));
                    Assert.That(actualModel.MethodOfTransportation, Is.EqualTo(suppliedDataToBind.TransportationMethod));
                    Assert.That(actualModel.AMBusNumber, Is.EqualTo(suppliedDataToBind.AMBusNumber));
                    Assert.That(actualModel.PMBusNumber, Is.EqualTo(suppliedDataToBind.PMBusNumber));
                }
                [Test]
                public void Should_assign_student_address_on_student_transportation_model()
                {
                    var suppliedDataToBind = suppliedStudentInformationData.Single(x => x.StudentUSI == suppliedStudentUSI);
                    var suppliedAddress = String.Format("{0}, {1}, {2}", suppliedDataToBind.AddressLine1, suppliedDataToBind.City, suppliedDataToBind.State);
                    Assert.That(actualModel.StudentAddress, Is.EqualTo(suppliedAddress));
                }
                [Test]
                public void Should_assign_school_address_on_student_transportation_model()
                {
                    var suppliedDataToBind = suppliedSchoolInformationData.Single(x => x.SchoolId == suppliedSchoolId);
                    var suppliedAddress = String.Format("{0}, {1}, {2}", suppliedDataToBind.AddressLine1, suppliedDataToBind.City, suppliedDataToBind.State);
                    Assert.That(actualModel.SchoolAddress, Is.EqualTo(suppliedAddress));
                }
            }
        }
    }

     

  4. Continue to fully implement the service updates to get the data from the repositories and bind to the model.

    Service fully implemented
    using System;
    using System.Linq;
    using System.Xml;
    using Castle.MicroKernel.ModelBuilder.Descriptors;
    using Castle.Windsor.Installer;
    using EdFi.Dashboards.Common;
    using EdFi.Dashboards.Data.Entities;
    using EdFi.Dashboards.Data.Repository;
    using EdFi.Dashboards.Plugins.Trans.Resources.Models.StudentSchool;
    using EdFi.Dashboards.Plugins.Transportation.Data.Entities;
    using EdFi.Dashboards.Resources.Security.Common;
    using EdFi.Dashboards.SecurityTokenService.Authentication;
    namespace EdFi.Dashboards.Plugins.Transportation.Resources.StudentSchool
    {
        public class TransportationRequest
        {
            public long StudentUSI { get; set; }
            public int SchoolId { get; set; }
        }
        public interface ITransportationService : IService<TransportationRequest, TransportationModel> { }
        public class TransportationService : ITransportationService
        {
            private readonly IRepository<StudentSchoolTransportationInformation> transportationInformationRepository;
            private readonly IRepository<StudentInformation> studentInformationRepository;
            private readonly IRepository<SchoolInformation> schoolInformationRepository;
            public TransportationService(IRepository<StudentSchoolTransportationInformation> transportationInformationRepository, IRepository<StudentInformation> studentInformationRepository, IRepository<SchoolInformation> schoolInformationRepository)
            {
                this.transportationInformationRepository = transportationInformationRepository;
                this.studentInformationRepository = studentInformationRepository;
                this.schoolInformationRepository = schoolInformationRepository;
            }
            [CanBeAuthorizedBy(EdFiClaimTypes.ViewAllStudents, EdFiClaimTypes.ViewMyStudents)]
            public TransportationModel Get(TransportationRequest request)
            {
                var transportationData = (from t in transportationInformationRepository.GetAll()
                    where t.SchoolId == request.SchoolId && t.StudentUSI == request.StudentUSI
                    select t).SingleOrDefault();
                var studentData = (from s in studentInformationRepository.GetAll()
                    where s.StudentUSI == request.StudentUSI
                    select s).SingleOrDefault();
                var schoolData = (from s in schoolInformationRepository.GetAll()
                                   where s.SchoolId == request.SchoolId
                                   select s).SingleOrDefault();
                if(transportationData==null)
                    return new TransportationModel();
                var response = new TransportationModel
                {
                    StudentUSI = transportationData.StudentUSI,
                    SchoolId = transportationData.SchoolId,
                    MethodOfTransportation = transportationData.TransportationMethod,
                    AMBusNumber = transportationData.AMBusNumber,
                    PMBusNumber = transportationData.PMBusNumber,
                };
                if (studentData != null)
                    response.StudentAddress = String.Format("{0}, {1}, {2}", studentData.AddressLine1, studentData.City, studentData.State);
                if (schoolData != null)
                    response.SchoolAddress = String.Format("{0}, {1}, {2}", schoolData.AddressLine1, schoolData.City, schoolData.State);
                return response;
            }
        }
    }
  5. Run the unit tests again

  6. Update the view to include the necessary java scripts and html.

    Updated View
    @model EdFi.Dashboards.Plugins.Trans.Resources.Models.StudentSchool.TransportationModel
    @section ContentPlaceHolderHead{
        <script src="https://maps.googleapis.com/maps/api/js?sensor=false"></script>
        <script>
            $(function() {
                var directionsDisplay = new google.maps.DirectionsRenderer();
                var directionsService = new google.maps.DirectionsService();
                var center = new google.maps.LatLng(0, 0);
                var myOptions =
                {
                    zoom: 7,
                    mapTypeId: google.maps.MapTypeId.ROADMAP,
                    center: center
                }
                var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
                directionsDisplay.setMap(map);
                var start = "@Model.StudentAddress";
                var end = "@Model.SchoolAddress";
                var request = {
                    origin: start,
                    destination: end,
                    travelMode: google.maps.DirectionsTravelMode.DRIVING
                };
                directionsService.route(request, function(response, status) {
                    if (status == google.maps.DirectionsStatus.OK) {
                        directionsDisplay.setDirections(response);
                    }
                });
            });
        </script>
    }
    @section ContentPlaceHolder1{
        <style>
            .round-container {
                background-color: #d2e2ef;
                border-radius: 5px;
                padding: 10px;
                margin-right: 20px;
                margin-bottom: 20px;
                display: -moz-inline-block;
                display: inline-block;
                zoom: 1;
                vertical-align: top;
                width: 740px;
            }
        </style>
        <div class="l-information-wrapper">
            <h2 class="title">Transportation Information</h2>
            <div class="round-container">
                <ul>
                    <li>
                        <span class="label">Method of Transportation:</span>
                        <span>@(Model.MethodOfTransportation)</span>
                    </li>
                    <li>
                        <span class="label">AM Bus Number:</span>
                        <span>@(Model.AMBusNumber)</span>
                    </li>
                    <li>
                        <span class="label">PM Bus Number:</span>
                        <span>@(Model.PMBusNumber)</span>
                    </li>
                </ul>
            </div>
            <div id="map_canvas" style="height: 400px; width: 740px"></div>
        </div>
    }
  7. Build the code and run the application.

 

 

 

 

 

 

Your Rating:
Results:
1 Star2 Star3 Star4 Star5 Star
1 rates