Imports System.Xml Imports System.Text Imports System.Net.Http Imports DigitalData.Modules.Logging Imports DigitalData.Modules.Filesystem Imports MultiTool.Shared.Documents Namespace Winline Public Class WebService Inherits BaseClass Private ReadOnly Config As Config Private ReadOnly Serializer As Serializer Private ReadOnly AppDataPath As String Public Event WebServiceProgress As EventHandler(Of String) Public Sub New(pLogConfig As LogConfig, pConfig As Config, pAppDataPath As String) MyBase.New(pLogConfig, pLogConfig.GetLogger()) Serializer = New Serializer(pLogConfig) Config = pConfig AppDataPath = pAppDataPath 'Mapper = MapperFactory.GetMapper() End Sub Public Async Function TransferDocumentToWinline(pDocument As Document) As Task(Of Boolean) Dim oBytes As Byte() = GetBytesFromDocument(pDocument) 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 RaiseEvent WebServiceProgress(Me, "Einstellungen laden") ' --- 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 RaiseEvent WebServiceProgress(Me, "Dateien schreiben") Dim oOutputFilePath = IO.Path.Combine(GetBaseWebServicePath(), oFileName) IO.File.WriteAllBytes(oOutputFilePath, oBytes) ' --- 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 = pDocument.TemplateType Dim oTemplateName = pDocument.TemplateName ' 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.Id}&Type={oTemplateType}&Vorlage={oTemplateName}&ActionCode={oActionCode}&Byref={oByref}&Data={oImportRelativeFilePath}" Dim oClient As New HttpClient() Logger.Info("Creating HTTP Request to [{0}]", oWS.BaseUrl) RaiseEvent WebServiceProgress(Me, "Anfrage absenden") ' --- 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)) RaiseEvent WebServiceProgress(Me, "Antwort verarbeiten") 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) Dim oErrorStrings As New List(Of String) 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) oErrorStrings.Add($"[{oDetails.ErrorCode}] {oDetails.ErrorText}") End If Next If oResponseObject.OverallSuccess = False Then Dim oMessage = $"Request to Webservice was unsuccessful:{vbNewLine}{vbNewLine}{String.Join(vbNewLine, oErrorStrings.ToArray)}" Throw New ApplicationException(oMessage) 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 GetBytesFromDocument(pDocument As Document) As Byte() ' TODO: should "Lief_Name" be included here? Dim oFilteredFields As New List(Of String) From { "Fakt_Name" } Using oStream As New IO.MemoryStream() Dim w = XmlWriter.Create(oStream) w.WriteStartDocument() w.WriteStartElement("MESOWebService") w.WriteAttributeString("Template", pDocument.TemplateName) w.WriteAttributeString("TemplateType", pDocument.TemplateType) w.WriteAttributeString("option", pDocument.Option) w.WriteAttributeString("printVoucher", pDocument.PrintVoucher) For Each oRow In pDocument.Rows w.WriteStartElement(oRow.Name) For Each oField As KeyValuePair(Of String, DocumentRow.FieldValue) In oRow.Fields If oField.Value.Final = String.Empty Then Continue For End If If oFilteredFields.Contains(oField.Key) Then Continue For End If w.WriteStartElement(oField.Key) w.WriteValue(oField.Value.Final) w.WriteEndElement() ' Field Next w.WriteEndElement() ' Row Next w.WriteEndElement() ' MESOWebService w.WriteEndDocument() ' Document w.Close() Return oStream.ToArray() End Using 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(AppDataPath, "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