ZUGFeRD REST Service - ErrorCodes aus Exception abfangen, und mit dem Code den Text aus der Datenbank holen und anzeigen.

This commit is contained in:
2025-08-08 11:51:49 +02:00
parent aa3a798b24
commit 11d6157726
5 changed files with 205 additions and 59 deletions

View File

@@ -12,6 +12,7 @@ using System.Data.SqlClient;
using Microsoft.Extensions.Configuration;
using System.Xml.Linq;
using Newtonsoft.Json.Linq;
using System.Text.RegularExpressions;
namespace ZUGFeRDRESTService.Controllers
{
@@ -37,6 +38,7 @@ namespace ZUGFeRDRESTService.Controllers
private readonly PropertyValues _props;
//private readonly Dictionary<string, XmlItemProperty> _propertyMap = new Dictionary<string, XmlItemProperty>();
private readonly List<XmlItemProperty> _propertyMapList = new List<XmlItemProperty>();
private readonly List<RejectionStringRow> _RecjectionMessageList = new List<RejectionStringRow>();
private int _MaxFileSizeInMegabytes;
private bool _AllowFacturX;
@@ -79,6 +81,8 @@ namespace ZUGFeRDRESTService.Controllers
_propertyMapList.AddRange(oPropertyMapList);
_logger.Debug("Property Map list initial: [{0}] entries found. [{1}] entries will be available.", oPropertyMapList.Count, _propertyMapList.Count);
_RecjectionMessageList = database.GetRejectionMessageList();
_logger.Debug("Validation Controller initialized!");
}
@@ -89,32 +93,32 @@ namespace ZUGFeRDRESTService.Controllers
if (!bool.TryParse(oZugferdConfig["AllowFacturX"], out _AllowFacturX))
{
_logger.Info("Configuration AllowFacturX was not set. Using default value [{0}]", false);
_AllowFacturX = false;
_logger.Info("Configuration AllowFacturX was not set. Using default value [{0}]", true);
_AllowFacturX = true;
}
if (!bool.TryParse(oZugferdConfig["AllowXRechnung"], out _AllowXRechnung))
{
_logger.Info("Configuration AllowXRechnung was not set. Using default value [{0}]", false);
_AllowXRechnung = false;
_logger.Info("Configuration AllowXRechnung was not set. Using default value [{0}]", true);
_AllowXRechnung = true;
}
if (!bool.TryParse(oZugferdConfig["AllowZugferd2x"], out _AllowZugferd2x))
{
_logger.Info("Configuration Zugferd2x was not set. Using default value [{0}]", false);
_AllowZugferd2x = false;
_logger.Info("Configuration Zugferd2x was not set. Using default value [{0}]", true);
_AllowZugferd2x = true;
}
if (!bool.TryParse(oZugferdConfig["AllowZugferd23x"], out _AllowZugferd23x))
{
_logger.Info("Configuration Zugferd23x was not set. Using default value [{0}]", false);
_AllowZugferd23x = false;
_logger.Info("Configuration Zugferd23x was not set. Using default value [{0}]", true);
_AllowZugferd23x = true;
}
if (!bool.TryParse(oZugferdConfig["AllowZugferd10"], out _AllowZugferd10))
{
_logger.Info("Configuration Zugferd10 was not set. Using default value [{0}]", true);
_AllowZugferd10 = true;
_logger.Info("Configuration Zugferd10 was not set. Using default value [{0}]", false);
_AllowZugferd10 = false;
}
if (!bool.TryParse(oZugferdConfig["AllowPeppolBISBill3x"], out _AllowPeppolBISBill3x))
@@ -161,7 +165,8 @@ namespace ZUGFeRDRESTService.Controllers
if (oFileSizeIsOK == false)
{
throw new ZUGFeRDExecption(ErrorType.FileTooBig, "FileTooBig");
//throw new ZUGFeRDExecption(ErrorType.FileTooBig, "FileTooBig");
throw new ZUGFeRDExecption(ErrorCodes.FileSizeLimitReachedException, _MaxFileSizeInMegabytes.ToString(), string.Empty, "FileTooBig");
}
_logger.Info("Extracting ZUGFeRD Data from file [{0}]", file.FileName);
@@ -189,7 +194,8 @@ namespace ZUGFeRDRESTService.Controllers
if (oFilteredPropertyMap.Count == 0)
{
_logger.Warn("No properties found in property map for specification [{0}]", oZugferdResult.Specification);
throw new ZUGFeRDExecption(ErrorType.UnsupportedFormat, "Unsupported Format");
//throw new ZUGFeRDExecption(ErrorType.UnsupportedFormat, "Unsupported Format");
throw new ZUGFeRDExecption(ErrorCodes.UnsupportedFerdException, "Unsupported Format");
}
else
{
@@ -213,14 +219,16 @@ namespace ZUGFeRDRESTService.Controllers
if (oPropertyResult.MissingProperties.Count > 0)
{
throw new ZUGFeRDExecption(ErrorType.MissingProperties, "Missing Properties");
//throw new ZUGFeRDExecption(ErrorType.MissingProperties, "Missing Properties");
throw new ZUGFeRDExecption(ErrorCodes.MissingValueException, "Missing Properties");
}
Tuple<bool, string> oValidateResult = ValidateBuyerOrderReference(oPropertyResult.ValidProperties);
if (oValidateResult.Item1 == false)
{
throw new ZUGFeRDExecption(ErrorType.UnknownError, "Unknown Error");
//throw new ZUGFeRDExecption(ErrorType.UnknownError, "Unknown Error");
throw new ZUGFeRDExecption(ErrorCodes.UnhandledException, "Unknown Error");
}
string oValidateResultString = oValidateResult.Item2;
@@ -254,28 +262,46 @@ namespace ZUGFeRDRESTService.Controllers
{
_logger.Error(ex);
// Determine which message should be sent in the response
string oMessage = ex.ErrorType switch
{
ErrorType.NoValidFile => "Die hochgeladene Datei ist keine gültige Datei.",
ErrorType.NoZugferd => "Die hochgeladene Datei ist keine ZUGFeRD-Rechnung.",
ErrorType.NoValidZugferd => "Die hochgeladene Datei ist keine gültige ZUGFeRD-Rechnung.",
ErrorType.MissingProperties => "Die hochgeladene Datei ist keine gültige ZUGFeRD-Rechnung, es fehlen einige Metadaten.",
ErrorType.FileTooBig => string.Format("Die hochgeladene Datei überschreitet die zulässige Dateigröße [{0}].", _MaxFileSizeInMegabytes),
ErrorType.UnsupportedFormat => "Die hochgeladene Datei enthält ein falsches oder nicht unterstütztes ZUGFeRD Format.",
_ => "Die hochgeladene Datei kann nicht validiert werden.",
};
// Determine if any errors should be sent in the response
string oMessage;
var oErrors = new List<string>();
switch (ex.ErrorType)
if (ex.ErrorCode != ErrorCodes.NotInUse)
{
case ErrorType.MissingProperties:
oErrors.AddRange(from item in oPropertyResult.MissingProperties
select item.Description);
break;
default:
break;
var rejectionCodeNumber = this.GetRejectionCodeNumber(ex.ErrorCode);
// Der gesamte Ausgabetext muss anhand des ErrorCodes ermittelt werden
oMessage = this.GetRejectionMessage(rejectionCodeNumber);
// Ersetze jetzt die Platzhalter @REPLACE_PARAM1 und @REPLACE_PARAM2
if (!string.IsNullOrEmpty(ex.Param1) && oMessage.Contains("@REPLACE_PARAM1", StringComparison.OrdinalIgnoreCase))
{
oMessage = Regex.Replace(oMessage, "@REPLACE_PARAM1", ex.Param1, RegexOptions.IgnoreCase);
}
if (!string.IsNullOrEmpty(ex.Param2) && oMessage.Contains("@REPLACE_PARAM2", StringComparison.OrdinalIgnoreCase))
{
oMessage = Regex.Replace(oMessage, "@REPLACE_PARAM2", ex.Param2, RegexOptions.IgnoreCase);
}
// Der REJECTION-Code wird in alle Meldungen eingefügt.
if (!string.IsNullOrEmpty(rejectionCodeNumber) && oMessage.Contains("@REJECTION_CODE", StringComparison.OrdinalIgnoreCase))
{
oMessage = Regex.Replace(oMessage, "@REJECTION_CODE", "Ablehnungscode: " + rejectionCodeNumber, RegexOptions.IgnoreCase);
}
// Determine if any errors should be sent in the response
switch (ex.ErrorCode)
{
case ErrorCodes.MissingValueException:
oErrors.AddRange(from item in oPropertyResult.MissingProperties
select (item.EN16931_ID + "(" + item.Description + ")"));
break;
default:
break;
}
}
else
{
oMessage = "Alte Logik. Meldung nicht gefunden";
}
_logger.Info($"Responding with message: [{oMessage}]");
@@ -289,10 +315,14 @@ namespace ZUGFeRDRESTService.Controllers
}
catch (ValidationException ex)
{
string oMessage = "Die hochgeladene Datei enthält ungültige Werte.";
var rejectionCodeNumber = this.GetRejectionCodeNumber(ex.ErrorCode);
// Der gesamte Ausgabetext muss anhand des ErrorCodes ermittelt werden
string oMessage = this.GetRejectionMessage(rejectionCodeNumber);
List<string> oErrors = ex.ValidationErrors.Select(e =>
{
return $"Element '{e.ElementName}' mit Wert '{e.ElementValue}': {e.ErrorMessage}";
return $"Element '{e.ElementName}' mit Wert '{e.ElementValue}': {e.ErrorMessageDE}";
}).ToList();
return new ValidationResponse()
@@ -422,5 +452,61 @@ namespace ZUGFeRDRESTService.Controllers
}
}
/// <summary>
/// Ermittelt die Ausgabe-nachricht für einen Fehlercode
/// </summary>
public string GetRejectionMessage(string pErrorCode)
{
_logger.Info("GetRejectionMessage() - errorCode.ToString(): '" + pErrorCode.ToString() + "'");
if (_RecjectionMessageList == null) return string.Empty;
// Sprache wird man vielleicht mal auswählen können
var language = "de-DE";
var searchTitle = "ZUGFERD_Rejection_" + pErrorCode + "_Web";
var messageItem = _RecjectionMessageList.Where(i => i.Title.Equals(searchTitle, StringComparison.OrdinalIgnoreCase) && i.Language == language).FirstOrDefault();
if (messageItem != null)
{
_logger.Info("GetRejectionMessage() - messageItem: '" + messageItem.String1 + "'");
return messageItem.String1;
}
else
{
_logger.Info("GetRejectionMessage() - Es wurde kein passender Text gefunden.");
return string.Empty;
}
}
private string GetRejectionCodeNumber(ErrorCodes rejectionCode)
{
switch (rejectionCode)
{
case ErrorCodes.ValidationException:
return "20001";
case ErrorCodes.MD5HashException:
return "20002";
case ErrorCodes.UnsupportedFerdException:
return "20003";
case ErrorCodes.InvalidFerdException:
return "20004";
case ErrorCodes.TooMuchFerdsException:
return "20005";
case ErrorCodes.InvalidFerdNoXMLAttachmentFound:
return "20006";
case ErrorCodes.MissingValueException:
return "20007";
case ErrorCodes.FileSizeLimitReachedException:
return "20008";
case ErrorCodes.OutOfMemoryException:
return "20009";
case ErrorCodes.UnhandledException:
return "20010";
case ErrorCodes.FileMoveException:
return "20011";
default:
return "20010";
}
}
}
}