I am making a small console app to get XML from an API and then save the data to a database. While this project was not created via test-driven-development, I have tried to make it such that tests can be written easily and properly. Additionally, the core portions of the application are in a separate library project, as I am also making other interfaces (web app, etc.) for working with the API and data.
Application
Imports JetBrains.Annotations
Public Class Application
<UsedImplicitly>
Public Shared Function Main(arguments As String()) As Integer
Dim calendarImporter As ICalendarImporter
If arguments.Length <> 2
calendarImporter = New CalendarImporter(
GetInput("Url: "),
GetInput("Token: "))
Else
calendarImporter = New CalendarImporter(arguments(0), arguments(1))
End If
Try
calendarImporter.RunAsync().GetAwaiter()
Return 0
Catch exception As Exception
HandleException(exception)
Return 1
End Try
End Function
Private Shared Function GetInput(prompt As String) As String
Dim input As String = Nothing
While String.IsNullOrWhiteSpace(input)
System.Console.Write(prompt)
input = System.Console.ReadLine()
End While
Return input
End Function
Private Shared Sub HandleException(exception As Exception)
System.Console.WriteLine(exception.Message)
Dim innerException = exception.InnerException
While innerException IsNot Nothing
System.Console.WriteLine()
System.Console.WriteLine(innerException.Message)
innerException = innerException.InnerException
End While
End Sub
End Class
ICalendarImporter
Public Interface ICalendarImporter
Function RunAsync() As Task
End Interface
CalendarImporter
Imports Library.CalendarImporter.Db
Imports Library.CalendarImporter.Services
Imports Library.CalendarImporter.Services.Interfaces
Public Class CalendarImporter
Implements ICalendarImporter
Implements IDisposable
Public Sub New(url As String, token As String)
Me.Url = url
Me.Token = token
End Sub
Private Property CalendarImporterService As ICalendarImporterService
Private Property Db As CalendarImporterDbContext
Private Property Url As String
Private Property Token As String
Public Async Function RunAsync() As Task Implements ICalendarImporter.RunAsync
CalendarImporterService = New CalendarImporterService(url, token)
Dim calendarImportResult = Await CalendarImporterService.ImportCalendarAsync()
If calendarImportResult.CalendarImport Is Nothing
Throw New Exception(
Convert.ToInt32(calendarImportResult.StatusCode) &
" " &
calendarImportResult.StatusCode.ToString())
End If
Db.CalendarImports.Add(calendarImportResult.CalendarImport)
Await Db.SaveChangesAsync()
End Function
Public Sub Dispose() Implements IDisposable.Dispose
Db?.Dispose()
End Sub
End Class
That concludes the console app. The following items are from the library, and used by the console app and others.
ICalendarImporterService
Imports Library.CalendarImporter.Services.Models
Namespace Services.Interfaces
Public Interface ICalendarImporterService
Function ImportCalendarAsync() As Task(Of ImportCalendarResult)
End Interface
End NameSpace
CalendarImporterService
Imports System.IO
Imports System.Net.Http
Imports System.Net.Http.Headers
Imports System.Xml
Imports System.Xml.Serialization
Imports Library.CalendarImporter.Entities
Imports Library.CalendarImporter.Services.Interfaces
Imports Library.CalendarImporter.Services.Models
Namespace Services
Public Class CalendarImporterService
Implements ICalendarImporterService
Public Sub New(url As String, token As String)
Me.Url = url
Me.Token = token
End Sub
Private ReadOnly Property Url As String
Private ReadOnly Property Token As String
Private Property CalendarImportXmlSerializer As XmlSerializer =
New XmlSerializer(GetType(CalendarImport))
Public Async Function ImportCalendarAsync() As Task(Of ImportCalendarResult) _
Implements ICalendarImporterService.ImportCalendarAsync
Dim getXmlResult = Await GetXmlAsync()
Dim result = New ImportCalendarResult With {
.StatusCode = getXmlResult.StatusCode
}
If Not String.IsNullOrWhiteSpace(getXmlResult.Xml)
result.CalendarImport = DeserializeXml(getXmlResult.Xml)
result.CalendarImport.Xml = getXmlResult.Xml.Replace("UTF-8", "UTF-16")
result.CalendarImport.Date = Date.Now
End If
Return result
End Function
Private Function DeserializeXml(xml As String) As CalendarImport
Using stringReader = New StringReader(xml)
Using xmlReader As XmlReader = XmlReader.Create(stringReader)
Return CalendarImportXmlSerializer.Deserialize(xmlReader)
End Using
End Using
End Function
Private Async Function GetXmlAsync() As Task(Of GetXmlResult)
Using httpClient = New HttpClient
httpClient.DefaultRequestHeaders.Authorization =
New AuthenticationHeaderValue("Basic", Token)
Dim response = Await httpClient.GetAsync(Url)
Dim result = New GetXmlResult With {
.StatusCode = response.StatusCode
}
If response.IsSuccessStatusCode
result.Xml = Await response.Content.ReadAsStringAsync()
End If
Return result
End Using
End Function
End Class
End NameSpace
GetXmlResult
Imports System.Net
Namespace Services.Models
Public Class GetXmlResult
Public Property StatusCode As HttpStatusCode
Public Property Xml As String
End Class
End NameSpace
ImportCalendarResult
Imports System.Net
Imports Library.CalendarImporter.Entities
Namespace Services.Models
Public Class ImportCalendarResult
Public Property CalendarImport As CalendarImport
Public Property StatusCode As HttpStatusCode
End Class
End NameSpace
The Entities
namespace that includes CalendarImport
contains the POCO the XML and database map to. CalendarImport
is the name of the root XML object. The namespaces have been edited to remove potentially identifying information about the client(s) involved with the project.
How would I improve this?