LocalFileStorage

This commit is contained in:
2025-06-05 14:03:55 +02:00
parent 5e7080fd9d
commit ed4dc8fa75
24 changed files with 298 additions and 189 deletions

View File

@@ -29,5 +29,10 @@ namespace BeWo.Data.Access
{
return new LocalFileStorageDAO(rootpath);
}
}
public static LocalTenantFileStorageDAO GetLocalTenantFileStorage(string rootpath)
{
return new LocalTenantFileStorageDAO(rootpath);
}
}
}

View File

@@ -3,14 +3,17 @@ using BS.Shared;
using BS.Shared.Core;
using BS.Shared.Exceptions;
using BS.Shared.Interface;
using DevExpress.Mvvm.Native;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Remoting.Messaging;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web.UI.WebControls;
using Task = System.Threading.Tasks.Task;
namespace BeWo.Data.Access
@@ -24,47 +27,29 @@ namespace BeWo.Data.Access
_rootPath = rootPath;
}
private string GetFilePath(string tenant, string filePath)
private string GetFilePath(string filePath)
{
return Path.Combine(_rootPath, tenant, filePath);
return Path.Combine(_rootPath, filePath);
}
public async Task<IStoredFile> SaveXRechnungPdfAsync(string tenant, IInvoiceBase invoicebase, Stream content)
public async Task SaveLogAsync(string pFileName, Stream content, CancellationToken cancellationToken = default)
{
var lTid = (int)TableID.InvoiceBase;
var lOid = invoicebase.Oid;
var lFileName = $"{lOid}.XRechnung.pdf";
var lFilePath = Path.Combine("logs", pFileName);
return await SaveFileAsync(tenant, BWPFeature.XRechnung, lFileName, "application/pdf", content, lTid, lOid).ConfigureAwait(true);
await SaveFileAsync(lFilePath, pFileName, content, cancellationToken).ConfigureAwait(true);
}
private async Task<IStoredFile> SaveFileAsync(string tenant, BWPFeature feature, string pFileName, string pContentType, Stream content, int? pBeWoObjectTid = null, long? pBeWoObjectOid = null, CancellationToken cancellationToken = default)
{
var lFilePath = feature.ToString();
return await SaveFileAsync(tenant, lFilePath, pFileName, pContentType, content, pBeWoObjectTid, pBeWoObjectOid, cancellationToken).ConfigureAwait(true);
}
private async Task<IStoredFile> SaveFileAsync(string tenant, string pFilePath, string pFileName, string pContentType, Stream content, int? pBeWoObjectTid = null, long? pBeWoObjectOid = null, CancellationToken cancellationToken = default)
private async Task SaveFileAsync(string pFilePath, string pFileName, Stream content, CancellationToken cancellationToken = default)
{
// Prüfe Namen
if (SecurityUtils.ContainsInvalidFilenameChars(pFilePath))
if (SecurityUtils.ContainsInvalidFilenameChars(pFileName))
throw new BeWoInvalidOperationException(AppError.LocalFileStorageFileNameInvalidChar);
if (Path.GetFileName(pFilePath) != pFileName)
throw new BeWoInvalidOperationException(AppError.LocalFileStorageFileNameNotEqFilePath);
// Erstelle DB Eintrag
var storedfile = new StoredFile();
storedfile.FileName = pFileName;
storedfile.FilePath = pFilePath;
storedfile.ContentType = pContentType;
storedfile.BeWoObjectTid = pBeWoObjectTid;
storedfile.BeWoObjectOid = pBeWoObjectOid;
// Erstelle File Ordner
var path = GetFilePath(tenant, pFilePath);
var path = GetFilePath(pFilePath);
var directory = Path.GetDirectoryName(path);
Directory.CreateDirectory(directory);
@@ -72,21 +57,17 @@ namespace BeWo.Data.Access
using (var stream = File.Create(path))
{
await content.CopyToAsync(stream, bufferSize: 81920, cancellationToken).ConfigureAwait(true);
storedfile.Size = content.Position;
storedfile.Checksum = SecurityUtils.GetChecksumBuffered(content);
}
return storedfile;
}
public Task<bool> FileExistsAsync(string tenant, IStoredFile storedFile, CancellationToken cancellationToken = default)
public Task<bool> FileExistsAsync(string pFilePath, CancellationToken cancellationToken = default)
{
return Task.FromResult(File.Exists(GetFilePath(tenant, storedFile.FilePath)));
return Task.FromResult(File.Exists(GetFilePath(pFilePath)));
}
public Task<Stream> GetFileAsync(string tenant, IStoredFile storedFile, CancellationToken cancellationToken = default)
public Task<Stream> GetFileAsync(string pFilePath, CancellationToken cancellationToken = default)
{
var path = GetFilePath(tenant, storedFile.FilePath);
var path = GetFilePath(pFilePath);
if (!File.Exists(path))
return Task.FromResult<Stream>(null);
@@ -94,9 +75,9 @@ namespace BeWo.Data.Access
return Task.FromResult(stream);
}
public Task<bool> DeleteFileAsync(string tenant, IStoredFile storedFile, CancellationToken cancellationToken = default)
public Task<bool> DeleteFileAsync(string pFilePath, CancellationToken cancellationToken = default)
{
var path = GetFilePath(tenant, storedFile.FilePath);
var path = GetFilePath(pFilePath);
if (File.Exists(path))
{
File.Delete(path);

View File

@@ -0,0 +1,111 @@
using BeWo.Data.Entities;
using BS.Shared;
using BS.Shared.Core;
using BS.Shared.Exceptions;
using BS.Shared.Interface;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Remoting.Messaging;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web.UI.WebControls;
using Task = System.Threading.Tasks.Task;
namespace BeWo.Data.Access
{
public class LocalTenantFileStorageDAO
{
private readonly string _rootPath;
public LocalTenantFileStorageDAO(string rootPath)
{
_rootPath = rootPath;
}
private string GetFilePath(string tenant, string filePath)
{
return Path.Combine(_rootPath, tenant, filePath);
}
public async Task<IStoredFile> SaveXRechnungPdfAsync(string tenant, IInvoiceBase invoicebase, Stream content)
{
var lTid = (int)TableID.InvoiceBase;
var lOid = invoicebase.Oid;
var lFileName = $"{lOid}.XRechnung.pdf";
return await SaveFileAsync(tenant, BWPFeature.XRechnung, lFileName, "application/pdf", content, lTid, lOid).ConfigureAwait(true);
}
private async Task<IStoredFile> SaveFileAsync(string tenant, BWPFeature feature, string pFileName, string pContentType, Stream content, int? pBeWoObjectTid = null, long? pBeWoObjectOid = null, CancellationToken cancellationToken = default)
{
var lFilePath = feature.ToString();
return await SaveFileAsync(tenant, lFilePath, pFileName, pContentType, content, pBeWoObjectTid, pBeWoObjectOid, cancellationToken).ConfigureAwait(true);
}
private async Task<IStoredFile> SaveFileAsync(string tenant, string pFilePath, string pFileName, string pContentType, Stream content, int? pBeWoObjectTid = null, long? pBeWoObjectOid = null, CancellationToken cancellationToken = default)
{
// Prüfe Namen
if (SecurityUtils.ContainsInvalidFilenameChars(pFilePath))
throw new BeWoInvalidOperationException(AppError.LocalFileStorageFileNameInvalidChar);
if (Path.GetFileName(pFilePath) != pFileName)
throw new BeWoInvalidOperationException(AppError.LocalFileStorageFileNameNotEqFilePath);
// Erstelle DB Eintrag
var storedfile = new StoredFile();
storedfile.FileName = pFileName;
storedfile.FilePath = pFilePath;
storedfile.ContentType = pContentType;
storedfile.BeWoObjectTid = pBeWoObjectTid;
storedfile.BeWoObjectOid = pBeWoObjectOid;
// Erstelle File Ordner
var path = GetFilePath(tenant, pFilePath);
var directory = Path.GetDirectoryName(path);
Directory.CreateDirectory(directory);
// Speichere Datei
using (var stream = File.Create(path))
{
await content.CopyToAsync(stream, bufferSize: 81920, cancellationToken).ConfigureAwait(true);
storedfile.Size = content.Position;
storedfile.Checksum = SecurityUtils.GetChecksumBuffered(content);
}
return storedfile;
}
public Task<bool> FileExistsAsync(string tenant, IStoredFile storedFile, CancellationToken cancellationToken = default)
{
return Task.FromResult(File.Exists(GetFilePath(tenant, storedFile.FilePath)));
}
public Task<Stream> GetFileAsync(string tenant, IStoredFile storedFile, CancellationToken cancellationToken = default)
{
var path = GetFilePath(tenant, storedFile.FilePath);
if (!File.Exists(path))
return Task.FromResult<Stream>(null);
Stream stream = File.OpenRead(path);
return Task.FromResult(stream);
}
public Task<bool> DeleteFileAsync(string tenant, IStoredFile storedFile, CancellationToken cancellationToken = default)
{
var path = GetFilePath(tenant, storedFile.FilePath);
if (File.Exists(path))
{
File.Delete(path);
return Task.FromResult(true);
}
return Task.FromResult(false);
}
}
}

View File

@@ -213,6 +213,7 @@
<Compile Include="Access\GenericDAO.cs" />
<Compile Include="Access\FinanceDAO.cs" />
<Compile Include="Access\LocalFileStorageDAO.cs" />
<Compile Include="Access\LocalTenantFileStorageDAO.cs" />
<Compile Include="Access\OrganisationDAO.cs" />
<Compile Include="Access\ScriptDAO.cs" />
<Compile Include="Access\SearchDAO.cs" />

View File

@@ -3,7 +3,7 @@
<PropertyGroup>
<NameOfLastUsedPublishProfile>C:\Projects\Bewo\BeWo - Main\Host\Properties\PublishProfiles\FolderProfile.pubxml</NameOfLastUsedPublishProfile>
<UseIISExpress>true</UseIISExpress>
<LastActiveSolutionConfig>Debug|Any CPU</LastActiveSolutionConfig>
<LastActiveSolutionConfig>Release|Any CPU</LastActiveSolutionConfig>
<Use64BitIISExpress>false</Use64BitIISExpress>
<IISExpressSSLPort />
<IISExpressAnonymousAuthentication />

View File

@@ -324,7 +324,8 @@
<add key="OpenWebUIUrl" value="https://owui1.ownsoft.de/"/>
<add key="XRechnungApiUrl" value="https://test2.evplaner.de/xrg/"/>
<add key="HelloWorldPdfLocation" value="C:\StoredFiles"/>
<add key="StoredFilesFolderPath" value="C:\StoredFiles"/>
<add key="HelloWorldPdfLocation" value="C:\StoredFiles\HelloWorld.pdf"/>
</appSettings>
<!-- <> <> <> Appsettings <> <> <> -->
<devExpress>

View File

@@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BeWo.Service.Attributes
{
[AttributeUsage(AttributeTargets.Method, Inherited = true)]
public class RequireIPAddressAttribute : Attribute
{
public WebConfigSetting WebConfigSetting { get; set; }
public RequireIPAddressAttribute(WebConfigSetting pWebConfig)
{
WebConfigSetting = pWebConfig;
}
}
}

View File

@@ -9,7 +9,8 @@ namespace BeWo.Service
public enum WebConfigSetting
{
OpenWebUIUrl,
XRechnungApiUrl,
XRechnungApiUrl,
StoredFilesFolderPath,
HelloWorldPdfLocation
}

View File

@@ -229,6 +229,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="Attributes\RequireApiKeyAttribute.cs" />
<Compile Include="Attributes\RequireIPAddressAttribute.cs" />
<Compile Include="Attributes\RequireNoTenantAttribute.cs" />
<Compile Include="Attributes\RequirePermissionAttribute.cs" />
<Compile Include="BeWoServiceEnums.cs" />
@@ -580,7 +581,6 @@
<Compile Include="ServiceUtils\ServiceTranslator.cs" />
<Compile Include="ServiceUtils\ServiceHelper.cs" />
<Compile Include="ServiceUtils\UriTemplateResolver.cs" />
<Compile Include="ServiceUtils\XRechnung\XRechnungSender.cs" />
<Compile Include="UnitOfWork\HibernateSessionEndpointBehavior.cs" />
<Compile Include="UnitOfWork\HibernateSessionBehaviorExtension.cs" />
<Compile Include="UnitOfWork\HibernateSessionContextInitializer.cs" />
@@ -623,6 +623,7 @@
<ItemGroup>
<Folder Include="ServiceUtils\API\" />
<Folder Include="ServiceUtils\Generell\" />
<Folder Include="ServiceUtils\XRechnung\" />
</ItemGroup>
<ItemGroup>
<None Include="..\.editorconfig">

View File

@@ -1,4 +1,6 @@
using System;
using BeWo.Data.Access;
using BeWo.Service.ServiceUtils;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
@@ -50,9 +52,14 @@ namespace BeWo.Service.ServiceBehavior.JsonError
{
serializer.WriteObject(stream, jsonError);
stream.Position = 0;
ServiceHelper.WriteLogFile("LastJsonError.json.txt", stream);
stream.Position = 0;
using (var reader = new StreamReader(stream))
{
string jsonString = reader.ReadToEnd();
fault = Message.CreateMessage(version, null, new JsonBodyWriter(jsonString));
}
}

View File

@@ -3,6 +3,7 @@ using BS.Shared;
using BS.Shared.Core;
using BS.Shared.DataContracts;
using BS.Shared.DataContracts.Feature.AI;
using BS.Shared.DataContracts.Invoicing.XRechnung;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -17,6 +18,6 @@ namespace BeWo.Service.ServiceContracts.Enhanced
{
[FaultContract(typeof(BeWoFault))]
[OperationContract]
byte[] CreateXRechnung(long invoice_base_oid, int report_type, string report_url);
XRechnungResponse CreateXRechnung(long invoice_base_oid, int report_type, string report_url);
}
}

View File

@@ -141,7 +141,5 @@ namespace BeWo.Service.ServiceContracts
[FaultContract(typeof(BeWoFault))]
[OperationContract]
void StorniereInvoiceBases(List<InvoiceBaseDC> invoices);
[FaultContract(typeof(BeWoFault))] [OperationContract] XRechnungResponse GetXRechnung(XRechnungRequest req);
}
}

