Skip to content
This repository was archived by the owner on Mar 27, 2026. It is now read-only.

Commit 9686f68

Browse files
committed
Merge pull request #36 from jpsingleton/refactor
DI Refactor
2 parents bf79931 + cc64c7e commit 9686f68

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+488
-167
lines changed
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
using Huxley.ldbServiceReference;
2+
3+
[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(Huxley.App_Start.NinjectWebCommon), "Start")]
4+
[assembly: WebActivatorEx.ApplicationShutdownMethodAttribute(typeof(Huxley.App_Start.NinjectWebCommon), "Stop")]
5+
6+
namespace Huxley.App_Start {
7+
using System;
8+
using System.Web;
9+
using Microsoft.Web.Infrastructure.DynamicModuleHelper;
10+
using Ninject;
11+
using Ninject.Web.Common;
12+
13+
public static class NinjectWebCommon {
14+
private static readonly Bootstrapper Bootstrapper = new Bootstrapper();
15+
16+
/// <summary>
17+
/// Starts the application
18+
/// </summary>
19+
public static void Start() {
20+
DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
21+
DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
22+
Bootstrapper.Initialize(CreateKernel);
23+
}
24+
25+
/// <summary>
26+
/// Stops the application.
27+
/// </summary>
28+
public static void Stop() {
29+
Bootstrapper.ShutDown();
30+
}
31+
32+
/// <summary>
33+
/// Creates the kernel that will manage your application.
34+
/// </summary>
35+
/// <returns>The created kernel.</returns>
36+
private static IKernel CreateKernel() {
37+
var kernel = new StandardKernel();
38+
try {
39+
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
40+
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
41+
kernel.Bind<ILdbClient>().To<LdbClient>().InRequestScope();
42+
kernel.Bind<LDBServiceSoapClient>().To<LDBServiceSoapClient>().InRequestScope();
43+
return kernel;
44+
} catch {
45+
kernel.Dispose();
46+
throw;
47+
}
48+
}
49+
}
50+
}

