MultiTool/MultiTool.Shared/Winline/WebServiceData.vb
2021-11-23 16:26:11 +01:00

235 lines
9.5 KiB
VB.net

Imports System.Xml
Imports System.Text
Imports System.Net.Http
Imports DigitalData.Modules.Logging
Imports MultiTool.Shared.Documents
Imports MultiTool.Shared.Templates.GeneralConfig
Imports MultiTool.Shared.Winline.Entities
Namespace Winline
Public Class WebServiceData
Inherits BaseClass
Private ReadOnly Config As WebServiceConfig
Private ReadOnly Serializer As Serializer
Private ReadOnly AppDataPath As String
Public Event WebServiceProgress As EventHandler(Of String)
Public Sub New(pLogConfig As LogConfig, pWebserviceConfig As WebServiceConfig, pAppDataPath As String)
MyBase.New(pLogConfig, pLogConfig.GetLogger())
Serializer = New Serializer(pLogConfig)
Config = pWebserviceConfig
AppDataPath = pAppDataPath
End Sub
Public Async Function TransferDocumentToWinline(pDocument As Document, pMandator As Mandator, Optional pIsTest As Boolean = False) As Task(Of Boolean)
Dim oBytes As Byte() = GetBytesFromDocument(pDocument)
Dim oWS = Config
' --- 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(oWS.ImportRelativePath), oFileName)
' Absolute Path to copy Request file
Dim oImportAbsolutePath = IO.Path.Combine(oWS.ImportBasePath, oWS.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 = Test call
' 1 = Real call
Dim oActionCode = 1
If pIsTest = True Then
oActionCode = 0
End If
' 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={pMandator.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(Templates.Entities.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 Templates.Entities.MESOWebServiceResult = oSerializer.Deserialize(oStream)
Dim oErrorStrings As New List(Of String)
For Each oDetails As Templates.Entities.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()
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)
pDocument.Rows.Sort()
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 oField.Value.IsVirtual 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 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