View File

@@ -25,5 +25,10 @@ namespace BeWo.Service.ServiceContracts
[WebGet(UriTemplate = "/GetPdf", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
[RequireNoTenant]
Stream GetPdf();
[OperationContract]
[WebInvoke(UriTemplate = "/GetPdf", Method = "POST", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
[RequireNoTenant]
Stream GetPdf2();
}
}

View File

@@ -30,7 +30,6 @@ using BS.Shared.AppSender;
using BeWo.Data.Security;
using BeWo.Data.Models.XRechnung;
using BS.Shared.DataContracts.Invoicing.XRechnung;
using BeWo.Service.ServiceUtils.XRechnung;
using System.IO;
using BeWo.Service.ServiceUtils;
@@ -750,29 +749,5 @@ namespace BeWo.Service.ServiceImplementations
throw Utils.CreateBeWoFaultException(e);
}
}
public XRechnungResponse GetXRechnung(XRechnungRequest req)
{
try
{
var str = ServiceConfigReader.GetInvoiceTestJsonString();
//var str = File.ReadAllText(@"C:\dev\invoicetest.json", System.Text.Encoding.UTF8);
var xrec = JsonConvert.DeserializeObject<XRechnung>(str);
var url = "https://app5.bewoplaner.de/service/DownloadFile.aspx?key=jhkf4589141324h6543958";
var ds = new DownloadServiceImp();
var url2 = ds.CreateTemporaryUrl(url, false);
var response = XRechnungSender.Send(xrec, url2);
return response;
}
catch (Exception e)
{
throw Utils.CreateBeWoFaultException(e);
}
}
}
}

