Skip to content

Commit 3b92698

Browse files
committed
Clean solution commit
1 parent 7c10068 commit 3b92698

22 files changed

+849
-177
lines changed

TollBooth.sln

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ Microsoft Visual Studio Solution File, Format Version 12.00
33
# Visual Studio 15
44
VisualStudioVersion = 15.0.27130.2003
55
MinimumVisualStudioVersion = 10.0.40219.1
6-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TollBooth", "TollBooth\TollBooth.csproj", "{58B34BE7-1F92-45A6-AA28-56E4684640E4}"
6+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TollBooth", "TollBooth\TollBooth.csproj", "{58B34BE7-1F92-45A6-AA28-56E4684640E4}"
77
EndProject
8-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TollBoth_Tests", "TollBoth_Tests\TollBoth_Tests.csproj", "{73589AA0-D7C0-461B-9896-E5F89A359D71}"
8+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UploadImages", "UploadImages\UploadImages.csproj", "{A7110625-77CF-45DD-920F-F35E8A4740BB}"
99
EndProject
1010
Global
1111
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -17,10 +17,10 @@ Global
1717
{58B34BE7-1F92-45A6-AA28-56E4684640E4}.Debug|Any CPU.Build.0 = Debug|Any CPU
1818
{58B34BE7-1F92-45A6-AA28-56E4684640E4}.Release|Any CPU.ActiveCfg = Release|Any CPU
1919
{58B34BE7-1F92-45A6-AA28-56E4684640E4}.Release|Any CPU.Build.0 = Release|Any CPU
20-
{73589AA0-D7C0-461B-9896-E5F89A359D71}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21-
{73589AA0-D7C0-461B-9896-E5F89A359D71}.Debug|Any CPU.Build.0 = Debug|Any CPU
22-
{73589AA0-D7C0-461B-9896-E5F89A359D71}.Release|Any CPU.ActiveCfg = Release|Any CPU
23-
{73589AA0-D7C0-461B-9896-E5F89A359D71}.Release|Any CPU.Build.0 = Release|Any CPU
20+
{A7110625-77CF-45DD-920F-F35E8A4740BB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21+
{A7110625-77CF-45DD-920F-F35E8A4740BB}.Debug|Any CPU.Build.0 = Debug|Any CPU
22+
{A7110625-77CF-45DD-920F-F35E8A4740BB}.Release|Any CPU.ActiveCfg = Release|Any CPU
23+
{A7110625-77CF-45DD-920F-F35E8A4740BB}.Release|Any CPU.Build.0 = Release|Any CPU
2424
EndGlobalSection
2525
GlobalSection(SolutionProperties) = preSolution
2626
HideSolutionNode = FALSE

TollBooth/DatabaseMethods.cs

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Configuration;
4+
using System.Linq;
5+
using System.Text;
6+
using System.Threading.Tasks;
7+
using Microsoft.Azure.Documents.Client;
8+
using Microsoft.Azure.WebJobs.Host;
9+
using TollBooth.Models;
10+
11+
namespace TollBooth
12+
{
13+
internal class DatabaseMethods
14+
{
15+
private readonly string _endpointUrl = ConfigurationManager.AppSettings["cosmosDBEndPointUrl"];
16+
private readonly string _authorizationKey = ConfigurationManager.AppSettings["cosmosDBAuthorizationKey"];
17+
private readonly string _databaseId = ConfigurationManager.AppSettings["cosmosDBDatabaseId"];
18+
private readonly string _collectionId = ConfigurationManager.AppSettings["cosmosDBCollectionId"];
19+
private readonly TraceWriter _log;
20+
// Reusable instance of DocumentClient which represents the connection to a Cosmos DB endpoint.
21+
private DocumentClient _client;
22+
23+
public DatabaseMethods(TraceWriter log)
24+
{
25+
_log = log;
26+
}
27+
28+
/// <summary>
29+
/// Retrieves all license plate records (documents) that have not yet been exported.
30+
/// </summary>
31+
/// <returns></returns>
32+
public List<LicensePlateDataDocument> GetLicensePlatesToExport()
33+
{
34+
_log.Info("Retrieving license plates to export");
35+
int exportedCount = 0;
36+
var collectionLink = UriFactory.CreateDocumentCollectionUri(_databaseId, _collectionId);
37+
List<LicensePlateDataDocument> licensePlates;
38+
39+
using (_client = new DocumentClient(new Uri(_endpointUrl), _authorizationKey))
40+
{
41+
// MaxItemCount value tells the document query to retrieve 100 documents at a time until all are returned.
42+
// TODO 5: Retrieve a List of LicensePlateDataDocument objects from the collectionLink where the exported value is false.
43+
// COMPLETE: licensePlates = _client.CreateDocumentQuery ...
44+
// TODO 6: Remove the line below.
45+
licensePlates = new List<LicensePlateDataDocument>();
46+
}
47+
48+
exportedCount = licensePlates.Count();
49+
_log.Info($"{exportedCount} license plates found that are ready for export");
50+
return licensePlates;
51+
}
52+
53+
/// <summary>
54+
/// Updates license plate records (documents) as exported. Call after successfully
55+
/// exporting the passed in license plates.
56+
/// In a production environment, it would be best to create a stored procedure that
57+
/// bulk updates the set of documents, vastly reducing the number of transactions.
58+
/// </summary>
59+
/// <param name="licensePlates"></param>
60+
/// <returns></returns>
61+
public async Task MarkLicensePlatesAsExported(IEnumerable<LicensePlateDataDocument> licensePlates)
62+
{
63+
_log.Info("Updating license plate documents exported values to true");
64+
var collectionLink = UriFactory.CreateDocumentCollectionUri(_databaseId, _collectionId);
65+
66+
using (_client = new DocumentClient(new Uri(_endpointUrl), _authorizationKey))
67+
{
68+
foreach (var licensePlate in licensePlates)
69+
{
70+
licensePlate.exported = true;
71+
var response = await _client.ReplaceDocumentAsync(UriFactory.CreateDocumentUri(_databaseId, _collectionId, licensePlate.Id), licensePlate);
72+
73+
var updated = response.Resource;
74+
//_log.Info($"Exported value of updated document: {updated.GetPropertyValue<bool>("exported")}");
75+
}
76+
}
77+
}
78+
79+
}
80+
}

TollBooth/ExportLicensePlates.cs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
using System.Linq;
2+
using System.Net;
3+
using System.Net.Http;
4+
using System.Threading.Tasks;
5+
using Microsoft.Azure.WebJobs;
6+
using Microsoft.Azure.WebJobs.Extensions.Http;
7+
using Microsoft.Azure.WebJobs.Host;
8+
9+
namespace TollBooth
10+
{
11+
public static class ExportLicensePlates
12+
{
13+
[FunctionName("ExportLicensePlates")]
14+
public static async Task<HttpResponseMessage> Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]HttpRequestMessage req, TraceWriter log)
15+
{
16+
int exportedCount = 0;
17+
log.Info("Finding license plate data to export");
18+
19+
var databaseMethods = new DatabaseMethods(log);
20+
var licensePlates = databaseMethods.GetLicensePlatesToExport();
21+
if (licensePlates.Any())
22+
{
23+
log.Info($"Retrieved {licensePlates.Count} license plates");
24+
var fileMethods = new FileMethods(log);
25+
var uploaded = await fileMethods.GenerateAndSaveCsv(licensePlates);
26+
if (uploaded)
27+
{
28+
await databaseMethods.MarkLicensePlatesAsExported(licensePlates);
29+
exportedCount = licensePlates.Count;
30+
log.Info("Finished updating the license plates");
31+
}
32+
else
33+
{
34+
log.Info(
35+
"Export file could not be uploaded. Skipping database update that marks the documents as exported.");
36+
}
37+
38+
log.Info($"Exported {exportedCount} license plates");
39+
}
40+
else
41+
{
42+
log.Info("No license plates to export");
43+
}
44+
45+
return exportedCount == 0
46+
? req.CreateResponse(HttpStatusCode.NoContent)
47+
: req.CreateResponse(HttpStatusCode.OK, $"Exported {exportedCount} license plates");
48+
}
49+
}
50+
}

