Imports System.Xml Imports System.Net Imports System.Net.Http Imports System.Globalization Imports AutoMapper Imports DigitalData.Modules.Logging Imports DigitalData.Modules.Filesystem Imports ImporterShared.Documents Imports System.Text Namespace Winline Public Class WebService Inherits BaseClass Private ReadOnly Config As Config Private ReadOnly Serializer As Serializer Private ReadOnly Mapper As AutoMapper.Mapper Private ReadOnly FileEx As File Public Sub New(pLogConfig As LogConfig, pConfig As Config) MyBase.New(pLogConfig, pLogConfig.GetLogger()) FileEx = New File(pLogConfig) Serializer = New Serializer(pLogConfig) Config = pConfig Mapper = MapperFactory.GetMapper() End Sub Public Async Function TransferDocumentToWinLine(pDocument As Document) As Task(Of Boolean) If TypeOf pDocument.Data Is Schemas.Orders.Input.MESOWebService Then Return Await TransferOrderToWinline(pDocument) Else Return False End If End Function Private Async Function TransferOrderToWinline(pDocument As Document) As Task(Of Boolean) Dim oOrderOutput = TransformOrderToOutput(pDocument.Data) Dim oWS As Config.WebServiceConfig = Config.Webservice ' --- Get and create path for request/response files Dim oPath As String = GetBaseWebServicePath() If IO.Directory.Exists(oPath) = False Then IO.Directory.CreateDirectory(oPath) End If ' --- Build all teh filenamez and pathz Dim oBaseFileName As String = GetBaseFilenameForRequest() Dim oFileName = GetXmlFilenameWithSuffix(oBaseFileName, "Request", "xml") ' Relative Path for Webservice Call Dim oImportRelativeFilePath = IO.Path.Combine(GetDateSubDirectoryPath(Config.Webservice.ImportRelativePath), oFileName) ' Absolute Path to copy Request file Dim oImportAbsolutePath = IO.Path.Combine(Config.Webservice.ImportBasePath, Config.Webservice.ImportRelativePath) Dim oImportAbsoluteFilePath = IO.Path.Combine(GetDateSubDirectoryPath(oImportAbsolutePath), oFileName) ' --- Serialize Data into XML string Dim oOutputFilePath = SerializeOrder(oOrderOutput, oFileName) ' --- Copy file to Winline Import Directory Try IO.File.Copy(oOutputFilePath, oImportAbsoluteFilePath, True) Catch ex As Exception Logger.Error(ex) Throw ex End Try ' --- Prepare URL and HTTP Client Dim oTemplateType = 30 Dim oTemplateName = "EXIM-VRG_orders" ' ActionCode: Should this be a test or not? ' 0 = Testcall ' 1 = Real call Dim oActionCode = 1 ' Byref: Should data be supplied as file or as string? ' 0 = As String ' 1 = As File (relative to Winline Server directory) Dim oByref = 1 Dim oURL As String = $"{oWS.BaseUrl}/ewlservice/import?User={oWS.Username}&Password={oWS.Password}&Company={pDocument.Mandator}&Type={oTemplateType}&Vorlage={oTemplateName}&ActionCode={oActionCode}&Byref={oByref}&Data={oImportRelativeFilePath}" Dim oClient As New HttpClient() Logger.Info("Creating HTTP Request to [{0}]", oWS.BaseUrl) ' --- Bring the action! Try Dim oResponse As HttpResponseMessage = Await oClient.GetAsync(oURL) Await HandleResponse(oResponse, oPath, oBaseFileName) Return True Catch ex As Exception Logger.Error(ex) Throw ex Finally oClient.Dispose() End Try End Function Private Async Function HandleResponse(pResponse As HttpResponseMessage, pPath As String, pBaseFileNAme As String) As Task pResponse.EnsureSuccessStatusCode() Dim oResponseBody As String = Await pResponse.Content.ReadAsStringAsync() Dim oContentType = pResponse.Content.Headers.ContentType.MediaType Dim oSerializer = Serializer.GetSerializer(GetType(Schemas.MESOWebServiceResult)) Select Case oContentType Case "text/xml" WriteResponseFile(pPath, pBaseFileNAme, oResponseBody, "xml") Dim oBytes As Byte() = Encoding.UTF8.GetBytes(oResponseBody) Using oStream As New IO.MemoryStream(oBytes) Dim oResponseObject As Schemas.MESOWebServiceResult = oSerializer.Deserialize(oStream) For Each oDetails As Schemas.MESOWebServiceResultResultDetails In oResponseObject.ResultDetails If oDetails.Success = True Then Logger.Info("KeyValue: [{0}]", oDetails.KeyValue) Logger.Info("VoucherNumber: [{0}]", oDetails.VoucherNumber) Else Logger.Warn("ErrorCode: [{0}]", oDetails.ErrorCode) Logger.Warn("ErrorText: [{0}]", oDetails.ErrorText) End If Next If oResponseObject.OverallSuccess = False Then Throw New ApplicationException("Request to Webservice was unsuccessful. Please check the logs.") End If End Using Case "text/html" WriteResponseFile(pPath, pBaseFileNAme, oResponseBody, "txt") Throw New ApplicationException(oResponseBody) Case Else Throw New ApplicationException(oResponseBody) End Select End Function Private Function WriteResponseFile(pPath As String, pBaseFileName As String, pResponseBody As String, pExtension As String) Try Dim oRequestFileName As String = GetXmlFilenameWithSuffix(pBaseFileName, "Response", pExtension) Dim oFilePath As String = IO.Path.Combine(pPath, oRequestFileName) IO.File.WriteAllText(oFilePath, pResponseBody) Return True Catch ex As Exception Logger.Error(ex) Return False End Try End Function Private Function TransformOrderToOutput(pData As Schemas.Orders.Input.MESOWebService) As Schemas.Orders.Output.MESOWebService Dim oData As Schemas.Orders.Input.MESOWebService = pData Dim oResult As Schemas.Orders.Output.MESOWebService = Mapper.Map(Of Schemas.Orders.Output.MESOWebService)(oData) Dim oItems = oData.Items. Select(Function(i) If TypeOf i Is Schemas.Orders.Input.MESOWebServiceEXIMVRG_ordersT025 Then Return Mapper.Map(Of Schemas.Orders.Output.MESOWebServiceEXIMVRG_ordersT025)(i) Else Return Mapper.Map(Of Schemas.Orders.Output.MESOWebServiceEXIMVRG_ordersT026)(i) End If End Function). ToList() oResult.Items = oItems.ToArray() Return oResult End Function Private Function SerializeOrder(pData As Schemas.Orders.Output.MESOWebService, pFileName As String) As String Dim oSerializer = Serializer.GetSerializer(GetType(Schemas.Orders.Output.MESOWebService)) Dim oPath As String = GetBaseWebServicePath() Dim oFilePath As String = IO.Path.Combine(oPath, pFileName) Using oWriter = XmlWriter.Create(oFilePath, New XmlWriterSettings With {.Indent = True}) oSerializer.Serialize(oWriter, pData) End Using Return oFilePath End Function Private Function GetBaseWebServicePath() As String Return IO.Path.Combine(FileEx.GetAppDataPath("Digital Data", "EDI Document Importer"), "WebService") End Function Private Function GetBaseFilenameForRequest() As String Return $"{Now:yyyy-MM-dd_hh-mm-ffff}" End Function Private Function GetXmlFilenameWithSuffix(pBaseString As String, pSuffix As String, pExtension As String) Return $"{pBaseString}-{pSuffix}.{pExtension}" End Function Private Function GetDateSubDirectoryPath(pBasePath As String) Dim oDirectoryPath As String = Now.ToString("yyyy\\MM\\dd") Dim oFullPath As String = IO.Path.Combine(pBasePath, oDirectoryPath) If IO.Directory.Exists(oFullPath) = False Then Try IO.Directory.CreateDirectory(oFullPath) Return oFullPath Catch ex As Exception Logger.Error(ex) Return Nothing End Try Else Return oFullPath End If End Function End Class End Namespace