View File

@@ -1,6 +1,7 @@
using BeWo.Data.Access;
using BeWo.Service.ServiceContracts;
using BeWo.Service.ServiceImplementations.Enhanced;
using BeWo.Service.ServiceUtils;
using BS.Shared.Core;
using BS.Shared.DataContracts.AdminService;
using BS.Shared.DataContracts.MikePHPContracts;
@@ -10,6 +11,7 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Principal;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
@@ -22,9 +24,12 @@ namespace BeWo.Service.ServiceImplementations
{
public ApiResponse<string> Test()
{
var message = new OperationsEnhancedServiceImp().HelloWorld();
var identity = WindowsIdentity.GetCurrent();
var message = $"{identity.Name} - {identity.IsAuthenticated} - {identity.AuthenticationType}";
return ApiResponse<string>.SuccessResponse(message);
ServiceHelper.WriteLogFile("ApiServiceTest", message);
return ApiResponse<string>.SuccessResponse("Hello World!");
}
public ApiResponse<decimal> GetGkvAbrechnungSumme(AdminServiceSumReqDC request)

View File

@@ -50,11 +50,13 @@ namespace BeWo.Service.ServiceImplementations
public Stream GetPdf()
{
WebOperationContext.Current.OutgoingResponse.ContentType = "application/pdf";
WebOperationContext.Current.OutgoingResponse.Headers.Add("Content-Disposition", "attachment; filename=\"helloworld.pdf\"");
WebOperationContext.Current.OutgoingResponse.Headers.Add("Content-Disposition", "inline; filename=\"helloworld.pdf\"");
var lFilePath = MergedConfig.GetSetting(WebConfigSetting.HelloWorldPdfLocation);
return new FileStream(lFilePath, FileMode.Open, FileAccess.Read);
}
public Stream GetPdf2() => GetPdf();
}
}

