Saxonite 1.2.11.4. BusinessMgr.
This commit is contained in:
@@ -5,16 +5,20 @@
|
|||||||
### Modules
|
### Modules
|
||||||
|
|
||||||
* NB All projects upgraded to .Net 6, 28Nov23.
|
* NB All projects upgraded to .Net 6, 28Nov23.
|
||||||
* SACS Standard Base
|
* **SACS Base**
|
||||||
* Base class library. .Net Standard 2.1. C#.
|
* C# Base class library, .Net6 (was .Net Standard 2.1).
|
||||||
* SACS Standard Dbas
|
* **SACS Dbas**
|
||||||
* Base database interface library. .Net Standard 2.1. C#.
|
* C# Base database interface library, .Net6 (was .Net Standard 2.1).
|
||||||
* SACS Standard Accounts
|
* **SACS Proc**
|
||||||
* Base Acounts system interface library. .Net Standard 2.1. C#.
|
* C# Base processes library, .Net6.
|
||||||
* SACS Standard Mob
|
* **SACS Maui**
|
||||||
* Base Mobile application library. .Net Standard 2.1. C#.
|
* C# Maui Mobile library, .Net6 (added Apr24).
|
||||||
* SACS Core Web
|
* **SACS Xamarin** (Apr24 SACS Standard Mob)
|
||||||
* Base Web application library. [C# .Net 6]
|
* C# Xamarin Mobile library, .Net6 (was .Net Standard 2.1).
|
||||||
* SACS Core Unit Tests
|
* **SACS Web**
|
||||||
* Unit Tests. [C# .Net 6]
|
* C# Base Web library, .Net 6.
|
||||||
|
* **SACS Accounts**
|
||||||
|
* C# Base Accounts system interface library, .Net6 (was .Net Standard 2.1).
|
||||||
|
* **SACS Unit Tests**
|
||||||
|
* C# Unit Tests, .Net 6.
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
<ProjectReference Include="..\SacsStandardAccounts\SacsStandardAccounts.csproj" />
|
<ProjectReference Include="..\SacsStandardAccounts\SacsStandardAccounts.csproj" />
|
||||||
<ProjectReference Include="..\SacsStandardBase\SacsStandardBase.csproj" />
|
<ProjectReference Include="..\SacsStandardBase\SacsStandardBase.csproj" />
|
||||||
<ProjectReference Include="..\SacsStandardDbas\SacsStandardDbas.csproj" />
|
<ProjectReference Include="..\SacsStandardDbas\SacsStandardDbas.csproj" />
|
||||||
|
<ProjectReference Include="..\SacsStandardProc\SacsStandardProc.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
using Sarand.Net.Standard.Base.Utils;
|
using Sarand.Net.Standard.Base.Utils;
|
||||||
|
|
||||||
@@ -43,6 +44,61 @@ namespace Sarand.UnitTests.Core.Base.Utils
|
|||||||
Assert.AreEqual(false, "Abc".IsBlank());
|
Assert.AreEqual(false, "Abc".IsBlank());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
// Regular Expression Matching.
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
[TestMethod]
|
||||||
|
public void StringUtil_Match()
|
||||||
|
{
|
||||||
|
// Match.
|
||||||
|
Assert.AreEqual(true, "ABCDEF".Match("CDE"));
|
||||||
|
Assert.AreEqual(true, "ABCDEF".MatchCI("cDe"));
|
||||||
|
Assert.AreEqual(true, "ABCDEF".Match("CDE", System.Text.RegularExpressions.RegexOptions.None));
|
||||||
|
Assert.AreEqual(true, "ABCDEF".Match(new Regex("CDE", System.Text.RegularExpressions.RegexOptions.None)));
|
||||||
|
Assert.AreEqual(true, "ABCDEF".Match(new Regex("cDe", System.Text.RegularExpressions.RegexOptions.IgnoreCase)));
|
||||||
|
|
||||||
|
// Match with escaped content.
|
||||||
|
Assert.AreEqual(true, "ABC\\sDEF".Match("\\\\s"));
|
||||||
|
Assert.AreEqual(true, "AB(CD)EF".Match("(..)"));
|
||||||
|
Assert.AreEqual(true, "AB(CD)EF".Match("\\(CD\\)"));
|
||||||
|
|
||||||
|
// Not match.
|
||||||
|
Assert.AreEqual(false, "ABCDEF".Match("cDe"));
|
||||||
|
Assert.AreEqual(false, "ABCDEF".MatchCI("eFg"));
|
||||||
|
Assert.AreEqual(false, "ABCDEF".Match("cDe", System.Text.RegularExpressions.RegexOptions.None));
|
||||||
|
Assert.AreEqual(false, "ABCDEF".Match(new Regex("cDe", System.Text.RegularExpressions.RegexOptions.None)));
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void StringUtil_IsMatch()
|
||||||
|
{
|
||||||
|
// IsMatch.
|
||||||
|
Assert.AreEqual(true, "ABCDEF".IsMatch("CDE"));
|
||||||
|
Assert.AreEqual(true, "ABCDEF".IsMatchCI("cDe"));
|
||||||
|
Assert.AreEqual(true, "ABCDEF".IsMatch("CDE", System.Text.RegularExpressions.RegexOptions.None));
|
||||||
|
Assert.AreEqual(true, "ABCDEF".IsMatch(new Regex("CDE", System.Text.RegularExpressions.RegexOptions.None)));
|
||||||
|
Assert.AreEqual(true, "ABCDEF".IsMatch(new Regex("cDe", System.Text.RegularExpressions.RegexOptions.IgnoreCase)));
|
||||||
|
|
||||||
|
// IsMatch with escaped content.
|
||||||
|
Assert.AreEqual(true, "ABC\\sDEF".IsMatch("\\\\s"));
|
||||||
|
Assert.AreEqual(true, "AB(CD)EF".IsMatch("(..)"));
|
||||||
|
Assert.AreEqual(true, "AB(CD)EF".IsMatch("\\(CD\\)"));
|
||||||
|
|
||||||
|
// Not match.
|
||||||
|
Assert.AreEqual(false, "ABCDEF".IsMatch("cDe"));
|
||||||
|
Assert.AreEqual(false, "ABCDEF".IsMatchCI("eFg"));
|
||||||
|
Assert.AreEqual(false, "ABCDEF".IsMatch("cDe", System.Text.RegularExpressions.RegexOptions.None));
|
||||||
|
Assert.AreEqual(false, "ABCDEF".IsMatch(new Regex("cDe", System.Text.RegularExpressions.RegexOptions.None)));
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void StringUtil_MatchCount()
|
||||||
|
{
|
||||||
|
// Match.
|
||||||
|
Assert.AreEqual(1, "ABCDEF".MatchCount(new Regex("CDE")));
|
||||||
|
Assert.AreEqual(2, "ABCDEFGHICDEJKL".MatchCount(new Regex("CDE")));
|
||||||
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// Padding.
|
// Padding.
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
using Sarand.Net.Standard.Proc.Excel;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Sacs.UnitTests.Net.Standard.Proc.Excel
|
||||||
|
{
|
||||||
|
[TestClass]
|
||||||
|
public class SaMsSpreadsheet_Tester
|
||||||
|
{
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
// Data members.
|
||||||
|
private Random random = new Random();
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
// GetPosForColId.
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
[TestMethod]
|
||||||
|
public void GetPosForColId_IsEmpty()
|
||||||
|
{
|
||||||
|
Assert.AreEqual(1, SaMsSpreadsheet.GetPosForColId("A"));
|
||||||
|
Assert.AreEqual(1, SaMsSpreadsheet.GetPosForColId("a"));
|
||||||
|
Assert.AreEqual(2, SaMsSpreadsheet.GetPosForColId("B"));
|
||||||
|
Assert.AreEqual(3, SaMsSpreadsheet.GetPosForColId("C"));
|
||||||
|
Assert.AreEqual(24, SaMsSpreadsheet.GetPosForColId("X"));
|
||||||
|
Assert.AreEqual(25, SaMsSpreadsheet.GetPosForColId("Y"));
|
||||||
|
Assert.AreEqual(26, SaMsSpreadsheet.GetPosForColId("Z"));
|
||||||
|
Assert.AreEqual(27, SaMsSpreadsheet.GetPosForColId("AA"));
|
||||||
|
Assert.AreEqual(28, SaMsSpreadsheet.GetPosForColId("AB"));
|
||||||
|
Assert.AreEqual(29, SaMsSpreadsheet.GetPosForColId("AC"));
|
||||||
|
Assert.AreEqual(128, SaMsSpreadsheet.GetPosForColId("DX"));
|
||||||
|
Assert.AreEqual(155, SaMsSpreadsheet.GetPosForColId("EY"));
|
||||||
|
Assert.AreEqual(182, SaMsSpreadsheet.GetPosForColId("FZ"));
|
||||||
|
|
||||||
|
// Invalid.
|
||||||
|
Assert.AreEqual(0, SaMsSpreadsheet.GetPosForColId(""));
|
||||||
|
Assert.AreEqual(0, SaMsSpreadsheet.GetPosForColId("1"));
|
||||||
|
Assert.AreEqual(0, SaMsSpreadsheet.GetPosForColId("A1"));
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -141,7 +141,7 @@ namespace Sacs.Web.Components
|
|||||||
//if (SacsSystem.DebugMode) SaLogger.Debug(SysUtil.Fn + "\n\tData: " + queryString + " \n\tEncrypted: " + encrypted);
|
//if (SacsSystem.DebugMode) SaLogger.Debug(SysUtil.Fn + "\n\tData: " + queryString + " \n\tEncrypted: " + encrypted);
|
||||||
return encrypted;
|
return encrypted;
|
||||||
}
|
}
|
||||||
catch (Exception exc) { SaLogger.Warn(SysUtil.Fn + " " + ExceptionUtil.GetErrorStateMessage(exc)); }
|
catch (Exception exc) { SaLogger.Warn($"{SysUtil.Fn} {ExceptionUtil.GetErrorStateMessage(exc)}"); }
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
public static NameValueCollection DecryptParameters(String encrypted, String base64IV, String base64Key)
|
public static NameValueCollection DecryptParameters(String encrypted, String base64IV, String base64Key)
|
||||||
@@ -253,10 +253,11 @@ namespace Sacs.Web.Components
|
|||||||
public class ItemData_Base
|
public class ItemData_Base
|
||||||
{
|
{
|
||||||
// Common item properties.
|
// Common item properties.
|
||||||
public String Id { get; set; }
|
public String Id { get; set; } = null;
|
||||||
public String Notes { get; set; }
|
private String notes;
|
||||||
public String StatusCode { get; set; }
|
public String Notes { get { return StringUtil.OnBlank(notes, null); } set { notes = StringUtil.EmptyOnNull(value).Trim(); } }
|
||||||
public String StatusDesc { get; set; }
|
public String StatusCode { get; set; } = null;
|
||||||
|
public String StatusDesc { get; set; } = null;
|
||||||
// Flags for common status values.
|
// Flags for common status values.
|
||||||
// Return true or null so that property is not serialised when false.
|
// Return true or null so that property is not serialised when false.
|
||||||
public bool? Awaiting { get { return StatusCode.EqualsCI(SacsSystem.GetStatusCode(SaStatus.Awaiting)) ? true : (bool?)null; } }
|
public bool? Awaiting { get { return StatusCode.EqualsCI(SacsSystem.GetStatusCode(SaStatus.Awaiting)) ? true : (bool?)null; } }
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ namespace Sarand.Net.Standard.Base.Core
|
|||||||
public abstract class SacsDisposable : IDisposable
|
public abstract class SacsDisposable : IDisposable
|
||||||
{
|
{
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// Data memebrs.
|
// Data members.
|
||||||
private bool disposed = false;
|
private bool disposed = false;
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
|
|||||||
@@ -626,7 +626,7 @@ namespace Sarand.Net.Standard.Base.Dbas
|
|||||||
{
|
{
|
||||||
if (bit > 0 && bit <= 32)
|
if (bit > 0 && bit <= 32)
|
||||||
{
|
{
|
||||||
// The operation depands on whether the value should be matched or not.
|
// The operation depends on whether the value should be matched or not.
|
||||||
String condition = (match? "<>" : "=");
|
String condition = (match? "<>" : "=");
|
||||||
// Test is achieved by shifting the value so as to drop the target bit, shift back one bit
|
// Test is achieved by shifting the value so as to drop the target bit, shift back one bit
|
||||||
// and identify those value that then do not match the original value shifted by one place less.
|
// and identify those value that then do not match the original value shifted by one place less.
|
||||||
@@ -727,7 +727,7 @@ namespace Sarand.Net.Standard.Base.Dbas
|
|||||||
{
|
{
|
||||||
// Must have an 'Order By' clause to use 'Offset ... Fetch Next ...'
|
// Must have an 'Order By' clause to use 'Offset ... Fetch Next ...'
|
||||||
if (orderByData.IsEmpty())
|
if (orderByData.IsEmpty())
|
||||||
throw new NotSupportedException("Query paging requires sort ofrder to be specified");
|
throw new NotSupportedException("Query paging requires sort order to be specified");
|
||||||
if (DbGlobalDbms.Type != DbmsType.MsSql)
|
if (DbGlobalDbms.Type != DbmsType.MsSql)
|
||||||
throw new NotSupportedException("Query paging only supported for MS SQL");
|
throw new NotSupportedException("Query paging only supported for MS SQL");
|
||||||
query += " OFFSET " + ((paging.PageNo - 1) * paging.PageLength) + " ROWS FETCH NEXT " + paging.PageLength + " ROWS ONLY";
|
query += " OFFSET " + ((paging.PageNo - 1) * paging.PageLength) + " ROWS FETCH NEXT " + paging.PageLength + " ROWS ONLY";
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
using Sarand.Net.Standard.Base.App;
|
using Microsoft.Net.Http.Headers;
|
||||||
|
using Sarand.Net.Standard.Base.App;
|
||||||
using Sarand.Net.Standard.Base.Core;
|
using Sarand.Net.Standard.Base.Core;
|
||||||
|
using Sarand.Net.Standard.Base.Net;
|
||||||
using Sarand.Net.Standard.Base.Tasks;
|
using Sarand.Net.Standard.Base.Tasks;
|
||||||
using Sarand.Net.Standard.Base.Utils;
|
using Sarand.Net.Standard.Base.Utils;
|
||||||
using System;
|
using System;
|
||||||
@@ -29,7 +31,7 @@ namespace Sarand.Net.Standard.Base.Helpers
|
|||||||
/// Request timeout. Default: 5 secs.
|
/// Request timeout. Default: 5 secs.
|
||||||
/// <para>NB Not currently supported as can only be changed when static HTTP Client not in use.</para>
|
/// <para>NB Not currently supported as can only be changed when static HTTP Client not in use.</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int TimeoutSecs { get; set; } = RequestTimeoutSecs_Default;
|
public int TimeoutSecs { get; set; } = SacsHttpClient.RequestTimeoutSecs_Default;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Headers to send with request.
|
/// Headers to send with request.
|
||||||
/// <para>Accept, Accept-Charset, Accept-Encoding, Accept-Language, User-Agent, Transfer-Encoding, Pragma, Expect etc.</para>
|
/// <para>Accept, Accept-Charset, Accept-Encoding, Accept-Language, User-Agent, Transfer-Encoding, Pragma, Expect etc.</para>
|
||||||
@@ -57,55 +59,28 @@ namespace Sarand.Net.Standard.Base.Helpers
|
|||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
/// <summary>Response data</summary>
|
/// <summary>Response data</summary>
|
||||||
public class ResponseData
|
public class ResponseData : SacsHttpResponseData
|
||||||
{
|
{
|
||||||
public DateTime RequestStarted { get; set; }
|
|
||||||
public DateTime RequestCompleted { get; set; }
|
|
||||||
/// <summary>Response headers.</summary>
|
|
||||||
public Dictionary<String, IEnumerable<String>> ResponseHeaders { get; } = new Dictionary<String, IEnumerable<String>>();
|
|
||||||
/// <summary>Response content headers.</summary>
|
|
||||||
public Dictionary<String, IEnumerable<String>> ContentHeaders { get; } = new Dictionary<String, IEnumerable<String>>();
|
|
||||||
/// <summary>Indicates whether Status Code represents success.</summary>
|
|
||||||
public bool Success { get; set; }
|
|
||||||
/// <summary>HTTP Status Code.</summary>
|
|
||||||
public HttpStatusCode StatusCode { get; set; }
|
|
||||||
/// <summary>HTTP message version. Default: 1.1</summary>
|
|
||||||
public Version Version { get; set; }
|
|
||||||
/// <summary>HTTP Reason Code.</summary>
|
|
||||||
public String ReasonPhrase { get; set; } = "";
|
|
||||||
/// <summary>Response data.</summary>
|
|
||||||
public String Data { get; set; } = "";
|
|
||||||
/// <summary>Elapsed time for request.</summary>
|
|
||||||
public TimeSpan Elapsed { get; set; }
|
|
||||||
/// <summary>Exception thrown during handling of request.</summary>
|
|
||||||
public Exception Exception { get; set; }
|
|
||||||
/// <summary>Error state message - generally exception type and message.</summary>
|
|
||||||
public String ErrorStateMessage { get; set; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// Data members.
|
// Data members.
|
||||||
private static readonly HttpClient httpClient;
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// Static initialisation.
|
// Static initialisation.
|
||||||
static SacsHttpClientHelper ()
|
static SacsHttpClientHelper()
|
||||||
{
|
{
|
||||||
// Configure client.
|
|
||||||
httpClient = new HttpClient();
|
|
||||||
httpClient.Timeout = new TimeSpan(0, 0, RequestTimeoutSecs_Default);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// Properties.
|
// Properties.
|
||||||
public static HttpClient HttpClient { get { return httpClient; } }
|
public static HttpClient HttpClient { get { return SacsHttpClient.HttpClient; } }
|
||||||
public static int RequestTimeoutSecs_Default { get; } = 5;
|
public static int RequestTimeoutSecs_Default { get { return SacsHttpClient.RequestTimeoutSecs_Default; } }
|
||||||
public static String HeaderName_ContentType { get; } = "Content-Type";
|
public static String HeaderName_ContentType { get {; return SacsHttpClient.HeaderName_ContentType; } }
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
public static async Task<ResponseData> DoRequest (RequestData requestData)
|
public static async Task<ResponseData> DoRequest(RequestData requestData)
|
||||||
{
|
{
|
||||||
String fn = "SacsHttpClientHelper.DoRequest";
|
|
||||||
requestData.ThrowIfCancellationRequested();
|
requestData.ThrowIfCancellationRequested();
|
||||||
ResponseData responseData = new ResponseData();
|
ResponseData responseData = new ResponseData();
|
||||||
|
|
||||||
@@ -114,14 +89,14 @@ namespace Sarand.Net.Standard.Base.Helpers
|
|||||||
if (requestData.FormData.Count > 0)
|
if (requestData.FormData.Count > 0)
|
||||||
{
|
{
|
||||||
postContent = new FormUrlEncodedContent(requestData.FormData);
|
postContent = new FormUrlEncodedContent(requestData.FormData);
|
||||||
if (!requestData.ContentHeaders.ContainsKey(HeaderName_ContentType))
|
if (!requestData.ContentHeaders.ContainsKey(SacsHttpClient.HeaderName_ContentType))
|
||||||
requestData.ContentHeaders.Add(HeaderName_ContentType, "application/x-www-form-urlencoded; charset=utf-8");
|
requestData.ContentHeaders.Add(SacsHttpClient.HeaderName_ContentType, "application/x-www-form-urlencoded; charset=utf-8");
|
||||||
}
|
}
|
||||||
else if (!StringUtil.IsEmpty(requestData.PostData) || requestData.ForcePost)
|
else if (!StringUtil.IsEmpty(requestData.PostData) || requestData.ForcePost)
|
||||||
{
|
{
|
||||||
postContent = new StringContent(StringUtil.EmptyOnNull(requestData.PostData), Encoding.UTF8);
|
postContent = new StringContent(StringUtil.EmptyOnNull(requestData.PostData), Encoding.UTF8);
|
||||||
if (!requestData.ContentHeaders.ContainsKey(HeaderName_ContentType))
|
if (!requestData.ContentHeaders.ContainsKey(SacsHttpClient.HeaderName_ContentType))
|
||||||
requestData.ContentHeaders.Add(HeaderName_ContentType, "text/plain; charset=utf-8");
|
requestData.ContentHeaders.Add(SacsHttpClient.HeaderName_ContentType, "text/plain; charset=utf-8");
|
||||||
}
|
}
|
||||||
requestData.ThrowIfCancellationRequested();
|
requestData.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
@@ -143,7 +118,7 @@ namespace Sarand.Net.Standard.Base.Helpers
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Default request headers.
|
// Default request headers.
|
||||||
if (HttpClient.DefaultRequestHeaders.Accept.Count == 0 && request.Headers.Accept.Count == 0)
|
if (SacsHttpClient.HttpClient.DefaultRequestHeaders.Accept.Count == 0 && request.Headers.Accept.Count == 0)
|
||||||
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("text/*"));
|
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("text/*"));
|
||||||
|
|
||||||
// Configure request.
|
// Configure request.
|
||||||
@@ -163,7 +138,7 @@ namespace Sarand.Net.Standard.Base.Helpers
|
|||||||
}
|
}
|
||||||
// Send request.
|
// Send request.
|
||||||
responseData.RequestStarted = DateTime.Now;
|
responseData.RequestStarted = DateTime.Now;
|
||||||
response = await HttpClient.SendAsync(request, requestData.CancellationToken);
|
response = await SacsHttpClient.HttpClient.SendAsync(request, requestData.CancellationToken);
|
||||||
responseData.RequestCompleted = DateTime.Now;
|
responseData.RequestCompleted = DateTime.Now;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -171,7 +146,7 @@ namespace Sarand.Net.Standard.Base.Helpers
|
|||||||
// GET.
|
// GET.
|
||||||
request.Method = HttpMethod.Get;
|
request.Method = HttpMethod.Get;
|
||||||
responseData.RequestStarted = DateTime.Now;
|
responseData.RequestStarted = DateTime.Now;
|
||||||
response = await HttpClient.SendAsync(request, requestData.CancellationToken);
|
response = await SacsHttpClient.HttpClient.SendAsync(request, requestData.CancellationToken);
|
||||||
responseData.RequestCompleted = DateTime.Now;
|
responseData.RequestCompleted = DateTime.Now;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -205,7 +180,7 @@ namespace Sarand.Net.Standard.Base.Helpers
|
|||||||
exc = exc.InnerException;
|
exc = exc.InnerException;
|
||||||
}
|
}
|
||||||
String msg = exc.GetType().Name + ": " + exc.Message;
|
String msg = exc.GetType().Name + ": " + exc.Message;
|
||||||
SaLogger.Warn(fn + " " + msg + ExceptionUtil.GetStackEntries(exc, 6).Concat("", "\n\t"));
|
SaLogger.Warn(SysUtil.Fn + " " + msg + ExceptionUtil.GetStackEntries(exc, 6).Concat("", "\n\t"));
|
||||||
responseData.ErrorStateMessage = msg;
|
responseData.ErrorStateMessage = msg;
|
||||||
}
|
}
|
||||||
requestData.ThrowIfCancellationRequested();
|
requestData.ThrowIfCancellationRequested();
|
||||||
@@ -218,33 +193,9 @@ namespace Sarand.Net.Standard.Base.Helpers
|
|||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// R e s p o n s e S t a t u s D e s c r i p t i o n
|
// R e s p o n s e S t a t u s D e s c r i p t i o n
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
public static String GetResponseStatusDescription (HttpStatusCode httpStatus)
|
public static String GetResponseStatusDescription(HttpStatusCode httpStatus)
|
||||||
{
|
{
|
||||||
// Ref. https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
|
return SacsHttpClient.GetResponseStatusDescription(httpStatus);
|
||||||
switch (httpStatus)
|
|
||||||
{
|
|
||||||
// 1xx: Informational - Request received, continuing process.
|
|
||||||
case HttpStatusCode.Continue: return "Continue";
|
|
||||||
// 2xx: Success - The action was successfully received, understood, and accepted.
|
|
||||||
case HttpStatusCode.OK: return "OK";
|
|
||||||
case HttpStatusCode.Created: return "Created";
|
|
||||||
case HttpStatusCode.Accepted: return "Accepted";
|
|
||||||
// 3xx: Redirection - Further action must be taken in order to complete the request.
|
|
||||||
case HttpStatusCode.MultipleChoices: return "Multiple choices";
|
|
||||||
case HttpStatusCode.MovedPermanently: return "Moved permanently";
|
|
||||||
case HttpStatusCode.Found: return "Found";
|
|
||||||
// 4xx: Client Error -The request contains bad syntax or cannot be fulfilled.
|
|
||||||
case HttpStatusCode.BadRequest: return "Bad request";
|
|
||||||
case HttpStatusCode.Unauthorized: return "Unauthorized";
|
|
||||||
case HttpStatusCode.PaymentRequired: return "Payment required";
|
|
||||||
case HttpStatusCode.Forbidden: return "Forbidden";
|
|
||||||
case HttpStatusCode.NotFound: return "Not found";
|
|
||||||
case HttpStatusCode.MethodNotAllowed: return "Method not allowed";
|
|
||||||
case HttpStatusCode.NotAcceptable: return "Not acceptable";
|
|
||||||
// 5xx: Server Error -The server failed to fulfill an apparently valid request.
|
|
||||||
case HttpStatusCode.InternalServerError: return "Internal server error";
|
|
||||||
}
|
|
||||||
return httpStatus.ToString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ namespace Sarand.Net.Standard.Base.Helpers
|
|||||||
private static Random random;
|
private static Random random;
|
||||||
public static Random Random { get { if (random == null) random = new Random(GetInt32(Int32.MaxValue)); return random; } }
|
public static Random Random { get { if (random == null) random = new Random(GetInt32(Int32.MaxValue)); return random; } }
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
public static void Fill(byte[] byteArray)
|
public static void Fill(byte[] byteArray)
|
||||||
{
|
{
|
||||||
RandomNumberGenerator.Fill(byteArray);
|
RandomNumberGenerator.Fill(byteArray);
|
||||||
|
|||||||
@@ -1,23 +1,31 @@
|
|||||||
using Sarand.Net.Standard.Base.App;
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.Net.Http.Headers;
|
||||||
|
using Sarand.Net.Standard.Base.App;
|
||||||
using Sarand.Net.Standard.Base.Core;
|
using Sarand.Net.Standard.Base.Core;
|
||||||
|
using Sarand.Net.Standard.Base.Helpers;
|
||||||
using Sarand.Net.Standard.Base.Tasks;
|
using Sarand.Net.Standard.Base.Tasks;
|
||||||
using Sarand.Net.Standard.Base.Utils;
|
using Sarand.Net.Standard.Base.Utils;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.IO.Compression;
|
||||||
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Net.Http.Headers;
|
using System.Net.Http.Headers;
|
||||||
|
using System.Reflection.Metadata;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using ZstdNet;
|
||||||
|
|
||||||
namespace Sarand.Net.Standard.Base.Net
|
namespace Sarand.Net.Standard.Base.Net
|
||||||
{
|
{
|
||||||
//=======================================================================
|
//=======================================================================
|
||||||
public class SacsHttpRequestData : SacsTaskData
|
public class SacsHttpRequestData : SacsTaskData
|
||||||
{
|
{
|
||||||
public SacsHttpRequestData (CancellationToken? cancellationToken) : base(cancellationToken) { }
|
public SacsHttpRequestData(CancellationToken? cancellationToken) : base(cancellationToken) { }
|
||||||
/// <summary>URL to send request to.</summary>
|
/// <summary>URL to send request to.</summary>
|
||||||
public String Url { get; set; }
|
public String Url { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -50,6 +58,21 @@ namespace Sarand.Net.Standard.Base.Net
|
|||||||
public bool ForcePost { get; set; }
|
public bool ForcePost { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//=======================================================================
|
||||||
|
public class SacsHttpCookieData
|
||||||
|
{
|
||||||
|
public String HeaderValue { get; set; }
|
||||||
|
public String Name { get; set; }
|
||||||
|
public String Value { get; set; }
|
||||||
|
public DateTime Expires { get; set; }
|
||||||
|
public long MaxAge { get; set; }
|
||||||
|
public String Path { get; set; }
|
||||||
|
public String Domain { get; set; }
|
||||||
|
public bool Secure { get; set; }
|
||||||
|
public bool HttpOnly { get; set; }
|
||||||
|
public Dictionary<string, string> Properties { get; } = new Dictionary<string, string>();
|
||||||
|
}
|
||||||
|
|
||||||
//=======================================================================
|
//=======================================================================
|
||||||
public class SacsHttpResponseData
|
public class SacsHttpResponseData
|
||||||
{
|
{
|
||||||
@@ -59,10 +82,14 @@ namespace Sarand.Net.Standard.Base.Net
|
|||||||
public Dictionary<String, IEnumerable<String>> ResponseHeaders { get; } = new Dictionary<String, IEnumerable<String>>();
|
public Dictionary<String, IEnumerable<String>> ResponseHeaders { get; } = new Dictionary<String, IEnumerable<String>>();
|
||||||
/// <summary>Response content headers.</summary>
|
/// <summary>Response content headers.</summary>
|
||||||
public Dictionary<String, IEnumerable<String>> ContentHeaders { get; } = new Dictionary<String, IEnumerable<String>>();
|
public Dictionary<String, IEnumerable<String>> ContentHeaders { get; } = new Dictionary<String, IEnumerable<String>>();
|
||||||
|
/// <summary>Response cookies from 'Set-Cookie' header.</summary>
|
||||||
|
public Dictionary<String, SacsHttpCookieData> Cookies { get; } = new Dictionary<string, SacsHttpCookieData>();
|
||||||
/// <summary>Indicates whether Status Code represents success.</summary>
|
/// <summary>Indicates whether Status Code represents success.</summary>
|
||||||
public bool Success { get; set; }
|
public bool Success { get; set; }
|
||||||
/// <summary>HTTP Status Code.</summary>
|
/// <summary>HTTP Status Code.</summary>
|
||||||
public HttpStatusCode StatusCode { get; set; }
|
public HttpStatusCode StatusCode { get; set; }
|
||||||
|
/// <summary>HTTP message version. Default: 1.1</summary>
|
||||||
|
public Version Version { get; set; }
|
||||||
/// <summary>HTTP Reason Code.</summary>
|
/// <summary>HTTP Reason Code.</summary>
|
||||||
public String ReasonPhrase { get; set; } = "";
|
public String ReasonPhrase { get; set; } = "";
|
||||||
/// <summary>Response data.</summary>
|
/// <summary>Response data.</summary>
|
||||||
@@ -80,26 +107,28 @@ namespace Sarand.Net.Standard.Base.Net
|
|||||||
{
|
{
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// Data members.
|
// Data members.
|
||||||
private static readonly HttpClient client;
|
private static readonly HttpClient httpClient;
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// Static initialisation.
|
// Static initialisation.
|
||||||
static SacsHttpClient ()
|
static SacsHttpClient()
|
||||||
{
|
{
|
||||||
// Configure client.
|
// Configure client.
|
||||||
client = new HttpClient();
|
httpClient = new HttpClient();
|
||||||
client.Timeout = new TimeSpan(0, 0, RequestTimeoutSecs_Default);
|
httpClient.Timeout = new TimeSpan(0, 0, RequestTimeoutSecs_Default);
|
||||||
|
ProductInfoHeaderValue productInfoHeaderValue = new ProductInfoHeaderValue("Saratoga", "1.2.3");
|
||||||
|
httpClient.DefaultRequestHeaders.UserAgent.Add(productInfoHeaderValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// Properties.
|
// Properties.
|
||||||
|
public static HttpClient HttpClient { get { return httpClient; } }
|
||||||
public static int RequestTimeoutSecs_Default { get; } = 5;
|
public static int RequestTimeoutSecs_Default { get; } = 5;
|
||||||
public static String HeaderName_ContentType { get; } = "Content-Type";
|
public static String HeaderName_ContentType { get; } = HeaderNames.ContentType;
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
public static async Task<SacsHttpResponseData> DoRequest (SacsHttpRequestData requestData)
|
public static async Task<SacsHttpResponseData> DoRequest(SacsHttpRequestData requestData)
|
||||||
{
|
{
|
||||||
String fn = "SacsHttpClient.DoRequest";
|
|
||||||
SacsHttpResponseData responseData = new SacsHttpResponseData();
|
SacsHttpResponseData responseData = new SacsHttpResponseData();
|
||||||
requestData.ThrowIfCancellationRequested();
|
requestData.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
@@ -109,13 +138,13 @@ namespace Sarand.Net.Standard.Base.Net
|
|||||||
{
|
{
|
||||||
postContent = new FormUrlEncodedContent(requestData.FormData);
|
postContent = new FormUrlEncodedContent(requestData.FormData);
|
||||||
if (!requestData.ContentHeaders.ContainsKey(HeaderName_ContentType))
|
if (!requestData.ContentHeaders.ContainsKey(HeaderName_ContentType))
|
||||||
requestData.ContentHeaders.Add(HeaderName_ContentType,"application/x-www-form-urlencoded; charset=utf-8");
|
requestData.ContentHeaders.Add(HeaderName_ContentType, "application/x-www-form-urlencoded; charset=utf-8");
|
||||||
}
|
}
|
||||||
else if (!StringUtil.IsEmpty(requestData.PostData) || requestData.ForcePost)
|
else if (!StringUtil.IsEmpty(requestData.PostData) || requestData.ForcePost)
|
||||||
{
|
{
|
||||||
postContent = new StringContent(StringUtil.EmptyOnNull(requestData.PostData), Encoding.UTF8);
|
postContent = new StringContent(StringUtil.EmptyOnNull(requestData.PostData), Encoding.UTF8);
|
||||||
if (!requestData.ContentHeaders.ContainsKey(HeaderName_ContentType))
|
if (!requestData.ContentHeaders.ContainsKey(HeaderName_ContentType))
|
||||||
requestData.ContentHeaders.Add(HeaderName_ContentType,"text/plain; charset=utf-8");
|
requestData.ContentHeaders.Add(HeaderName_ContentType, "text/plain; charset=utf-8");
|
||||||
}
|
}
|
||||||
requestData.ThrowIfCancellationRequested();
|
requestData.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
@@ -137,7 +166,7 @@ namespace Sarand.Net.Standard.Base.Net
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Default request headers.
|
// Default request headers.
|
||||||
if (client.DefaultRequestHeaders.Accept.Count == 0 && request.Headers.Accept.Count == 0)
|
if (httpClient.DefaultRequestHeaders.Accept.Count == 0 && request.Headers.Accept.Count == 0)
|
||||||
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("text/*"));
|
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("text/*"));
|
||||||
|
|
||||||
// Configure request.
|
// Configure request.
|
||||||
@@ -157,7 +186,7 @@ namespace Sarand.Net.Standard.Base.Net
|
|||||||
}
|
}
|
||||||
// Send request.
|
// Send request.
|
||||||
responseData.RequestStarted = DateTime.Now;
|
responseData.RequestStarted = DateTime.Now;
|
||||||
response = await client.SendAsync(request, requestData.CancellationToken);
|
response = await httpClient.SendAsync(request, requestData.CancellationToken);
|
||||||
responseData.RequestCompleted = DateTime.Now;
|
responseData.RequestCompleted = DateTime.Now;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -165,25 +194,61 @@ namespace Sarand.Net.Standard.Base.Net
|
|||||||
// GET.
|
// GET.
|
||||||
request.Method = HttpMethod.Get;
|
request.Method = HttpMethod.Get;
|
||||||
responseData.RequestStarted = DateTime.Now;
|
responseData.RequestStarted = DateTime.Now;
|
||||||
response = await client.SendAsync(request, requestData.CancellationToken);
|
response = await httpClient.SendAsync(request, requestData.CancellationToken);
|
||||||
responseData.RequestCompleted = DateTime.Now;
|
responseData.RequestCompleted = DateTime.Now;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract resopnse data.
|
// Extract response data.
|
||||||
|
responseData.Version = response.Version;
|
||||||
responseData.Success = response.IsSuccessStatusCode;
|
responseData.Success = response.IsSuccessStatusCode;
|
||||||
responseData.StatusCode = response.StatusCode;
|
responseData.StatusCode = response.StatusCode;
|
||||||
responseData.ReasonPhrase = response.ReasonPhrase;
|
responseData.ReasonPhrase = response.ReasonPhrase;
|
||||||
|
// Extract response headers.
|
||||||
if (response.Headers != null)
|
if (response.Headers != null)
|
||||||
{
|
{
|
||||||
foreach (var header in response.Headers)
|
foreach (var header in response.Headers)
|
||||||
responseData.ResponseHeaders[header.Key] = new List<String>(header.Value);
|
responseData.ResponseHeaders[header.Key] = new List<String>(header.Value);
|
||||||
}
|
}
|
||||||
|
// Extract response content headers.
|
||||||
if (response.Content != null && response.Content.Headers != null)
|
if (response.Content != null && response.Content.Headers != null)
|
||||||
{
|
{
|
||||||
foreach (var header in response.Content.Headers)
|
foreach (var header in response.Content.Headers)
|
||||||
responseData.ContentHeaders[header.Key] = new List<String>(header.Value);
|
responseData.ContentHeaders[header.Key] = new List<String>(header.Value);
|
||||||
}
|
}
|
||||||
responseData.Data = await response.Content.ReadAsStringAsync();
|
// Extract response cookies.
|
||||||
|
if (response.Headers.Contains(HeaderNames.SetCookie))
|
||||||
|
{
|
||||||
|
foreach (var cookieHeader in response.Headers.GetValues(HeaderNames.SetCookie))
|
||||||
|
{
|
||||||
|
SacsHttpCookieData cookie = ExtractCookieFromHeader(cookieHeader);
|
||||||
|
if (cookie != null && !StringUtil.IsBlank(cookie.Name))
|
||||||
|
responseData.Cookies.Add(cookie.Name, cookie);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Extract response payload.
|
||||||
|
var contentEncodings = responseData.ContentHeaders.GetValueOrDefault(HeaderNames.ContentEncoding, new List<String>());
|
||||||
|
using (var responseStream = await response.Content.ReadAsStreamAsync())
|
||||||
|
{
|
||||||
|
// Check if response needs to be decompressed, as directed by 'content-encoding' header.
|
||||||
|
Stream decompressedStream = null;
|
||||||
|
if (contentEncodings.ContainsCI("gzip"))
|
||||||
|
decompressedStream = new GZipStream(responseStream, CompressionMode.Decompress);
|
||||||
|
else if (contentEncodings.ContainsCI("deflate"))
|
||||||
|
decompressedStream = new DeflateStream(responseStream, CompressionMode.Decompress);
|
||||||
|
else if (contentEncodings.ContainsCI("br"))
|
||||||
|
decompressedStream = new BrotliStream(responseStream, CompressionMode.Decompress);
|
||||||
|
else if (contentEncodings.ContainsCI("zstd"))
|
||||||
|
decompressedStream = new DecompressionStream(responseStream);
|
||||||
|
|
||||||
|
// Read the response payload, decompressed if necessary.
|
||||||
|
using (var streamReader = new StreamReader(decompressedStream != null ? decompressedStream : responseStream))
|
||||||
|
responseData.Data = await streamReader.ReadToEndAsync();
|
||||||
|
|
||||||
|
// Clean-up.
|
||||||
|
if (decompressedStream != null)
|
||||||
|
decompressedStream.Dispose();
|
||||||
|
}
|
||||||
|
// Clean-up.
|
||||||
if (response != null) response.Dispose();
|
if (response != null) response.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -198,7 +263,7 @@ namespace Sarand.Net.Standard.Base.Net
|
|||||||
exc = exc.InnerException;
|
exc = exc.InnerException;
|
||||||
}
|
}
|
||||||
String msg = exc.GetType().Name + ": " + exc.Message;
|
String msg = exc.GetType().Name + ": " + exc.Message;
|
||||||
SaLogger.Warn(fn + " " + msg + ExceptionUtil.GetStackEntries(exc, 6).Concat("", "\n\t"));
|
SaLogger.Warn(SysUtil.Fn + " " + msg + ExceptionUtil.GetStackEntries(exc, 6).Concat("", "\n\t"));
|
||||||
responseData.ErrorStateMessage = msg;
|
responseData.ErrorStateMessage = msg;
|
||||||
}
|
}
|
||||||
requestData.ThrowIfCancellationRequested();
|
requestData.ThrowIfCancellationRequested();
|
||||||
@@ -208,10 +273,57 @@ namespace Sarand.Net.Standard.Base.Net
|
|||||||
return responseData;
|
return responseData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
// Cookies.
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
public static SacsHttpCookieData ExtractCookieFromHeader(String cookieHeader)
|
||||||
|
{
|
||||||
|
SacsHttpCookieData cookie = null;
|
||||||
|
String[] cookieParts = cookieHeader.Split(';');
|
||||||
|
if (cookieParts.Count() > 1)
|
||||||
|
{
|
||||||
|
cookie = new SacsHttpCookieData();
|
||||||
|
cookie.HeaderValue = cookieHeader;
|
||||||
|
// Name and value.
|
||||||
|
String[] cookieNameValue = cookieParts[0].Trim().Split(new char[] { '=' }, 2);
|
||||||
|
cookie.Name = cookieNameValue[0].Trim();
|
||||||
|
cookie.Value = cookieNameValue.Count() > 1 ? cookieNameValue[1].Trim() : "";
|
||||||
|
// Other properties.
|
||||||
|
for (int i = 1; i < cookieParts.Length; i++)
|
||||||
|
{
|
||||||
|
string[] properties = cookieParts[i].Trim().Split(new char[] { '=' }, 2);
|
||||||
|
String propertyName = properties[0].Trim();
|
||||||
|
String propertyValue = properties.Count() > 1 ? properties[1].Trim() : "True";
|
||||||
|
cookie.Properties.Add(propertyName, propertyValue);
|
||||||
|
if (propertyName.EqualsCI("Domain"))
|
||||||
|
cookie.Domain = propertyValue;
|
||||||
|
else if (propertyName.EqualsCI("Path"))
|
||||||
|
cookie.Path = propertyValue;
|
||||||
|
else if (propertyName.EqualsCI("Expires"))
|
||||||
|
{
|
||||||
|
cookie.Expires = DateUtil.ParseExact(propertyValue, "ddd, d MMM yyyy HH:mm:ss GMT");
|
||||||
|
if (!DateUtil.IsValid(cookie.Expires))
|
||||||
|
{
|
||||||
|
DateTime expires;
|
||||||
|
DateTime.TryParse(propertyValue, CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal, out expires);
|
||||||
|
cookie.Expires = expires;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (propertyName.EqualsCI("Max-Age"))
|
||||||
|
cookie.MaxAge = StringUtil.ToLong(propertyValue);
|
||||||
|
else if (propertyName.EqualsCI("Secure"))
|
||||||
|
cookie.Secure = StringUtil.ToBool(propertyValue);
|
||||||
|
else if (propertyName.EqualsCI("HttpOnly"))
|
||||||
|
cookie.HttpOnly = StringUtil.ToBool(propertyValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cookie;
|
||||||
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// R e s p o n s e S t a t u s D e s c r i p t i o n
|
// R e s p o n s e S t a t u s D e s c r i p t i o n
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
public static String GetResponseStatusDescription (HttpStatusCode httpStatus)
|
public static String GetResponseStatusDescription(HttpStatusCode httpStatus)
|
||||||
{
|
{
|
||||||
// Ref. https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
|
// Ref. https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
|
||||||
switch (httpStatus)
|
switch (httpStatus)
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Sarand.Net.Standard.Base.Core;
|
using Org.BouncyCastle.Asn1.Ocsp;
|
||||||
|
using Sarand.Net.Standard.Base.Core;
|
||||||
using Sarand.Net.Standard.Base.Utils;
|
using Sarand.Net.Standard.Base.Utils;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@@ -13,13 +14,13 @@ namespace Sarand.Net.Standard.Base.Net
|
|||||||
// H T M L E n c o d i n g
|
// H T M L E n c o d i n g
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
/// <summary>Converts a string to an HTML-encoded string.</summary>
|
/// <summary>Converts a string to an HTML-encoded string.</summary>
|
||||||
public static String HtmlEncode (this String value)
|
public static String HtmlEncode(this String value)
|
||||||
{
|
{
|
||||||
if (StringUtil.IsEmpty(value)) return value;
|
if (StringUtil.IsEmpty(value)) return value;
|
||||||
return WebUtility.HtmlEncode(value);
|
return WebUtility.HtmlEncode(value);
|
||||||
}
|
}
|
||||||
/// <summary>Converts a string that has been HTML-encoded for HTTP transmission into a decoded string.</summary>
|
/// <summary>Converts a string that has been HTML-encoded for HTTP transmission into a decoded string.</summary>
|
||||||
public static String HtmlDecode (this String value)
|
public static String HtmlDecode(this String value)
|
||||||
{
|
{
|
||||||
if (StringUtil.IsEmpty(value)) return value;
|
if (StringUtil.IsEmpty(value)) return value;
|
||||||
return WebUtility.HtmlDecode(value);
|
return WebUtility.HtmlDecode(value);
|
||||||
@@ -29,18 +30,64 @@ namespace Sarand.Net.Standard.Base.Net
|
|||||||
// U R L E n c o d i n g
|
// U R L E n c o d i n g
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
/// <summary>Converts a string to an HTML-encoded string.</summary>
|
/// <summary>Converts a string to an HTML-encoded string.</summary>
|
||||||
public static String UrlEncode (this String value)
|
public static String UrlEncode(this String value)
|
||||||
{
|
{
|
||||||
if (StringUtil.IsEmpty(value)) return value;
|
if (StringUtil.IsEmpty(value)) return value;
|
||||||
return WebUtility.UrlEncode(value);
|
return WebUtility.UrlEncode(value);
|
||||||
}
|
}
|
||||||
/// <summary>Converts a string that has been HTML-encoded for HTTP transmission into a decoded string.</summary>
|
/// <summary>Converts a string that has been HTML-encoded for HTTP transmission into a decoded string.</summary>
|
||||||
public static String UrlDecode (this String value)
|
public static String UrlDecode(this String value)
|
||||||
{
|
{
|
||||||
if (StringUtil.IsEmpty(value)) return value;
|
if (StringUtil.IsEmpty(value)) return value;
|
||||||
return WebUtility.UrlDecode(value);
|
return WebUtility.UrlDecode(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
// URI Builder.
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Configure HTTP URI builder.
|
||||||
|
/// </summary>
|
||||||
|
public static UriBuilder ConfigureUriBuilder(this UriBuilder uriBuilder, String host, String path, String query = null)
|
||||||
|
{
|
||||||
|
uriBuilder.Scheme = "http";
|
||||||
|
uriBuilder.Host = StringUtil.OnBlank(host);
|
||||||
|
uriBuilder.Path = StringUtil.OnBlank(path);
|
||||||
|
uriBuilder.Query = StringUtil.OnBlank(query);
|
||||||
|
return uriBuilder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create HTTP URI builder.
|
||||||
|
/// </summary>
|
||||||
|
public static UriBuilder CreateUriBuilder(String host, String path, String query = null)
|
||||||
|
{
|
||||||
|
UriBuilder uriBuilder = new UriBuilder();
|
||||||
|
return uriBuilder.ConfigureUriBuilder(host, path, query);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Configure HTTPS URI builder.
|
||||||
|
/// </summary>
|
||||||
|
public static UriBuilder ConfigureSslUriBuilder(this UriBuilder uriBuilder, String host, String path, String query = null)
|
||||||
|
{
|
||||||
|
uriBuilder.Scheme = "https";
|
||||||
|
uriBuilder.Port = 443;
|
||||||
|
uriBuilder.Host = StringUtil.OnBlank(host);
|
||||||
|
uriBuilder.Path = StringUtil.OnBlank(path);
|
||||||
|
uriBuilder.Query = StringUtil.OnBlank(query);
|
||||||
|
return uriBuilder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create HTTPS URI builder.
|
||||||
|
/// </summary>
|
||||||
|
public static UriBuilder CreateSslUriBuilder(String host, String path, String query = null)
|
||||||
|
{
|
||||||
|
UriBuilder uriBuilder = new UriBuilder();
|
||||||
|
return uriBuilder.ConfigureSslUriBuilder(host, path, query);
|
||||||
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ namespace Sarand.Net.Standard.Base.Tasks
|
|||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// Data members.
|
// Data members.
|
||||||
// Cancellation token source - allows task cancellation to be triggered
|
// Cancellation token source - allows task cancellation to be triggered
|
||||||
// if the cancellation tokden wasn't supplied on construction.
|
// if the cancellation token wasn't supplied on construction.
|
||||||
private CancellationTokenSource cancellationTokenSource = null;
|
private CancellationTokenSource cancellationTokenSource = null;
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
|
|||||||
@@ -59,9 +59,12 @@ namespace Sarand.Net.Standard.Base.Utils
|
|||||||
public static List<String> GetStackEntries(this Exception exc, int entries = 0)
|
public static List<String> GetStackEntries(this Exception exc, int entries = 0)
|
||||||
{
|
{
|
||||||
List<String> stackEntries = new List<string>();
|
List<String> stackEntries = new List<string>();
|
||||||
stackEntries.AddRange(exc.StackTrace.Split(new String[] { "\r\n" }, (entries > 0 ? entries : 999), StringSplitOptions.None));
|
if (exc.StackTrace != null)
|
||||||
for (int idx = 0; idx < stackEntries.Count; idx++)
|
{
|
||||||
stackEntries[idx] = stackEntries[idx].Replace(" at ", "");
|
stackEntries.AddRange(exc.StackTrace.Split(new String[] { "\r\n" }, (entries > 0 ? entries : 999), StringSplitOptions.None));
|
||||||
|
for (int idx = 0; idx < stackEntries.Count; idx++)
|
||||||
|
stackEntries[idx] = stackEntries[idx].Replace(" at ", "");
|
||||||
|
}
|
||||||
return stackEntries;
|
return stackEntries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ namespace Sarand.Net.Standard.Base.Utils
|
|||||||
public static class ListUtil
|
public static class ListUtil
|
||||||
{
|
{
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
public static void ClearAndDispose<T> (this IList<T> values) where T : IDisposable
|
public static void ClearAndDispose<T>(this IList<T> values) where T : IDisposable
|
||||||
{
|
{
|
||||||
while (values.Count > 0)
|
while (values.Count > 0)
|
||||||
{
|
{
|
||||||
@@ -50,7 +50,12 @@ namespace Sarand.Net.Standard.Base.Utils
|
|||||||
/// <summary>Unique values only - ignores number of instances of each value.</summary>
|
/// <summary>Unique values only - ignores number of instances of each value.</summary>
|
||||||
UniqueValuesOnly = 0x02,
|
UniqueValuesOnly = 0x02,
|
||||||
}
|
}
|
||||||
public static bool Equals<T> (this IList<T> sourceList, IList<T> targetList, Equality equality)
|
/// <summary>
|
||||||
|
/// Compare content of two lists.
|
||||||
|
/// <para>- Exact ensures precise number and sequence of elements.</para>
|
||||||
|
/// <para>- Unique allows any number and sequence as long as each item is present in both lists.</para>
|
||||||
|
/// </summary>
|
||||||
|
public static bool Equals<T>(this IList<T> sourceList, IList<T> targetList, Equality equality)
|
||||||
{
|
{
|
||||||
bool sameLength = (sourceList.Count == targetList.Count);
|
bool sameLength = (sourceList.Count == targetList.Count);
|
||||||
if (equality == Equality.Exact)
|
if (equality == Equality.Exact)
|
||||||
@@ -69,6 +74,22 @@ namespace Sarand.Net.Standard.Base.Utils
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
/// Remove the specified range of items from the list to a new list.
|
||||||
|
/// </summary>
|
||||||
|
public static List<T> ExtractRange<T>(this List<T> values, int index, int count)
|
||||||
|
{
|
||||||
|
List<T> extractedValues = new List<T>();
|
||||||
|
if (values.Any())
|
||||||
|
{
|
||||||
|
count = Math.Min(values.Count(), count);
|
||||||
|
extractedValues.AddRange(values.GetRange(index, count));
|
||||||
|
values.RemoveRange(index, count);
|
||||||
|
}
|
||||||
|
return extractedValues;
|
||||||
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
}
|
}
|
||||||
//=======================================================================
|
//=======================================================================
|
||||||
|
|||||||
@@ -0,0 +1,90 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
|
namespace Sarand.Net.Standard.Base.Utils
|
||||||
|
{
|
||||||
|
//=======================================================================
|
||||||
|
public static class NewtonsoftJsonUtil
|
||||||
|
{
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
// Extracting.
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
// Parsing.
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
|
||||||
|
/// <summary>Parse data as JSON Token.</summary>
|
||||||
|
public static JToken ParseJsonToken(string jsonData)
|
||||||
|
{
|
||||||
|
return JToken.Parse(jsonData);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Parse data as JSON Token.</summary>
|
||||||
|
public static JToken ParseJsonToken(string jsonData, out Exception excOut)
|
||||||
|
{
|
||||||
|
excOut = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return JToken.Parse(jsonData);
|
||||||
|
}
|
||||||
|
catch (Exception exc)
|
||||||
|
{
|
||||||
|
excOut = exc;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
|
||||||
|
/// <summary>Parse data as JSON Object.</summary>
|
||||||
|
public static JObject ParseJsonObject(string jsonData)
|
||||||
|
{
|
||||||
|
return JObject.Parse(jsonData);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Parse data as JSON Object.</summary>
|
||||||
|
public static JObject ParseJsonObject(string jsonData, out Exception excOut)
|
||||||
|
{
|
||||||
|
excOut = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return JObject.Parse(jsonData);
|
||||||
|
}
|
||||||
|
catch (Exception exc)
|
||||||
|
{
|
||||||
|
excOut = exc;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
/// <summary>Parse data as JSON Object.</summary>
|
||||||
|
public static JArray ParseJsonArray(string jsonData)
|
||||||
|
{
|
||||||
|
return JArray.Parse(jsonData);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Parse data as JSON Object.</summary>
|
||||||
|
public static JArray ParseJsonArray(string jsonData, out Exception excOut)
|
||||||
|
{
|
||||||
|
excOut = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return JArray.Parse(jsonData);
|
||||||
|
}
|
||||||
|
catch (Exception exc)
|
||||||
|
{
|
||||||
|
excOut = exc;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
}
|
||||||
|
//=======================================================================
|
||||||
|
}
|
||||||
@@ -66,7 +66,7 @@ namespace Sarand.Net.Standard.Base.Utils
|
|||||||
// Regular expressions.
|
// Regular expressions.
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create Regex from (quoted) expression and apply Regex.Match to String value and return Match.Success.
|
/// Apply Regex.Match to String value and return Match.Success.
|
||||||
/// <para>- Case sensitive.</para>
|
/// <para>- Case sensitive.</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static bool Match(this String value, String expression)
|
public static bool Match(this String value, String expression)
|
||||||
@@ -74,7 +74,7 @@ namespace Sarand.Net.Standard.Base.Utils
|
|||||||
return value.Match(expression, RegexOptions.None);
|
return value.Match(expression, RegexOptions.None);
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create Regex from (quoted) expression and apply Regex.Match to String value and return Match.Success.
|
/// Apply Regex.Match to String value and return Match.Success, ignoring case.
|
||||||
/// <para>- Case insensitive.</para>
|
/// <para>- Case insensitive.</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static bool MatchCI(this String value, String expression)
|
public static bool MatchCI(this String value, String expression)
|
||||||
@@ -82,12 +82,11 @@ namespace Sarand.Net.Standard.Base.Utils
|
|||||||
return value.Match(expression, RegexOptions.IgnoreCase);
|
return value.Match(expression, RegexOptions.IgnoreCase);
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create Regex from (quoted) expression and apply Regex.Match to String value and return Match.Success.
|
/// Apply Regex.Match to String value and return Match.Success.
|
||||||
/// <para>- Supply options as required.</para>
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static bool Match(this String value, String expression, RegexOptions options)
|
public static bool Match(this String value, String expression, RegexOptions options)
|
||||||
{
|
{
|
||||||
return new Regex(Regex.Escape(expression), options).Match(value).Success;
|
return Regex.Match(value, expression, options).Success;
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Apply Regex.Match to String value and return Match.Success.
|
/// Apply Regex.Match to String value and return Match.Success.
|
||||||
@@ -96,12 +95,67 @@ namespace Sarand.Net.Standard.Base.Utils
|
|||||||
{
|
{
|
||||||
return re.Match(value).Success;
|
return re.Match(value).Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Apply Regex.Matches to String value and return true if any matches found.
|
/// Apply Regex.IsMatch to String value.
|
||||||
|
/// <para>- Case sensitive.</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static bool Matches(this String value, Regex re)
|
public static bool IsMatch(this String value, String expression)
|
||||||
{
|
{
|
||||||
return re.Matches(value).Count < 1;
|
return value.IsMatch(expression, RegexOptions.None);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Apply Regex.IsMatch to String value, ignoring case.
|
||||||
|
/// <para>- Case insensitive.</para>
|
||||||
|
/// </summary>
|
||||||
|
public static bool IsMatchCI(this String value, String expression)
|
||||||
|
{
|
||||||
|
return value.IsMatch(new Regex(Regex.Escape(expression), RegexOptions.IgnoreCase));
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Apply Regex.IsMatch to String value.
|
||||||
|
/// </summary>
|
||||||
|
public static bool IsMatch(this String value, String expression, RegexOptions options)
|
||||||
|
{
|
||||||
|
return Regex.IsMatch(value, expression, options);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Apply Regex.IsMatch to String value.
|
||||||
|
/// </summary>
|
||||||
|
public static bool IsMatch(this String value, Regex re)
|
||||||
|
{
|
||||||
|
return re.IsMatch(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Apply Regex.Matches to String value and return number of matches found.
|
||||||
|
/// <para>- Case sensitive.</para>
|
||||||
|
/// </summary>
|
||||||
|
public static int MatchCount(this String value, String expression)
|
||||||
|
{
|
||||||
|
return value.MatchCount(expression, RegexOptions.None);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Apply Regex.Matches to String value and return number of matches found.
|
||||||
|
/// <para>- Case insensitive.</para>
|
||||||
|
/// </summary>
|
||||||
|
public static int MatchCountCI(this String value, String expression)
|
||||||
|
{
|
||||||
|
return value.MatchCount(expression, RegexOptions.IgnoreCase);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Apply Regex.Matches to String value and return number of matches found.
|
||||||
|
/// </summary>
|
||||||
|
public static int MatchCount(this String value, String expression, RegexOptions options)
|
||||||
|
{
|
||||||
|
return Regex.Matches(value, expression, options).Count;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Apply Regex.Matches to String value and return number of matches found.
|
||||||
|
/// </summary>
|
||||||
|
public static int MatchCount(this String value, Regex re)
|
||||||
|
{
|
||||||
|
return re.Matches(value).Count;
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
|
|||||||
@@ -1,45 +0,0 @@
|
|||||||
using Sarand.Net.Standard.Base.Core;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Net;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace Sarand.Net.Standard.Base.Utils
|
|
||||||
{
|
|
||||||
public static class WebUtil
|
|
||||||
{
|
|
||||||
//-------------------------------------------------------------------
|
|
||||||
// H T M L E n c o d i n g
|
|
||||||
//-------------------------------------------------------------------
|
|
||||||
/// <summary>Converts a string to an HTML-encoded string.</summary>
|
|
||||||
public static String HtmlEncode (this String value)
|
|
||||||
{
|
|
||||||
if (StringUtil.IsEmpty(value)) return value;
|
|
||||||
return WebUtility.HtmlEncode(value);
|
|
||||||
}
|
|
||||||
/// <summary>Converts a string that has been HTML-encoded for HTTP transmission into a decoded string.</summary>
|
|
||||||
public static String HtmlDecode (this String value)
|
|
||||||
{
|
|
||||||
if (StringUtil.IsEmpty(value)) return value;
|
|
||||||
return WebUtility.HtmlDecode(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
|
||||||
// U R L E n c o d i n g
|
|
||||||
//-------------------------------------------------------------------
|
|
||||||
/// <summary>Converts a string to an HTML-encoded string.</summary>
|
|
||||||
public static String UrlEncode (this String value)
|
|
||||||
{
|
|
||||||
if (StringUtil.IsEmpty(value)) return value;
|
|
||||||
return WebUtility.UrlEncode(value);
|
|
||||||
}
|
|
||||||
/// <summary>Converts a string that has been HTML-encoded for HTTP transmission into a decoded string.</summary>
|
|
||||||
public static String UrlDecode (this String value)
|
|
||||||
{
|
|
||||||
if (StringUtil.IsEmpty(value)) return value;
|
|
||||||
return WebUtility.UrlDecode(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -7,11 +7,12 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="CsvHelper" Version="19.0.0" />
|
<PackageReference Include="CsvHelper" Version="19.0.0" />
|
||||||
<PackageReference Include="MailKit" Version="4.5.0" />
|
<PackageReference Include="MailKit" Version="4.6.0" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Http" Version="2.2.2" />
|
<PackageReference Include="Microsoft.AspNetCore.Http" Version="2.2.2" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.2.0" />
|
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.2.0" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||||
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.4" />
|
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.4" />
|
||||||
|
<PackageReference Include="ZstdNet" Version="1.4.5" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ namespace Sarand.Net.Standard.Dbas.Base
|
|||||||
{
|
{
|
||||||
VS2017,
|
VS2017,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Visual Studio 2019 version. StringListUtil rather than StringListUtil.
|
/// Visual Studio 2019 version. StringListUtil rather than StringList.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
VS2019
|
VS2019
|
||||||
}
|
}
|
||||||
@@ -36,7 +36,7 @@ namespace Sarand.Net.Standard.Dbas.Base
|
|||||||
}
|
}
|
||||||
public class Config
|
public class Config
|
||||||
{
|
{
|
||||||
public SarandCommonVersion SarandCommonVersion { get; set; } = SarandCommonVersion.VS2017;
|
public SarandCommonVersion SarandCommonVersion { get; set; } = SarandCommonVersion.VS2019;
|
||||||
public DotNetVersion DotNetVersion { get; set; } = DotNetVersion.Framework;
|
public DotNetVersion DotNetVersion { get; set; } = DotNetVersion.Framework;
|
||||||
public SacsDatabase Database { get; set; }
|
public SacsDatabase Database { get; set; }
|
||||||
public Dbms DbmsOutput { get; set; } = Dbms.ODBC;
|
public Dbms DbmsOutput { get; set; } = Dbms.ODBC;
|
||||||
@@ -46,10 +46,12 @@ namespace Sarand.Net.Standard.Dbas.Base
|
|||||||
public class SchemaData
|
public class SchemaData
|
||||||
{
|
{
|
||||||
// Tables to be included (all others excluded) or those to be excluded.
|
// Tables to be included (all others excluded) or those to be excluded.
|
||||||
public List<String> Tables_Included { get; } = new List<String>();
|
public HashSet<String> Tables_Included { get; } = new HashSet<String>(StringComparer.InvariantCultureIgnoreCase);
|
||||||
public List<String> Tables_Excluded { get; } = new List<String>();
|
public HashSet<String> Tables_Excluded { get; } = new HashSet<String>(StringComparer.InvariantCultureIgnoreCase);
|
||||||
|
// Schema capitalisation - for class name prefix etc - where capitalising first letter is insufficient.
|
||||||
|
public Dictionary<String, String> SchemaNameCapitalisation { get; } = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase);
|
||||||
// Alternative table names.
|
// Alternative table names.
|
||||||
public Dictionary<String, List<String>> AlternativeTableNames { get; } = new Dictionary<string, List<string>>();
|
public Dictionary<String, List<String>> AlternativeTableNames { get; } = new Dictionary<string, List<string>>(StringComparer.InvariantCultureIgnoreCase);
|
||||||
public void AddAlternativeTableName(String tableName, String tableNameAlternative)
|
public void AddAlternativeTableName(String tableName, String tableNameAlternative)
|
||||||
{
|
{
|
||||||
if (!AlternativeTableNames.ContainsKey(tableName)) AlternativeTableNames[tableName] = new List<string>();
|
if (!AlternativeTableNames.ContainsKey(tableName)) AlternativeTableNames[tableName] = new List<string>();
|
||||||
@@ -66,7 +68,7 @@ namespace Sarand.Net.Standard.Dbas.Base
|
|||||||
public class DefinitionClassConfig
|
public class DefinitionClassConfig
|
||||||
{
|
{
|
||||||
/// <summary>Using namespaces for database definition and table class usings.</summary>
|
/// <summary>Using namespaces for database definition and table class usings.</summary>
|
||||||
public List<String> Usings { get; } = new List<String>() { "Sarand.Net.Standard.Base.Core", "Sarand.Net.Standard.Base.Dbas" };
|
public HashSet<String> Usings { get; } = new HashSet<String>() { "Sarand.Net.Standard.Base.Core", "Sarand.Net.Standard.Base.Dbas" };
|
||||||
public String Namespace { get; set; } = "Sarand.Application.Core.Base";
|
public String Namespace { get; set; } = "Sarand.Application.Core.Base";
|
||||||
public String Classname { get; set; } = "SaDbDfn";
|
public String Classname { get; set; } = "SaDbDfn";
|
||||||
}
|
}
|
||||||
@@ -75,7 +77,7 @@ namespace Sarand.Net.Standard.Dbas.Base
|
|||||||
public class TableClassConfig
|
public class TableClassConfig
|
||||||
{
|
{
|
||||||
/// <summary>Using namespaces for table classes.</summary>
|
/// <summary>Using namespaces for table classes.</summary>
|
||||||
public List<String> Usings { get; } = new List<String>() { "Sarand.Net.Standard.Base.Core", "Sarand.Net.Standard.Base.Dbas" };
|
public HashSet<String> Usings { get; } = new HashSet<String>() { "Sarand.Net.Standard.Base.Core", "Sarand.Net.Standard.Base.Dbas" };
|
||||||
public String Namespace_BaseClass { get; set; } = "Sarand.Net.Standard.Dbas.Data";
|
public String Namespace_BaseClass { get; set; } = "Sarand.Net.Standard.Dbas.Data";
|
||||||
public String Namespace { get; set; } = "Sarand.Application.Dbas";
|
public String Namespace { get; set; } = "Sarand.Application.Dbas";
|
||||||
public String BaseClass { get; set; } = "DbDataItem";
|
public String BaseClass { get; set; } = "DbDataItem";
|
||||||
@@ -89,6 +91,7 @@ namespace Sarand.Net.Standard.Dbas.Base
|
|||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// Data members.
|
// Data members.
|
||||||
private Config config = null;
|
private Config config = null;
|
||||||
|
private const String DefaultSchema_MSSQL = "dbo";
|
||||||
private static String /*lf = "\n",*/ crlf = "\r\n", tab1 = "\t", tab2 = "\t\t", tab3 = "\t\t\t", tab4 = "\t\t\t\t", tab5 = "\t\t\t\t\t";
|
private static String /*lf = "\n",*/ crlf = "\r\n", tab1 = "\t", tab2 = "\t\t", tab3 = "\t\t\t", tab4 = "\t\t\t\t", tab5 = "\t\t\t\t\t";
|
||||||
// Reserved words.
|
// Reserved words.
|
||||||
private static readonly String[] reservedWords =
|
private static readonly String[] reservedWords =
|
||||||
@@ -313,10 +316,19 @@ namespace Sarand.Net.Standard.Dbas.Base
|
|||||||
file.WriteLine(tab2 + "{");
|
file.WriteLine(tab2 + "{");
|
||||||
file.WriteLine(tab3 + "int tableIdx = (int)table - 1;");
|
file.WriteLine(tab3 + "int tableIdx = (int)table - 1;");
|
||||||
file.WriteLine(tab3 + "if (tableIdx < 0 || tableIdx >= tableCount) return String.Empty;");
|
file.WriteLine(tab3 + "if (tableIdx < 0 || tableIdx >= tableCount) return String.Empty;");
|
||||||
file.WriteLine(tab3 + "String tableName = tables[(int)tableIdx];");
|
file.WriteLine(tab3 + "String tableName = tables[(int)tableIdx].Name;");
|
||||||
file.WriteLine(tab3 + "if (delimitReservedWords) tableName = DelimitReservedWord(tableName);");
|
file.WriteLine(tab3 + "if (delimitReservedWords) tableName = DelimitReservedWord(tableName);");
|
||||||
file.WriteLine(tab3 + "return tableName;");
|
file.WriteLine(tab3 + "return tableName;");
|
||||||
file.WriteLine(tab2 + "}");
|
file.WriteLine(tab2 + "}");
|
||||||
|
file.WriteLine(tab2 + "public static String GetTableNameQual (TableIdx table, bool delimitReservedWords = true)");
|
||||||
|
file.WriteLine(tab2 + "{");
|
||||||
|
file.WriteLine(tab3 + "int tableIdx = (int)table - 1;");
|
||||||
|
file.WriteLine(tab3 + "if (tableIdx < 0 || tableIdx >= tableCount) return String.Empty;");
|
||||||
|
file.WriteLine(tab3 + "String schemaName = tables[(int)tableIdx].Schema;");
|
||||||
|
file.WriteLine(tab3 + "String tableName = tables[(int)tableIdx].Name;");
|
||||||
|
file.WriteLine(tab3 + "if (delimitReservedWords) { schemaName = DelimitReservedWord(schemaName); tableName = DelimitReservedWord(tableName); }");
|
||||||
|
file.WriteLine(tab3 + "return (StringUtil.IsBlank(schemaName) ? \"\" : schemaName + \".\") + tableName;");
|
||||||
|
file.WriteLine(tab2 + "}");
|
||||||
file.WriteLine(crlf + tab2 + "//-------------------------------------------------------------------");
|
file.WriteLine(crlf + tab2 + "//-------------------------------------------------------------------");
|
||||||
|
|
||||||
// Table for Column method.
|
// Table for Column method.
|
||||||
@@ -369,8 +381,15 @@ namespace Sarand.Net.Standard.Dbas.Base
|
|||||||
file.WriteLine(tab2 + "}");
|
file.WriteLine(tab2 + "}");
|
||||||
file.WriteLine(tab2 + "public static String DelimitReservedWord (String word)");
|
file.WriteLine(tab2 + "public static String DelimitReservedWord (String word)");
|
||||||
file.WriteLine(tab2 + "{");
|
file.WriteLine(tab2 + "{");
|
||||||
file.WriteLine(tab3 + "if (!IsReservedWord(word)) return word;");
|
file.WriteLine(tab3 + "return IsReservedWord(word) ? DelimitWord(word) : word;");
|
||||||
file.WriteLine(tab3 + "switch (reservedWordDelim)");
|
file.WriteLine(tab2 + "}");
|
||||||
|
file.WriteLine(tab2 + "public static String DelimitWord (String word)");
|
||||||
|
file.WriteLine(tab2 + "{");
|
||||||
|
file.WriteLine(tab3 + "return DelimitWord(word, reservedWordDelim);");
|
||||||
|
file.WriteLine(tab2 + "}");
|
||||||
|
file.WriteLine(tab2 + "public static String DelimitWord (String word, DbReservedWordDelim wordDelim)");
|
||||||
|
file.WriteLine(tab2 + "{");
|
||||||
|
file.WriteLine(tab3 + "switch (wordDelim)");
|
||||||
file.WriteLine(tab3 + "{");
|
file.WriteLine(tab3 + "{");
|
||||||
file.WriteLine(tab4 + "case DbReservedWordDelim.None:");
|
file.WriteLine(tab4 + "case DbReservedWordDelim.None:");
|
||||||
file.WriteLine(tab5 + "break;");
|
file.WriteLine(tab5 + "break;");
|
||||||
@@ -447,12 +466,22 @@ namespace Sarand.Net.Standard.Dbas.Base
|
|||||||
file.WriteLine(tab2 + "}");
|
file.WriteLine(tab2 + "}");
|
||||||
file.WriteLine(crlf + tab2 + "//-------------------------------------------------------------------");
|
file.WriteLine(crlf + tab2 + "//-------------------------------------------------------------------");
|
||||||
|
|
||||||
// Table definitions.
|
// Table names.
|
||||||
file.WriteLine(tab2 + "// Table definitions.");
|
file.WriteLine(tab2 + "// Table definitions.");
|
||||||
file.WriteLine(tab2 + "private static readonly String[] tables =");
|
file.WriteLine(tab2 + "private class TableDfn");
|
||||||
|
file.WriteLine(tab2 + "{");
|
||||||
|
file.WriteLine(tab3 + "internal String Schema { get; set; }");
|
||||||
|
file.WriteLine(tab3 + "internal String Name { get; set; }");
|
||||||
|
file.WriteLine(tab3 + "internal TableDfn (String schema, String name)");
|
||||||
|
file.WriteLine(tab3 + "{");
|
||||||
|
file.WriteLine(tab4 + "this.Schema= schema;");
|
||||||
|
file.WriteLine(tab4 + "this.Name = name;");
|
||||||
|
file.WriteLine(tab3 + "}");
|
||||||
|
file.WriteLine(tab2 + "}");
|
||||||
|
file.WriteLine(tab2 + "private static readonly TableDfn[] tables =");
|
||||||
file.WriteLine(tab2 + "{");
|
file.WriteLine(tab2 + "{");
|
||||||
foreach (DbDfnTable tableDfn in tableDfns)
|
foreach (DbDfnTable tableDfn in tableDfns)
|
||||||
file.WriteLine(tab3 + "\"" + tableDfn.Name + "\", ");
|
file.WriteLine(tab3 + "new TableDfn(\"" + tableDfn.Schema + "\",\"" + tableDfn.Name + "\"),");
|
||||||
file.WriteLine(tab2 + "};");
|
file.WriteLine(tab2 + "};");
|
||||||
file.WriteLine(crlf + tab2 + "//-------------------------------------------------------------------");
|
file.WriteLine(crlf + tab2 + "//-------------------------------------------------------------------");
|
||||||
|
|
||||||
@@ -476,7 +505,6 @@ namespace Sarand.Net.Standard.Dbas.Base
|
|||||||
file.WriteLine(tab4 + "this.DataLen = dataLen;");
|
file.WriteLine(tab4 + "this.DataLen = dataLen;");
|
||||||
file.WriteLine(tab3 + "}");
|
file.WriteLine(tab3 + "}");
|
||||||
file.WriteLine(tab2 + "}");
|
file.WriteLine(tab2 + "}");
|
||||||
file.WriteLine(crlf + tab2 + "//-------------------------------------------------------------------");
|
|
||||||
file.WriteLine(tab2 + "private static readonly ColumnDfn[] columns =");
|
file.WriteLine(tab2 + "private static readonly ColumnDfn[] columns =");
|
||||||
file.WriteLine(tab2 + "{");
|
file.WriteLine(tab2 + "{");
|
||||||
uint tableIdx = 0;
|
uint tableIdx = 0;
|
||||||
@@ -505,6 +533,10 @@ namespace Sarand.Net.Standard.Dbas.Base
|
|||||||
private void GenerateTableInterfaceClass(DbDfnTable tableDfn)
|
private void GenerateTableInterfaceClass(DbDfnTable tableDfn)
|
||||||
{
|
{
|
||||||
String className = tableDfn.Name + "_Db";
|
String className = tableDfn.Name + "_Db";
|
||||||
|
if (!StringUtil.IsEmpty(tableDfn.Schema) && !tableDfn.Schema.EqualsCI("dbo"))
|
||||||
|
{
|
||||||
|
className = config.Schema.SchemaNameCapitalisation.GetValueOrDefault(tableDfn.Schema, StringUtil.CapitaliseFirst(tableDfn.Schema)) + "_" + className;
|
||||||
|
}
|
||||||
List<String> primaryColumnNames = tableDfn.GetPrimaryColumnNames();
|
List<String> primaryColumnNames = tableDfn.GetPrimaryColumnNames();
|
||||||
String identityColumnName = tableDfn.Columns.GetIdentityColumnName();
|
String identityColumnName = tableDfn.Columns.GetIdentityColumnName();
|
||||||
String identityColumnVariableTypeName = tableDfn.Columns.GetIdentityColumnVariableTypeName();
|
String identityColumnVariableTypeName = tableDfn.Columns.GetIdentityColumnVariableTypeName();
|
||||||
|
|||||||
@@ -141,7 +141,7 @@ namespace Sarand.Net.Standard.Dbas.Base
|
|||||||
if (StringUtil.IsEmpty(config.DatabaseName))
|
if (StringUtil.IsEmpty(config.DatabaseName))
|
||||||
config.DatabaseName = sqlDatabase;
|
config.DatabaseName = sqlDatabase;
|
||||||
|
|
||||||
SaLogger.Info("DatabaseConsole.GenerateConnectionString Driver: " + sqlDriver + ". Server: " + sqlServer + ". Database: " + sqlDatabase + ". Connection: " + connectionString);
|
SaLogger.Info($"{SysUtil.Fn} Driver: " + sqlDriver + ". Server: " + sqlServer + ". Database: " + sqlDatabase + ". Connection: " + connectionString);
|
||||||
}
|
}
|
||||||
return connectionString;
|
return connectionString;
|
||||||
}
|
}
|
||||||
@@ -219,7 +219,7 @@ namespace Sarand.Net.Standard.Dbas.Base
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
SaLogger.Debug("DropDbIndex Table: " + tableName + "; Index: " + indexName + "; Exception: " + database.ErrorStateMessage);
|
SaLogger.Debug($"{SysUtil.Fn} Table: " + tableName + "; Index: " + indexName + "; Exception: " + database.ErrorStateMessage);
|
||||||
#endif
|
#endif
|
||||||
SetErrorState("Failed to drop index " + indexName + " on " + tableName + " - " + database.ErrorStateMessage);
|
SetErrorState("Failed to drop index " + indexName + " on " + tableName + " - " + database.ErrorStateMessage);
|
||||||
}
|
}
|
||||||
@@ -240,7 +240,7 @@ namespace Sarand.Net.Standard.Dbas.Base
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
SaLogger.Debug("DropDbIndex Table: " + tableName + "; Index: " + indexName + "; Exception: " + database.ErrorStateMessage);
|
SaLogger.Debug($"{SysUtil.Fn} Table: " + tableName + "; Index: " + indexName + "; Exception: " + database.ErrorStateMessage);
|
||||||
#endif
|
#endif
|
||||||
SetErrorState("Failed to drop primary key " + indexName + " on " + tableName + " - " + database.ErrorStateMessage);
|
SetErrorState("Failed to drop primary key " + indexName + " on " + tableName + " - " + database.ErrorStateMessage);
|
||||||
}
|
}
|
||||||
@@ -288,7 +288,7 @@ namespace Sarand.Net.Standard.Dbas.Base
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
SaLogger.Debug("CreatePrimaryDbIndex Table: %" + tableName + "; Index: " + indexName + "; Exception: " + database.ErrorStateMessage);
|
SaLogger.Debug($"{SysUtil.Fn} Table: %" + tableName + "; Index: " + indexName + "; Exception: " + database.ErrorStateMessage);
|
||||||
#endif
|
#endif
|
||||||
SetErrorState("Failed to create primary index " + indexName + " on " + tableName + " - " + database.ErrorStateMessage);
|
SetErrorState("Failed to create primary index " + indexName + " on " + tableName + " - " + database.ErrorStateMessage);
|
||||||
}
|
}
|
||||||
@@ -322,7 +322,7 @@ namespace Sarand.Net.Standard.Dbas.Base
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
SaLogger.Debug("CreateDbIndex Table: " + tableName + "; Index: " + indexName + "; Exception: " + database.ErrorStateMessage);
|
SaLogger.Debug($"{SysUtil.Fn} Table: " + tableName + "; Index: " + indexName + "; Exception: " + database.ErrorStateMessage);
|
||||||
#endif
|
#endif
|
||||||
SetErrorState("Failed to create index " + indexName + " on " + tableName + " - " + database.ErrorStateMessage);
|
SetErrorState("Failed to create index " + indexName + " on " + tableName + " - " + database.ErrorStateMessage);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,8 +57,8 @@ namespace Sarand.Net.Standard.Dbas.CodeType
|
|||||||
OutputDirectory = directory,
|
OutputDirectory = directory,
|
||||||
};
|
};
|
||||||
// Schema - Tables.
|
// Schema - Tables.
|
||||||
config.Schema.Tables_Included.AddRange(new String[] { "SaCodeType", "SaCode" });
|
config.Schema.Tables_Included.UnionWith(new String[] { "SaCodeType", "SaCode" });
|
||||||
config.Schema.Tables_Excluded.AddRange(new String[] { });
|
config.Schema.Tables_Excluded.UnionWith(new String[] { });
|
||||||
// Schema - Columns.
|
// Schema - Columns.
|
||||||
config.Schema.InsertOnlyColumns.Add(".*", "CreateOn,CreateBy,CreateHost");
|
config.Schema.InsertOnlyColumns.Add(".*", "CreateOn,CreateBy,CreateHost");
|
||||||
config.Schema.InsertOnlyColumns.Add("SaCodeType", "Code");
|
config.Schema.InsertOnlyColumns.Add("SaCodeType", "Code");
|
||||||
|
|||||||
@@ -384,7 +384,7 @@ namespace Sarand.Net.Standard.Dbas.Data
|
|||||||
// Only populate table names and/or table schemas where not previously done.
|
// Only populate table names and/or table schemas where not previously done.
|
||||||
if (tables.Count < 1 || tables.Exists(item => !item.HasColumns()))
|
if (tables.Count < 1 || tables.Exists(item => !item.HasColumns()))
|
||||||
{
|
{
|
||||||
// Use a single connection for table and schaema population.
|
// Use a single connection for table and schema population.
|
||||||
using (DbConnection dbConnection = CreateConnection(true))
|
using (DbConnection dbConnection = CreateConnection(true))
|
||||||
{
|
{
|
||||||
dbConnection.Open();
|
dbConnection.Open();
|
||||||
|
|||||||
@@ -58,8 +58,8 @@ namespace Sarand.Net.Standard.Dbas.Interface
|
|||||||
OutputDirectory = directory,
|
OutputDirectory = directory,
|
||||||
};
|
};
|
||||||
// Schema - Tables.
|
// Schema - Tables.
|
||||||
config.Schema.Tables_Included.AddRange(new String[] { "SaInterface", "SaInterfaceProcess", "SaInterfaceProcessMessage", "SaInterfaceDataItem", "SaInterfaceProcessDataItem" });
|
config.Schema.Tables_Included.UnionWith(new String[] { "SaInterface", "SaInterfaceProcess", "SaInterfaceProcessMessage", "SaInterfaceDataItem", "SaInterfaceProcessDataItem" });
|
||||||
config.Schema.Tables_Excluded.AddRange(new String[] { });
|
config.Schema.Tables_Excluded.UnionWith(new String[] { });
|
||||||
config.Schema.AddAlternativeTableName("SaInterface", "Interface");
|
config.Schema.AddAlternativeTableName("SaInterface", "Interface");
|
||||||
config.Schema.AddAlternativeTableName("SaInterfaceProcess", "InterfaceProcess");
|
config.Schema.AddAlternativeTableName("SaInterfaceProcess", "InterfaceProcess");
|
||||||
config.Schema.AddAlternativeTableName("SaInterfaceProcessMessage", "InterfaceProcessMessage");
|
config.Schema.AddAlternativeTableName("SaInterfaceProcessMessage", "InterfaceProcessMessage");
|
||||||
|
|||||||
@@ -58,8 +58,8 @@ namespace Sarand.Net.Standard.Dbas.ItemData
|
|||||||
OutputDirectory = directory,
|
OutputDirectory = directory,
|
||||||
};
|
};
|
||||||
// Schema - Tables.
|
// Schema - Tables.
|
||||||
config.Schema.Tables_Included.AddRange(new String[] { "SaItemData" });
|
config.Schema.Tables_Included.UnionWith(new String[] { "SaItemData" });
|
||||||
config.Schema.Tables_Excluded.AddRange(new String[] { });
|
config.Schema.Tables_Excluded.UnionWith(new String[] { });
|
||||||
// Schema - Columns.
|
// Schema - Columns.
|
||||||
config.Schema.InsertOnlyColumns.Add(".*", "CreateOn,CreateBy,CreateHost");
|
config.Schema.InsertOnlyColumns.Add(".*", "CreateOn,CreateBy,CreateHost");
|
||||||
config.Schema.InsertOnlyColumns.Add("SaItemData", "ItemType,ItemId,Name,Context");
|
config.Schema.InsertOnlyColumns.Add("SaItemData", "ItemType,ItemId,Name,Context");
|
||||||
|
|||||||
@@ -62,8 +62,8 @@ namespace Sarand.Net.Standard.Dbas.ItemDocs
|
|||||||
OutputDirectory = directory,
|
OutputDirectory = directory,
|
||||||
};
|
};
|
||||||
// Schema - Tables.
|
// Schema - Tables.
|
||||||
config.Schema.Tables_Included.AddRange(new String[] { "SaItemDoc" });
|
config.Schema.Tables_Included.UnionWith(new String[] { "SaItemDoc" });
|
||||||
config.Schema.Tables_Excluded.AddRange(new String[] { });
|
config.Schema.Tables_Excluded.UnionWith(new String[] { });
|
||||||
// Schema - Columns.
|
// Schema - Columns.
|
||||||
config.Schema.InsertOnlyColumns.Add(".*", "CreateOn,CreateBy,CreateHost");
|
config.Schema.InsertOnlyColumns.Add(".*", "CreateOn,CreateBy,CreateHost");
|
||||||
config.Schema.InsertOnlyColumns.Add("SaItemDocs", "ItemType,ItemId,Name,Context");
|
config.Schema.InsertOnlyColumns.Add("SaItemDocs", "ItemType,ItemId,Name,Context");
|
||||||
|
|||||||
@@ -58,8 +58,8 @@ namespace Sarand.Net.Standard.Dbas.ItemOptions
|
|||||||
OutputDirectory = directory,
|
OutputDirectory = directory,
|
||||||
};
|
};
|
||||||
// Schema - Tables.
|
// Schema - Tables.
|
||||||
config.Schema.Tables_Included.AddRange(new String[] { "SaItemOption" });
|
config.Schema.Tables_Included.UnionWith(new String[] { "SaItemOption" });
|
||||||
config.Schema.Tables_Excluded.AddRange(new String[] { });
|
config.Schema.Tables_Excluded.UnionWith(new String[] { });
|
||||||
// Schema - Columns.
|
// Schema - Columns.
|
||||||
config.Schema.InsertOnlyColumns.Add(".*", "CreateOn,CreateBy,CreateHost");
|
config.Schema.InsertOnlyColumns.Add(".*", "CreateOn,CreateBy,CreateHost");
|
||||||
config.Schema.InsertOnlyColumns.Add("SaItemOption", "ItemType,ItemId,Name,Context");
|
config.Schema.InsertOnlyColumns.Add("SaItemOption", "ItemType,ItemId,Name,Context");
|
||||||
|
|||||||
@@ -58,8 +58,8 @@ namespace Sarand.Net.Standard.Dbas.ReferenceData
|
|||||||
OutputDirectory = directory,
|
OutputDirectory = directory,
|
||||||
};
|
};
|
||||||
// Schema - Tables.
|
// Schema - Tables.
|
||||||
config.Schema.Tables_Included.AddRange(new String[] { "Language", "Region", "Currency", "TaxCode", "UnitMeasure" });
|
config.Schema.Tables_Included.UnionWith(new String[] { "Language", "Region", "Currency", "TaxCode", "UnitMeasure" });
|
||||||
config.Schema.Tables_Excluded.AddRange(new String[] { });
|
config.Schema.Tables_Excluded.UnionWith(new String[] { });
|
||||||
// Schema - Columns.
|
// Schema - Columns.
|
||||||
config.Schema.InsertOnlyColumns.Add(".*", "CreateOn,CreateBy,CreateHost");
|
config.Schema.InsertOnlyColumns.Add(".*", "CreateOn,CreateBy,CreateHost");
|
||||||
config.Schema.InsertOnlyColumns.Add("Language", "");
|
config.Schema.InsertOnlyColumns.Add("Language", "");
|
||||||
|
|||||||
@@ -57,8 +57,8 @@ namespace Sarand.Net.Standard.Dbas.Security
|
|||||||
OutputDirectory = directory,
|
OutputDirectory = directory,
|
||||||
};
|
};
|
||||||
// Schema - Tables.
|
// Schema - Tables.
|
||||||
config.Schema.Tables_Included.AddRange(new String[] { "SaSecItem", "SaSecLink" });
|
config.Schema.Tables_Included.UnionWith(new String[] { "SaSecItem", "SaSecLink" });
|
||||||
config.Schema.Tables_Excluded.AddRange(new String[] { });
|
config.Schema.Tables_Excluded.UnionWith(new String[] { });
|
||||||
config.Schema.AddAlternativeTableName("SaSecItem", "SaSecurityItem");
|
config.Schema.AddAlternativeTableName("SaSecItem", "SaSecurityItem");
|
||||||
config.Schema.AddAlternativeTableName("SaSecLink", "SaSecurityLink");
|
config.Schema.AddAlternativeTableName("SaSecLink", "SaSecurityLink");
|
||||||
// Schema - Columns.
|
// Schema - Columns.
|
||||||
|
|||||||
@@ -58,8 +58,8 @@ namespace Sarand.Net.Standard.Dbas.UpdateLog
|
|||||||
OutputDirectory = directory,
|
OutputDirectory = directory,
|
||||||
};
|
};
|
||||||
// Schema - Tables.
|
// Schema - Tables.
|
||||||
config.Schema.Tables_Included.AddRange(new String[] { "SaAttrUpdate" });
|
config.Schema.Tables_Included.UnionWith(new String[] { "SaAttrUpdate" });
|
||||||
config.Schema.Tables_Excluded.AddRange(new String[] { });
|
config.Schema.Tables_Excluded.UnionWith(new String[] { });
|
||||||
// SChema - Columns.
|
// SChema - Columns.
|
||||||
config.Schema.InsertOnlyColumns.Add(".*", "CreateOn,CreateBy,CreateHost");
|
config.Schema.InsertOnlyColumns.Add(".*", "CreateOn,CreateBy,CreateHost");
|
||||||
config.Schema.InsertOnlyColumns.Add("SaAttrUpdate", "ItemType,ItemId,Logged,Attribute");
|
config.Schema.InsertOnlyColumns.Add("SaAttrUpdate", "ItemType,ItemId,Logged,Attribute");
|
||||||
|
|||||||
@@ -587,14 +587,14 @@ namespace Sarand.Net.Standard.Proc.Excel
|
|||||||
public static int GetPosForColId(String colId)
|
public static int GetPosForColId(String colId)
|
||||||
{
|
{
|
||||||
colId = StringUtil.TrimWhitespace(StringUtil.OnBlank(colId)).ToUpper();
|
colId = StringUtil.TrimWhitespace(StringUtil.OnBlank(colId)).ToUpper();
|
||||||
if (!colId.Matches(new Regex("[A-Z]+")))
|
if (!colId.IsMatch("^[A-Z]{1,2}$"))
|
||||||
{
|
{
|
||||||
SaLogger.Warn(SysUtil.Fn + " Invalid column Id supplied: '" + colId + "'");
|
SaLogger.Warn(SysUtil.Fn + " Invalid column Id supplied: '" + colId + "'");
|
||||||
return -1;
|
return 0;
|
||||||
}
|
}
|
||||||
int col = (colId[0] - 'A');
|
int col = (colId[0] - 'A' + 1);
|
||||||
if (colId.Length > 1)
|
if (colId.Length > 1)
|
||||||
col = ((colId[1] - 'A') * 26) + (colId[0] - 'A');
|
col = (col * 26) + (colId[1] - 'A' + 1);
|
||||||
return col;
|
return col;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -845,7 +845,7 @@ namespace Sarand.Net.Standard.Proc.Excel
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (IsCellDate(cell))
|
if (IsCellDate(cell))
|
||||||
return new DataValue(cell.DateCellValue);
|
return new DataValue((DateTime)(cell.DateCellValue ?? DateTime.MinValue));
|
||||||
if (IsCellNumeric(cell))
|
if (IsCellNumeric(cell))
|
||||||
{
|
{
|
||||||
double value = cell.NumericCellValue;
|
double value = cell.NumericCellValue;
|
||||||
@@ -971,7 +971,7 @@ namespace Sarand.Net.Standard.Proc.Excel
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
IRow row = GetRowByPos(rowPos, true);
|
IRow row = GetRowByPos(rowPos, true);
|
||||||
for (int valueIdx = 0; valueIdx < values.Count; valueIdx++)
|
for (int valueIdx = 0; valueIdx < values.Count; valueIdx++)
|
||||||
{
|
{
|
||||||
uint colPos = (uint)Math.Max(1, colPosStart + valueIdx);
|
uint colPos = (uint)Math.Max(1, colPosStart + valueIdx);
|
||||||
Object value = values[valueIdx];
|
Object value = values[valueIdx];
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
using Sarand.Net.Standard.Base.Procs;
|
using Sarand.Net.Standard.Base.App;
|
||||||
|
using Sarand.Net.Standard.Base.Dbas;
|
||||||
|
using Sarand.Net.Standard.Base.Procs;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
@@ -13,8 +15,11 @@ namespace Sarand.Net.Standard.Proc.Procs
|
|||||||
// Definitions.
|
// Definitions.
|
||||||
public new class Config : SaProcess_Base.Config
|
public new class Config : SaProcess_Base.Config
|
||||||
{
|
{
|
||||||
protected Config() : base()
|
protected Config(DbUpdateInfo dbUpdateInfo) : base()
|
||||||
{ }
|
{
|
||||||
|
this.DbUpdateInfo = dbUpdateInfo;
|
||||||
|
}
|
||||||
|
public DbUpdateInfo DbUpdateInfo { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
|
|||||||
@@ -10,8 +10,8 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="DocumentFormat.OpenXml" Version="3.0.1" />
|
<PackageReference Include="DocumentFormat.OpenXml" Version="3.0.2" />
|
||||||
<PackageReference Include="NPOI" Version="2.6.2" />
|
<PackageReference Include="NPOI" Version="2.7.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
Reference in New Issue
Block a user