-Aggiunta dei servizi di connessione REST base, di SAP e di Salesforce

This commit is contained in:
Alessio Dal Santo
2025-06-16 17:42:55 +02:00
parent 7346db3b63
commit 53058e16a6
6 changed files with 858 additions and 1 deletions
@@ -1,6 +1,7 @@
using DataConnection.REST.Configuration;
using DataConnection.REST.Interfaces;
using DataConnection.REST.Models; // Added for metadata models
using Microsoft.EntityFrameworkCore.Storage.Json;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -9,6 +10,7 @@ using System.Net.Http;
using System.Net.Http.Headers;
using System.Net.Http.Json;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading;
using System.Threading.Tasks;
using System.Xml;
@@ -79,11 +81,19 @@ namespace DataConnection.REST.Implementations
public async Task<bool> LoginAsync(string companyDB, string userName, string password, CancellationToken cancellationToken = default)
{
var loginPayload = new { CompanyDB = companyDB, UserName = userName, Password = password };
var loginUri = "/b1s/v2/Login"; // Assuming v1, adjust if needed
var loginUri = "/b1s/v2/Login"; // Assuming v2, adjust if needed // --- Logging Aggiunto ---
var absoluteUri = _sapHttpClient.BaseAddress != null ? new Uri(_sapHttpClient.BaseAddress, loginUri).ToString() : loginUri;
Console.WriteLine($"--- SAP B1 Login Attempt ---");
Console.WriteLine($"Target URL: {absoluteUri}");
Console.WriteLine($"Payload: CompanyDB='{companyDB}', UserName='{userName}', Password='{(string.IsNullOrEmpty(password) ? "" : password.Substring(0, Math.Min(1, password.Length)) + "...")}'"); // Non loggare la password completa in produzione!
// Verifica se IgnoreSslErrors è attivo (preso dalle opzioni passate al costruttore)
Console.WriteLine($"Ignore SSL Errors: {_options.IgnoreSslErrors}");
// --- Fine Logging ---
try
{
// Use the internal HttpClient configured with CookieContainer
// Pass the loginPayload object directly, PostAsJsonAsync handles serialization
var response = await _sapHttpClient.PostAsJsonAsync(loginUri, loginPayload, cancellationToken);
if (!response.IsSuccessStatusCode)
@@ -92,6 +102,7 @@ namespace DataConnection.REST.Implementations
Console.WriteLine($"SAP B1 Login failed: {response.StatusCode}");
var errorContent = await response.Content.ReadAsStringAsync(cancellationToken);
Console.WriteLine($"Error details: {errorContent}");
Console.WriteLine($"--- End SAP B1 Login Attempt (Failed) ---"); // Log fine tentativo
return false;
}
@@ -107,6 +118,7 @@ namespace DataConnection.REST.Implementations
_sessionTimeout = DateTime.UtcNow.AddSeconds(sessionInfo.SessionTimeout);
Console.WriteLine($"SAP B1 Login successful. Session expires around: {_sessionTimeout.ToLocalTime()}");
Console.WriteLine($"--- End SAP B1 Login Attempt (Success) ---"); // Log fine tentativo
return true;
}
@@ -116,18 +128,30 @@ namespace DataConnection.REST.Implementations
catch (HttpRequestException ex)
{
Console.WriteLine($"HTTP Request Error during SAP B1 Login: {ex.Message}");
// Logga dettagli sull'eccezione interna se presente (spesso utile per problemi SSL)
if (ex.InnerException != null)
{
Console.WriteLine($"Inner Exception: {ex.InnerException.Message}");
}
Console.WriteLine($"--- End SAP B1 Login Attempt (Exception) ---"); // Log fine tentativo
return false;
}
catch (JsonException ex)
{
Console.WriteLine($"JSON Parsing Error during SAP B1 Login: {ex.Message}");
Console.WriteLine($"--- End SAP B1 Login Attempt (JsonException) ---"); // Log fine tentativo
return false;
}
catch (Exception ex)
{
Console.WriteLine($"Error during SAP B1 Login: {ex.Message}");
Console.WriteLine($"--- End SAP B1 Login Attempt (Exception) ---"); // Log fine tentativo
return false;
}
// finally // Aggiunto per sicurezza - Rimosso perchè non necessario qui
// {
// // Potrebbe essere utile loggare qui se necessario
// }
}
/// <summary>
@@ -276,6 +300,248 @@ namespace DataConnection.REST.Implementations
}
/// <summary>
/// Creates a new entity in SAP Business One using the Service Layer.
/// </summary>
/// <param name="entityName">The name of the entity to create (e.g., "Items", "BusinessPartners").</param>
/// <param name="entityData">The data for the new entity as key-value pairs.</param>
/// <param name="cancellationToken">Cancellation token.</param>
/// <returns>The created entity data or null if creation failed.</returns>
public override async Task<Dictionary<string, object>?> CreateEntityAsync(string entityName, Dictionary<string, object> entityData, CancellationToken cancellationToken = default)
{
// Ensure session is active before attempting creation
if (!IsSessionActive())
{
Console.WriteLine("Error: Not logged into SAP B1 Service Layer. Cannot create entity.");
return null;
}
// SAP B1 Service Layer typically uses plural entity names for endpoints
var createUri = $"/b1s/v2/{entityName}";
try
{ Console.WriteLine($"--- SAP B1 Entity Creation Attempt ---");
Console.WriteLine($"Entity: {entityName}");
Console.WriteLine($"Target URL: {(_sapHttpClient.BaseAddress != null ? new Uri(_sapHttpClient.BaseAddress, createUri) : createUri)}");
Console.WriteLine($"Data: {System.Text.Json.JsonSerializer.Serialize(entityData)}");
var response = await _sapHttpClient.PostAsJsonAsync(createUri, entityData, cancellationToken);
if (!response.IsSuccessStatusCode)
{
var errorContent = await response.Content.ReadAsStringAsync(cancellationToken);
Console.WriteLine($"SAP B1 Entity Creation failed: {response.StatusCode}");
Console.WriteLine($"Error details: {errorContent}");
Console.WriteLine($"--- End SAP B1 Entity Creation Attempt (Failed) ---");
return null;
}
var responseContent = await response.Content.ReadAsStringAsync(cancellationToken);
Console.WriteLine($"SAP B1 Entity Creation successful");
Console.WriteLine($"Response: {responseContent}");
Console.WriteLine($"--- End SAP B1 Entity Creation Attempt (Success) ---");
if (string.IsNullOrEmpty(responseContent))
return entityData; // Return original data if no response content
return System.Text.Json.JsonSerializer.Deserialize<Dictionary<string, object>>(responseContent);
}
catch (HttpRequestException ex)
{
Console.WriteLine($"HTTP Request Error during SAP B1 entity creation: {ex.Message}");
if (ex.InnerException != null)
{
Console.WriteLine($"Inner Exception: {ex.InnerException.Message}");
}
Console.WriteLine($"--- End SAP B1 Entity Creation Attempt (Exception) ---");
return null;
}
catch (JsonException ex)
{
Console.WriteLine($"JSON Parsing Error during SAP B1 entity creation: {ex.Message}");
Console.WriteLine($"--- End SAP B1 Entity Creation Attempt (JsonException) ---");
return null;
}
catch (Exception ex)
{
Console.WriteLine($"Error during SAP B1 entity creation: {ex.Message}");
Console.WriteLine($"--- End SAP B1 Entity Creation Attempt (Exception) ---");
return null;
}
}
/// <summary>
/// Discovers a list of available entities from SAP B1 Service Layer without detailed field information.
/// </summary>
/// <param name="cancellationToken">Cancellation token</param>
/// <returns>A list of discovered entity summaries</returns>
public async Task<List<RestEntitySummary>> DiscoverEntitySummariesAsync(CancellationToken cancellationToken = default)
{
if (!IsSessionActive())
{
Console.WriteLine("Error: Not logged into SAP B1 Service Layer. Cannot discover metadata.");
return new List<RestEntitySummary>();
}
var entities = new List<RestEntitySummary>();
var metadataUri = "/b1s/v2/$metadata";
try
{
var response = await _sapHttpClient.GetAsync(metadataUri, cancellationToken);
response.EnsureSuccessStatusCode();
var xmlContent = await response.Content.ReadAsStringAsync(cancellationToken);
var edmx = XDocument.Parse(xmlContent);
// Define XML namespaces
XNamespace edm = "http://schemas.microsoft.com/ado/2009/11/edm";
XNamespace edmxNs = "http://schemas.microsoft.com/ado/2007/06/edmx";
XNamespace defaultEdmNs = edmx.Root?.GetDefaultNamespace() ?? edm;
XNamespace dataServicesNs = edmx.Root?.Element(edmxNs + "DataServices")?.GetDefaultNamespace() ?? defaultEdmNs;
var schemaElement = edmx.Descendants(defaultEdmNs + "Schema").FirstOrDefault() ??
edmx.Descendants(dataServicesNs + "Schema").FirstOrDefault();
if (schemaElement == null)
{
Console.WriteLine("Error: Could not find Schema element in $metadata response.");
return entities;
}
// Find all EntityType elements within the Schema
foreach (var entityTypeElement in schemaElement.Elements(defaultEdmNs + "EntityType"))
{
var entityName = entityTypeElement.Attribute("Name")?.Value;
if (string.IsNullOrEmpty(entityName)) continue;
var entitySummary = new RestEntitySummary
{
Name = entityName,
Label = entityName, // SAP B1 typically doesn't have separate labels
IsCustom = entityName.StartsWith("U_", StringComparison.OrdinalIgnoreCase),
EntityType = "EntityType"
};
entities.Add(entitySummary);
}
}
catch (HttpRequestException ex)
{
Console.WriteLine($"HTTP Request Error during SAP B1 metadata discovery: {ex.Message}");
}
catch (XmlException ex)
{
Console.WriteLine($"XML Parsing Error during SAP B1 metadata discovery: {ex.Message}");
}
catch (Exception ex)
{
Console.WriteLine($"Error during SAP B1 metadata discovery: {ex.Message}");
}
return entities.OrderBy(e => e.Name).ToList();
}
/// <summary>
/// Discovers detailed information for a specific entity including all its properties.
/// </summary>
/// <param name="entityName">The name of the entity to get details for</param>
/// <param name="cancellationToken">Cancellation token</param>
/// <returns>Detailed entity information or null if not found</returns>
public async Task<RestEntityInfo?> DiscoverEntityDetailsAsync(string entityName, CancellationToken cancellationToken = default)
{
if (!IsSessionActive())
{
Console.WriteLine("Error: Not logged into SAP B1 Service Layer. Cannot discover entity details.");
return null;
}
var metadataUri = "/b1s/v2/$metadata";
try
{
var response = await _sapHttpClient.GetAsync(metadataUri, cancellationToken);
response.EnsureSuccessStatusCode();
var xmlContent = await response.Content.ReadAsStringAsync(cancellationToken);
var edmx = XDocument.Parse(xmlContent);
// Define XML namespaces
XNamespace edm = "http://schemas.microsoft.com/ado/2009/11/edm";
XNamespace edmxNs = "http://schemas.microsoft.com/ado/2007/06/edmx";
XNamespace defaultEdmNs = edmx.Root?.GetDefaultNamespace() ?? edm;
XNamespace dataServicesNs = edmx.Root?.Element(edmxNs + "DataServices")?.GetDefaultNamespace() ?? defaultEdmNs;
var schemaElement = edmx.Descendants(defaultEdmNs + "Schema").FirstOrDefault() ??
edmx.Descendants(dataServicesNs + "Schema").FirstOrDefault();
if (schemaElement == null)
{
Console.WriteLine("Error: Could not find Schema element in $metadata response.");
return null;
}
// Find the specific EntityType element
var entityTypeElement = schemaElement.Elements(defaultEdmNs + "EntityType")
.FirstOrDefault(e => e.Attribute("Name")?.Value == entityName);
if (entityTypeElement == null)
{
Console.WriteLine($"Error: Could not find EntityType '{entityName}' in $metadata response.");
return null;
}
var entityInfo = new RestEntityInfo
{
Name = entityName
};
// Find key properties for this entity type
var keyProperties = new HashSet<string>();
var keyElement = entityTypeElement.Element(defaultEdmNs + "Key");
if (keyElement != null)
{
foreach (var propRef in keyElement.Elements(defaultEdmNs + "PropertyRef"))
{
var keyName = propRef.Attribute("Name")?.Value;
if (!string.IsNullOrEmpty(keyName)) keyProperties.Add(keyName);
}
}
// Find properties for this entity type
foreach (var propertyElement in entityTypeElement.Elements(defaultEdmNs + "Property"))
{
var propName = propertyElement.Attribute("Name")?.Value;
if (string.IsNullOrEmpty(propName)) continue;
var propInfo = new RestPropertyInfo
{
Name = propName,
Type = propertyElement.Attribute("Type")?.Value ?? string.Empty,
IsKey = keyProperties.Contains(propName),
IsRequired = propertyElement.Attribute("Nullable")?.Value?.ToLower() == "false",
MaxLength = int.TryParse(propertyElement.Attribute("MaxLength")?.Value, out var maxLen) ? maxLen : null
};
entityInfo.Properties.Add(propInfo);
}
return entityInfo;
}
catch (HttpRequestException ex)
{
Console.WriteLine($"HTTP Request Error during SAP B1 entity details discovery: {ex.Message}");
}
catch (XmlException ex)
{
Console.WriteLine($"XML Parsing Error during SAP B1 entity details discovery: {ex.Message}");
}
catch (Exception ex)
{
Console.WriteLine($"Error during SAP B1 entity details discovery: {ex.Message}");
}
return null;
}
// Helper to get cookie value
private string? GetCookieValue(string cookieName)
{