View File

@@ -7,7 +7,6 @@ using BeWo.Service.DCEntityMapper;
using BeWo.Service.ServiceContracts.Enhanced;
using BeWo.Service.ServiceProxy;
using BeWo.Service.ServiceUtils;
using BeWo.Service.ServiceUtils.XRechnung;
using BS.Shared;
using BS.Shared.DataContracts;
using BS.Shared.DataContracts.Feature.AI;
@@ -29,7 +28,7 @@ namespace BeWo.Service.ServiceImplementations.Enhanced
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Single)]
public class AccountingEnhancedServiceImp : IAccountingEnhancedService
{
public byte[] CreateXRechnung(long invoice_base_oid, int report_type, string report_url)
public XRechnungResponse CreateXRechnung(long invoice_base_oid, int report_type, string report_url)
{
if (string.IsNullOrWhiteSpace(report_url))
throw new ArgumentNullException(nameof(report_url));
@@ -39,9 +38,9 @@ namespace BeWo.Service.ServiceImplementations.Enhanced
// Erstelle Url ohne weitere Authentifizierung
var download_url = report_url + "&mode=pdf";
var token_url = (new DownloadServiceImp()).CreateTemporaryUrl(download_url, false);
var token_url = new DownloadServiceImp().CreateTemporaryUrl(download_url, false);
var response = ServiceFacade.XRechnung.Create(str, token_url).GetAwaiter().GetResult();
var response = ServiceFacade.XRechnung.Create(str, token_url);
return response;
}

View File

@@ -8,7 +8,6 @@ using BeWo.Service.DCEntityMapper;
using BeWo.Service.ServiceContracts.Enhanced;
using BeWo.Service.ServiceProxy;
using BeWo.Service.ServiceUtils;
using BeWo.Service.ServiceUtils.XRechnung;
using BS.Shared;
using BS.Shared.DataContracts;
using BS.Shared.DataContracts.Feature.AI;
@@ -35,10 +34,7 @@ namespace BeWo.Service.ServiceImplementations.Enhanced
{
public string HelloWorld()
{
return "OperationEnhancedService: Hello World!" +
"\n\n" + ServiceSecurityContext.Current.PrimaryIdentity.Name +
"\n" + ServiceSecurityContext.Current.PrimaryIdentity.AuthenticationType +
"\n" + ServiceSecurityContext.Current.PrimaryIdentity.IsAuthenticated;
return "OperationEnhancedService: Hello World!";
}
}
}