src/Huxley/Controllers/CrsController.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ public IEnumerable<CrsRecord> Get() {
3232

3333
// GET /crs/{query}
3434
public IEnumerable<CrsRecord> Get(string query) {
35+
if (query.Equals("London Terminals", StringComparison.InvariantCultureIgnoreCase)) {
36+
return HuxleyApi.LondonTerminals;
37+
}
3538
// Could use a RegEx here but putting user input into a RegEx can be dangerous
3639
var results = HuxleyApi.CrsCodes.Where(c => c.StationName.IndexOf(query, StringComparison.InvariantCultureIgnoreCase) >= 0);
3740
return results;

src/Huxley/Controllers/DelaysController.cs

Lines changed: 70 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,18 @@ You should have received a copy of the GNU Affero General Public License
2222
using System.Collections.Generic;
2323
using System.Globalization;
2424
using System.Linq;
25-
using System.ServiceModel;
2625
using System.Threading.Tasks;
2726
using System.Web.Http;
2827
using Huxley.Models;
2928
using Huxley.ldbServiceReference;
3029

3130
namespace Huxley.Controllers {
32-
public class DelaysController : BaseController {
31+
public class DelaysController : LdbController {
32+
33+
public DelaysController(ILdbClient client)
34+
: base(client) {
35+
}
36+
3337
// GET /delays/{crs}/{filtertype}/{filtercrs}/{numrows}/{stds}?accessToken=[your token]
3438
public async Task<DelaysResponse> Get([FromUri] StationBoardRequest request) {
3539

@@ -61,121 +65,81 @@ public async Task<DelaysResponse> Get([FromUri] StationBoardRequest request) {
6165
}
6266
}
6367

64-
// https://en.wikipedia.org/wiki/London_station_group
65-
// Farringdon [ZFD] is not a London Terminal but it probably should be (maybe when Crossrail opens it will be)
66-
var londonTerminals = new List<string> {
67-
"BFR", // Blackfriars
68-
"CST", // Cannon Street
69-
"CHX", // Charing Cross
70-
"CTX", // City Thameslink
71-
"EUS", // Euston
72-
"FST", // Fenchurch Street
73-
"KGX", // King's Cross
74-
"LST", // Liverpool Street
75-
"LBG", // London Bridge
76-
"MYB", // Marylebone
77-
"MOG", // Moorgate
78-
"OLD", // Old Street
79-
"PAD", // Paddington
80-
"STP", // St. Pancras
81-
"VXH", // Vauxhall
82-
"VIC", // Victoria
83-
"WAT", // Waterloo
84-
"WAE", // Waterloo East
85-
};
86-
87-
var client = new LDBServiceSoapClient();
68+
var totalDelayMinutes = 0;
69+
var delayedTrains = new List<ServiceItem>();
8870

89-
// Avoiding Problems with the Using Statement in WCF clients
90-
// https://msdn.microsoft.com/en-us/library/aa355056.aspx
91-
try {
92-
var totalDelayMinutes = 0;
93-
var delayedTrains = new List<ServiceItem>();
71+
var token = MakeAccessToken(request.AccessToken);
9472

95-
var token = MakeAccessToken(request.AccessToken);
73+
var filterCrs = request.FilterCrs;
74+
if (request.FilterCrs.Equals("LON", StringComparison.InvariantCultureIgnoreCase) ||
75+
request.FilterCrs.Equals("London", StringComparison.InvariantCultureIgnoreCase)) {
76+
filterCrs = null;
77+
}
9678

97-
var filterCrs = request.FilterCrs;
98-
if (request.FilterCrs.Equals("LON", StringComparison.InvariantCultureIgnoreCase) ||
99-
request.FilterCrs.Equals("London", StringComparison.InvariantCultureIgnoreCase)) {
100-
filterCrs = null;
101-
}
102-
103-
var board = await client.GetDepartureBoardAsync(token, request.NumRows, request.Crs, filterCrs, request.FilterType, 0, 0);
104-
105-
var response = board.GetStationBoardResult;
106-
var filterLocationName = response.filterLocationName;
107-
108-
var trainServices = response.trainServices ?? new ServiceItem[0];
109-
var railReplacement = null != response.busServices && !trainServices.Any() && response.busServices.Any();
110-
var messagesPresent = null != response.nrccMessages && response.nrccMessages.Any();
111-
112-
if (null == filterCrs) {
113-
// This only finds trains terminating at London terminals. BFR/STP etc. won't be picked up if called at en-route.
114-
// Could query for every terminal or get service for every train and check calling points. Very chatty either way.
115-
switch (request.FilterType) {
116-
case FilterType.to:
117-
trainServices = trainServices.Where(ts => ts.destination.Any(d => londonTerminals.Contains(d.crs.ToUpperInvariant()))).ToArray();
118-
break;
119-
case FilterType.from:
120-
trainServices = trainServices.Where(ts => ts.origin.Any(d => londonTerminals.Contains(d.crs.ToUpperInvariant()))).ToArray();
121-
break;
122-
default:
123-
throw new ArgumentOutOfRangeException();
124-
}
125-
filterCrs = "LON";
126-
filterLocationName = "London";
79+
var board = await Client.GetDepartureBoardAsync(token, request.NumRows, request.Crs, filterCrs, request.FilterType, 0, 0);
80+
81+
var response = board.GetStationBoardResult;
82+
var filterLocationName = response.filterLocationName;
83+
84+
var trainServices = response.trainServices ?? new ServiceItem[0];
85+
var railReplacement = null != response.busServices && !trainServices.Any() && response.busServices.Any();
86+
var messagesPresent = null != response.nrccMessages && response.nrccMessages.Any();
87+
88+
if (null == filterCrs) {
89+
// This only finds trains terminating at London terminals. BFR/STP etc. won't be picked up if called at en-route.
90+
// Could query for every terminal or get service for every train and check calling points. Very chatty either way.
91+
switch (request.FilterType) {
92+
case FilterType.to:
93+
trainServices = trainServices.Where(ts => ts.destination.Any(d => HuxleyApi.LondonTerminals.Any(lt => lt.CrsCode == d.crs.ToUpperInvariant()))).ToArray();
94+
break;
95+
case FilterType.from:
96+
trainServices = trainServices.Where(ts => ts.origin.Any(o => HuxleyApi.LondonTerminals.Any(lt => lt.CrsCode == o.crs.ToUpperInvariant()))).ToArray();
97+
break;
98+
default:
99+
throw new ArgumentOutOfRangeException();
127100
}
101+
filterCrs = "LON";
102+
filterLocationName = "London";
103+
}
128104

129-
// If STDs are provided then select only the train(s) matching them
130-
if (stds.Count > 0) {
131-
trainServices = trainServices.Where(ts => stds.Contains(ts.std.Replace(":", ""))).ToArray();
132-
}
105+
// If STDs are provided then select only the train(s) matching them
106+
if (stds.Count > 0) {
107+
trainServices = trainServices.Where(ts => stds.Contains(ts.std.Replace(":", ""))).ToArray();
108+
}
133109

134-
// Parse the response from the web service.
135-
foreach (var si in trainServices.Where(si => !si.etd.Equals("On time", StringComparison.InvariantCultureIgnoreCase))) {
136-
if (si.etd.Equals("Delayed", StringComparison.InvariantCultureIgnoreCase) ||
137-
si.etd.Equals("Cancelled", StringComparison.InvariantCultureIgnoreCase)) {
138-
delayedTrains.Add(si);
139-
} else {
140-
DateTime etd;
141-
// Could be "Starts Here", "No Report" or contain a * (report overdue)
142-
if (DateTime.TryParse(si.etd.Replace("*", ""), out etd)) {
143-
DateTime std;
144-
if (DateTime.TryParse(si.std, out std)) {
145-
var late = etd.Subtract(std);
146-
totalDelayMinutes += (int)late.TotalMinutes;
147-
if (late.TotalMinutes > HuxleyApi.Settings.DelayMinutesThreshold) {
148-
delayedTrains.Add(si);
149-
}
110+
// Parse the response from the web service.
111+
foreach (var si in trainServices.Where(si => !si.etd.Equals("On time", StringComparison.InvariantCultureIgnoreCase))) {
112+
if (si.etd.Equals("Delayed", StringComparison.InvariantCultureIgnoreCase) ||
113+
si.etd.Equals("Cancelled", StringComparison.InvariantCultureIgnoreCase)) {
114+
delayedTrains.Add(si);
115+
} else {
116+
DateTime etd;
117+
// Could be "Starts Here", "No Report" or contain a * (report overdue)
118+
if (DateTime.TryParse(si.etd.Replace("*", ""), out etd)) {
119+
DateTime std;
120+
if (DateTime.TryParse(si.std, out std)) {
121+
var late = etd.Subtract(std);
122+
totalDelayMinutes += (int)late.TotalMinutes;
123+
if (late.TotalMinutes > HuxleyApi.Settings.DelayMinutesThreshold) {
124+
delayedTrains.Add(si);
150125
}
151126
}
152127
}
153128
}
154-
155-
return new DelaysResponse {
156-
GeneratedAt = response.generatedAt,
157-
Crs = response.crs,
158-
LocationName = response.locationName,
159-
Filtercrs = filterCrs,
160-
FilterLocationName = filterLocationName,
161-
Delays = delayedTrains.Count > 0 || railReplacement || messagesPresent,
162-
TotalTrainsDelayed = delayedTrains.Count,
163-
TotalDelayMinutes = totalDelayMinutes,
164-
TotalTrains = trainServices.Length,
165-
DelayedTrains = delayedTrains,
166-
};
167-
168-
} catch (CommunicationException) {
169-
client.Abort();
170-
} catch (TimeoutException) {
171-
client.Abort();
172-
} catch (Exception) {
173-
client.Abort();
174-
throw;
175-
} finally {
176-
client.Close();
177129
}
178-
return new DelaysResponse();
130+
131+
return new DelaysResponse {
132+
GeneratedAt = response.generatedAt,
133+
Crs = response.crs,
134+
LocationName = response.locationName,
135+
Filtercrs = filterCrs,
136+
FilterLocationName = filterLocationName,
137+
Delays = delayedTrains.Count > 0 || railReplacement || messagesPresent,
138+
TotalTrainsDelayed = delayedTrains.Count,
139+
TotalDelayMinutes = totalDelayMinutes,
140+
TotalTrains = trainServices.Length,
141+
DelayedTrains = delayedTrains,
142+
};
179143
}
180144
}
181145
}
Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,14 @@ You should have received a copy of the GNU Affero General Public License
2424
using Huxley.ldbServiceReference;
2525

2626
namespace Huxley.Controllers {
27-
public class BaseController : ApiController {
27+
public class LdbController : ApiController {
28+
29+
protected readonly ILdbClient Client;
30+
31+
public LdbController(ILdbClient client) {
32+
Client = client;
33+
}
34+
2835
protected static AccessToken MakeAccessToken(Guid accessToken) {
2936
// If ClientAccessToken is an empty GUID then no token is required in the Huxley URL.
3037
// If ClientAccessToken matches the token in the URL then the DarwinAccessToken will be used instead in the SOAP call.

src/Huxley/Controllers/ServiceController.cs

Lines changed: 9 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -19,42 +19,27 @@ You should have received a copy of the GNU Affero General Public License
1919
*/
2020

2121
using System;
22-
using System.ServiceModel;
2322
using System.Threading.Tasks;
2423
using System.Web.Http;
2524
using Huxley.Models;
2625
using Huxley.ldbServiceReference;
2726

2827
namespace Huxley.Controllers {
29-
public class ServiceController : BaseController {
28+
public class ServiceController : LdbController {
29+
30+
public ServiceController(ILdbClient client)
31+
: base(client) {
32+
}
33+
3034
// GET /service/ID?accessToken=[your token]
3135
public async Task<ServiceDetails> Get([FromUri] ServiceRequest request) {
32-
3336
Guid sid;
3437
if (Guid.TryParse(request.ServiceId, out sid)) {
3538
request.ServiceId = Convert.ToBase64String(sid.ToByteArray());
3639
}
37-
38-
var client = new LDBServiceSoapClient();
39-
40-
// Avoiding Problems with the Using Statement in WCF clients
41-
// https://msdn.microsoft.com/en-us/library/aa355056.aspx
42-
try {
43-
var token = MakeAccessToken(request.AccessToken);
44-
45-
var service = await client.GetServiceDetailsAsync(token, request.ServiceId);
46-
return service.GetServiceDetailsResult;
47-
} catch (CommunicationException) {
48-
client.Abort();
49-
} catch (TimeoutException) {
50-
client.Abort();
51-
} catch (Exception) {
52-
client.Abort();
53-
throw;
54-
} finally {
55-
client.Close();
56-
}
57-
return new ServiceDetails();
40+
var token = MakeAccessToken(request.AccessToken);
41+
var service = await Client.GetServiceDetailsAsync(token, request.ServiceId);
42+
return service.GetServiceDetailsResult;
5843
}
5944
}
6045
}

0 commit comments

Comments
 (0)