TollBooth/FileMethods.cs

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Configuration;
4+
using System.IO;
5+
using System.Linq;
6+
using System.Text;
7+
using System.Threading.Tasks;
8+
using CsvHelper;
9+
using Microsoft.Azure.WebJobs.Host;
10+
using Microsoft.WindowsAzure.Storage;
11+
using Microsoft.WindowsAzure.Storage.Blob;
12+
using TollBooth.Models;
13+
14+
namespace TollBooth
15+
{
16+
internal class FileMethods
17+
{
18+
private readonly CloudBlobClient _blobClient;
19+
private readonly string _containerName = ConfigurationManager.AppSettings["exportCsvContainerName"];
20+
private readonly string _blobStorageConnection = ConfigurationManager.AppSettings["blobStorageConnection"];
21+
private readonly TraceWriter _log;
22+
23+
public FileMethods(TraceWriter log)
24+
{
25+
_log = log;
26+
// Retrieve storage account information from connection string.
27+
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(_blobStorageConnection);
28+
29+
// Create a blob client for interacting with the blob service.
30+
_blobClient = storageAccount.CreateCloudBlobClient();
31+
}
32+
33+
public async Task<bool> GenerateAndSaveCsv(IEnumerable<LicensePlateDataDocument> licensePlates)
34+
{
35+
var successful = false;
36+
37+
_log.Info("Generating CSV file");
38+
string blobName = $"{DateTime.UtcNow.ToString("s")}.csv";
39+
40+
using (var stream = new MemoryStream())
41+
{
42+
using (var textWriter = new StreamWriter(stream))
43+
using (var csv = new CsvWriter(textWriter))
44+
{
45+
csv.Configuration.Delimiter = ",";
46+
csv.WriteRecords(licensePlates.Select(ToLicensePlateData));
47+
await textWriter.FlushAsync();
48+
49+
_log.Info($"Beginning file upload: {blobName}");
50+
try
51+
{
52+
var container = _blobClient.GetContainerReference(_containerName);
53+
54+
// Retrieve reference to a blob.
55+
var blob = container.GetBlockBlobReference(blobName);
56+
await container.CreateIfNotExistsAsync();
57+
58+
// Upload blob.
59+
stream.Position = 0;
60+
// TODO 7: Asyncronously upload the blob from the memory stream.
61+
// COMPLETE: await blob...;
62+
63+
successful = true;
64+
}
65+
catch (Exception e)
66+
{
67+
_log.Error($"Could not upload CSV file: {e.Message}", e);
68+
successful = false;
69+
}
70+
}
71+
}
72+
73+
return successful;
74+
}
75+
76+
/// <summary>
77+
/// Used for mapping from a LicensePlateDataDocument object to a LicensePlateData object.
78+
/// </summary>
79+
/// <param name="source"></param>
80+
/// <returns></returns>
81+
private static LicensePlateData ToLicensePlateData(LicensePlateDataDocument source)
82+
{
83+
return new LicensePlateData
84+
{
85+
FileName = source.fileName,
86+
LicensePlateText = source.licensePlateText,
87+
TimeStamp = source.Timestamp
88+
};
89+
}
90+
}
91+
}

0 commit comments

Comments
 (0)