View File

@@ -4,12 +4,14 @@ using BeWo.Service.DCEntityMapper;
using BS.Shared.Core;
using BS.Shared.Core.Facade;
using BS.Shared.DataContracts.Feature.AI;
using BS.Shared.DataContracts.Invoicing.XRechnung;
using DevExpress.XtraRichEdit.Model;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Security.Policy;
using System.Text;
using System.Threading.Tasks;
@@ -19,14 +21,27 @@ namespace BeWo.Service.ServiceProxy
{
private readonly JsonHttpClientFacade _JsonHttpClientFacade;
public XRechnungApiClient()
public XRechnungApiClient() : this(MergedConfig.GetSetting(WebConfigSetting.XRechnungApiUrl)) { }
public XRechnungApiClient(string base_url)
{
var base_url = MergedConfig.GetSetting(WebConfigSetting.XRechnungApiUrl);
_JsonHttpClientFacade = new JsonHttpClientFacade(base_url);
}
public Task<byte[]> Create(object xrechnung, string url)
public XRechnungResponse Create(object xrechnung)
{
_JsonHttpClientFacade.JsonObject = new
{
json = xrechnung
};
var bytes = _JsonHttpClientFacade.SendAsync("create").GetAwaiter().GetResult();
var response = XRechnungResponse.Parse(bytes);
return response;
}
public XRechnungResponse Create(object xrechnung, string url)
{
_JsonHttpClientFacade.JsonObject = new
{
@@ -34,7 +49,11 @@ namespace BeWo.Service.ServiceProxy
pdf = url
};
return _JsonHttpClientFacade.SendAsync("create");
var bytes = _JsonHttpClientFacade.SendAsync("create").GetAwaiter().GetResult();
var response = XRechnungResponse.Parse(bytes);
return response;
}
}
}

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.IdentityModel.Claims;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Remoting.Channels;
@@ -9,6 +10,8 @@ using System.ServiceModel.Channels;
using System.ServiceModel.Dispatcher;
using System.Text;
using System.Threading.Tasks;
using BeWo.Data.Access;
using BeWo.Service.Core;
using BS.Shared.Extensions;
using NHibernate.Hql.Ast.ANTLR.Tree;
@@ -109,5 +112,34 @@ namespace BeWo.Service.ServiceUtils
return attribute;
}
public static void WriteLogFile(string pFileName, string pContent, string root_path = null)
{
if (root_path == null)
root_path = MergedConfig.GetSetting(WebConfigSetting.StoredFilesFolderPath);
var storage = DAOFactory.GetLocalFileStorage(root_path);
using (var stream = new MemoryStream())
{
using (var writer = new StreamWriter(stream))
{
writer.Write(pContent);
writer.Flush();
stream.Position = 0;
storage.SaveLogAsync(pFileName, stream).GetAwaiter().GetResult();
}
}
}
public static void WriteLogFile(string pFileName, Stream pContent)
{
var root_path = MergedConfig.GetSetting(WebConfigSetting.StoredFilesFolderPath);
var storage = DAOFactory.GetLocalFileStorage(root_path);
storage.SaveLogAsync(pFileName, pContent).GetAwaiter().GetResult();
}
}
}

View File

@@ -1,77 +0,0 @@
using BeWo.Data.Models.XRechnung;
using BS.Shared.AppSender;
using BS.Shared.DataContracts.Invoicing.XRechnung;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
namespace BeWo.Service.ServiceUtils.XRechnung
{
public static class XRechnungSender
{
private static readonly string XRECHNUNG_SERVER_URL = "https://test2.evplaner.de/xrg/create";
public static XRechnungResponse Send(object xrechnung, string url = null)
{
var request_dict = new Dictionary<string, object>()
{
{"json", xrechnung },
{ "pdf", url }
};
var request = new XRechnungRequest();
request.SetXRechnung(xrechnung);
request.Url = url;
var dict = request.ToDict();
var res_bytes = GetResponse(dict);
if (res_bytes is null)
return null;
if(XRechnungResponse.TryParse(res_bytes, out XRechnungResponse response))
{
return response;
}
return null;
}
private static byte[] GetResponse(IEnumerable<KeyValuePair<string, string>> kvp)
{
HttpResponseMessage response;
using (var httpClient = new HttpClient())
{
using (var content = new FormUrlEncodedContent(kvp))
{
content.Headers.Clear();
content.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
var task = Task.Run(() => httpClient.PostAsync(XRECHNUNG_SERVER_URL, content));
task.Wait();
response = task.Result;
}
}
if (response is null)
return null;
//if (!response.IsSuccessStatusCode)
// return null;
var task2 = Task.Run(() => response.Content.ReadAsByteArrayAsync());
task2.Wait();
return task2.Result;
}
}
}

View File

@@ -27,15 +27,22 @@ namespace BS.Shared.DataContracts.Invoicing.XRechnung
ResponseBytes = res_bytes;
}
public static XRechnungResponse Parse(byte[] res_bytes)
{
var response = new XRechnungResponse(res_bytes);
response.LoadErrors();
return response;
}
public static bool TryParse(byte[] res_bytes, out XRechnungResponse rechnungResponse)
{
rechnungResponse = null;
try
{
rechnungResponse = new XRechnungResponse(res_bytes);
rechnungResponse.LoadErrors();
rechnungResponse = Parse(res_bytes);
return true;
}

View File

@@ -148,7 +148,7 @@
<Compile Include="Core\MailUtils.cs" />
<Compile Include="Core\SecurityUtils.cs" />
<Compile Include="Core\TokenUtils.cs" />
<Compile Include="Core\Utilss\WebUtils.cs" />
<Compile Include="Core\Utilities\WebUtils.cs" />
<Compile Include="Core\Validator.cs" />
<Compile Include="Core\DebugUtils.cs" />
<Compile Include="Core\ImageUtils.cs" />

View File

@@ -1,32 +1,66 @@
using BeWo.Data.Models.XRechnung;
using BeWo.Service.ServiceUtils.XRechnung;
using BeWo.Data.Access;
using BeWo.Data.Models.XRechnung;
using BeWo.Service.ServiceProxy;
using BeWo.Service.ServiceUtils;
using BS.Shared.AppSender;
using BS.Shared.DataContracts.Invoicing.XRechnung;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Newtonsoft.Json;
using System;
using System.IO;
using System.Security.Policy;
using System.Text.RegularExpressions;
using static System.Net.WebRequestMethods;
namespace XRechnungUnitTest
{
[TestClass]
public class UnitTest1
{
public string Url { get; set; }
public string ValidDownloadUrl { get; set; }
public string InvalidDownloadUrl { get; set; }
public string InvoiceTest { get; set; }
public XRechnung XRechnung { get; set; }
public XRechnungApiClient ValidApiClient { get; set; }
public XRechnungApiClient InvalidApiClient { get; set; }
[TestInitialize]
public void Init()
{
InvoiceTest = File.ReadAllText("invoicetest.json", System.Text.Encoding.UTF8);
Url = "https://test2.evplaner.de/xrg/";
ValidDownloadUrl = "https://app5.bewoplaner.de/service/ApiStreamService.svc/GetPdf";
InvalidDownloadUrl = "https://app5.bewoplaner.de/service/ApiStreamService.svc/GetFakePdf";
ValidApiClient = new XRechnungApiClient(Url);
InvalidApiClient = new XRechnungApiClient(Url);
InvoiceTest = ServiceConfigReader.GetInvoiceTestJsonString();
XRechnung = JsonConvert.DeserializeObject<XRechnung>(InvoiceTest);
}
[TestMethod]
public void SendRequest()
public void SendRequestInvoiceTestString()
{
var response = XRechnungSender.Send(XRechnung);
var response = ValidApiClient.Create(InvoiceTest);
Assert.IsFalse(response.HasErrors);
}
[TestMethod]
public void SendRequestXRechnungObject()
{
var response = ValidApiClient.Create(XRechnung);
Assert.IsFalse(response.HasErrors);
}
[TestMethod]
public void SendRequestInvoiceTestStringValidUrl()
{
var response = ValidApiClient.Create(InvoiceTest, ValidDownloadUrl);
Assert.IsFalse(response.HasErrors);
}
@@ -34,19 +68,7 @@ namespace XRechnungUnitTest
[TestMethod]
public void SendRequestValidUrl()
{
var url = "https://app5.bewoplaner.de/service/DownloadFile.aspx?key=jhkf4589141324h6543958";
var response = XRechnungSender.Send(XRechnung, url);
Assert.IsFalse(response.HasErrors);
}
[TestMethod]
public void SendRequestValidUrlEscape()
{
var url = Uri.EscapeDataString("https://app5.bewoplaner.de/service/DownloadFile.aspx?key=jhkf4589141324h6543958");
var response = XRechnungSender.Send(XRechnung, url);
var response = ValidApiClient.Create(XRechnung, ValidDownloadUrl);
Assert.IsFalse(response.HasErrors);
}
@@ -54,9 +76,7 @@ namespace XRechnungUnitTest
[TestMethod]
public void SendRequestInvalidUrl()
{
var url = "Hallo Mike!";
var response = XRechnungSender.Send(XRechnung, url);
var response = InvalidApiClient.Create(XRechnung, InvalidDownloadUrl);
Assert.IsTrue(response.HasErrors);
}