diff --git a/.gitignore b/.gitignore
index 688980b..49647ee 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,81 +1,13 @@
-# --------------------------------------------------------------------------------------------------
-# Core Visual Studio / .NET build outputs
-# --------------------------------------------------------------------------------------------------
-bin/
-obj/
-[Bb]uild/
-[Dd]ebug*/
-[Rr]elease*/
-x64/
-x86/
-[Aa][Rr][Mm]/
-[Aa][Rr][Mm]64/
-_ReSharper.*/
-*.user
-*.userosscache
-*.suo
-*.cache
-*.pdb
-*.mpdb
-*.opendb
-*.VC.db
-*.vscode/
-
-# --------------------------------------------------------------------------------------------------
-# Package artefacts (NuGet, npm, etc.)
-# --------------------------------------------------------------------------------------------------
-/packages/
-*.nupkg
-*.snupkg
-*.nuspec
-package-lock.json
-packages.config
-npm-debug.log*
-yarn-error.log
-
-# --------------------------------------------------------------------------------------------------
-# TFS / TFVC specific files and folders
-# --------------------------------------------------------------------------------------------------
-$tf/
-*$tf/
-*.tf
-*.tfs
-.tfignore
-
-# --------------------------------------------------------------------------------------------------
-# IDE tooling and workspace settings
-# --------------------------------------------------------------------------------------------------
-.vs/
-.vscode/
-*.swp
-*.sln.docstates
-*.VC.VC.opendb
-.idea/
-.DS_Store
-Thumbs.db
-
-# --------------------------------------------------------------------------------------------------
-# Test results and profiling data
-# --------------------------------------------------------------------------------------------------
-[Tt]est[Rr]esult*/
-[Bb]uild[Ll]og.*
-*.trx
-*.coverage
-*.coveragexml
-*.opencover.xml
-*.dotCover
-BenchmarkDotNet.Artifacts/
-
-# --------------------------------------------------------------------------------------------------
-# Miscellaneous recommended ignores
-# --------------------------------------------------------------------------------------------------
-_UpgradeReport_Files/
-Backup*/
-UpgradeLog*.XML
-*.tmp
-*.temp
-*.log
-*.bak
-*.orig
-*.scc
-
+bin/
+obj/
+.vs/
+*.user
+packages/
+F4SDHelper/packages.config
+F4SDM42WebApi/packages.config
+F4SDM42WebApi/BasePackage/Assemblies/
+F4SDM42WebApi/Root/InstalledPackages/
+F4SDHelper/bin/
+F4SDHelper/obj/
+F4SDM42WebApi/bin/
+F4SDM42WebApi/obj/
diff --git a/F4SDHelper/F4SD - Helper.csproj b/F4SDHelper/F4SD - Helper.csproj
index 7dc3d72..1939174 100644
--- a/F4SDHelper/F4SD - Helper.csproj
+++ b/F4SDHelper/F4SD - Helper.csproj
@@ -1,63 +1,25 @@
-
-
-
+
- Debug
- AnyCPU
- {EB95E1FB-7A9E-4894-BD28-2D0BE2715EBE}
+ net8.0
Library
- Properties
C4IT.F4SDM
C4ITF4SDM42WebApiHelper
- v4.7.2
- 512
- true
-
- SAK
- SAK
- SAK
- SAK
-
-
- true
- full
- false
- bin\Debug\
- DEBUG;TRACE
- prompt
- 4
-
-
- pdbonly
- true
- bin\Release\
- TRACE
- prompt
- 4
-
-
- bin\Release_and_copy\
- TRACE
- true
- pdbonly
- AnyCPU
- 7.3
- prompt
+ disable
+ disable
+ latestmajor
+ false
+ false
+
-
- ..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll
+
+ ..\F4SDM42WebApi\M42Libraries\26.1\Newtonsoft.Json.dll
+ false
-
-
-
-
-
-
-
-
+
+
Common\C4IT.Logging.LogManager.cs
@@ -67,11 +29,6 @@
Properties\SharedAssemblyInfo.cs
-
-
-
-
-
-
-
\ No newline at end of file
+
+
diff --git a/F4SDM42WebApi/C4ITF4SDM42WebApi.dll.host b/F4SDM42WebApi/C4ITF4SDM42WebApi.dll.host
new file mode 100644
index 0000000..22e782f
--- /dev/null
+++ b/F4SDM42WebApi/C4ITF4SDM42WebApi.dll.host
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/F4SDM42WebApi/F4SD - M42WebApi.csproj b/F4SDM42WebApi/F4SD - M42WebApi.csproj
index be3676e..82666de 100644
--- a/F4SDM42WebApi/F4SD - M42WebApi.csproj
+++ b/F4SDM42WebApi/F4SD - M42WebApi.csproj
@@ -1,139 +1,93 @@
-
-
-
+
- Debug
- AnyCPU
- {D8CBFFCA-0B43-4ACC-80EA-C944E7420CEE}
+ net8.0
Library
- Properties
C4IT.F4SDM
C4ITF4SDM42WebApi
- v4.7.2
- 512
- true
-
- SAK
- SAK
- SAK
- SAK
-
-
- true
- full
- false
- bin\Debug\
- DEBUG;TRACE
- prompt
- 4
-
-
-
-
- pdbonly
- true
- bin\Release\
- TRACE
- prompt
- 4
-
-
- true
- bin\Debug_and_copy\
- DEBUG;TRACE
- full
- AnyCPU
- 7.3
- prompt
-
-
- bin\Release_and_copy\
- TRACE
- true
- pdbonly
- AnyCPU
- 7.3
- prompt
+ win-x64;linux-x64
+ true
+ disable
+ disable
+ latestmajor
+ false
+ false
+ d8cbffca-0b43-4acc-80ea-c944e7420cee
+ C4ITF4SD*.*
+
-
- False
- M42Libraries\Matrix42.Common.dll
+
+ M42Libraries\26.1\Matrix42.Common.dll
+ false
-
- False
- M42Libraries\Matrix42.Contracts.Common.dll
+
+ M42Libraries\26.1\Matrix42.Contracts.Common.dll
+ false
-
- False
- M42Libraries\Matrix42.Contracts.Platform.dll
+
+ M42Libraries\26.1\Matrix42.Contracts.Platform.dll
+ false
-
- False
- M42Libraries\Matrix42.Contracts.ServiceManagement.dll
+
+ M42Libraries\26.1\Matrix42.Contracts.ServiceManagement.dll
+ false
-
- False
- M42Libraries\Matrix42.Pandora.Contracts.dll
+
+ M42Libraries\26.1\Matrix42.Hosting.Contracts.dll
+ false
-
- False
- M42Libraries\Matrix42.Services.Description.Contracts.dll
+
+ M42Libraries\26.1\Matrix42.Configuration.Global.dll
+ false
-
- ..\packages\Newtonsoft.Json.12.0.2\lib\net45\Newtonsoft.Json.dll
+
+ M42Libraries\26.1\Matrix42.Pandora.Contracts.dll
+ false
-
-
-
-
-
- False
- M42Libraries\System.Web.Http.dll
+
+ M42Libraries\26.1\Matrix42.Services.Description.Contracts.dll
+ false
-
- False
- M42Libraries\System.Web.OData.dll
+
+ M42Libraries\26.1\Matrix42.WebApi.Contracts.dll
+ false
-
-
-
-
-
-
-
- False
- M42Libraries\update4u.SPS.DataLayer.dll
+
+ M42Libraries\26.1\Newtonsoft.Json.dll
+ false
-
- False
- M42Libraries\update4u.SPS.Utility.dll
+
+ M42Libraries\26.1\System.Net.Http.Formatting.dll
+ false
+
+
+ M42Libraries\26.1\update4u.SPS.DataLayer.dll
+ false
+
+
+ M42Libraries\26.1\update4u.SPS.Utility.dll
+ false
+
+
+
+
+
-
- Properties\SharedAssemblyInfo.cs
-
+
+ Properties\SharedAssemblyInfo.cs
+
+
-
- {eb95e1fb-7a9e-4894-bd28-2d0be2715ebe}
- F4SD - Helper
- True
-
-
-
-
-
-
+
+
-
-
- @echo powershell -ExecutionPolicy Unrestricted $(ProjectDir)deploy.ps1 -ProjectDir $(ProjectDir) -SolutionDir $(SolutionDir) -OutDir $(OutDir) -ConfigurationName $(ConfigurationName)
-
-
\ No newline at end of file
+
+
diff --git a/F4SDM42WebApi/F4SDHelperService.cs b/F4SDM42WebApi/F4SDHelperService.cs
index 4fa9d8a..49f7cc8 100644
--- a/F4SDM42WebApi/F4SDHelperService.cs
+++ b/F4SDM42WebApi/F4SDHelperService.cs
@@ -13,9 +13,9 @@ using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
-using System.Web;
using Matrix42.Common;
+using Matrix42.WebApi.Contracts;
using update4u.SPS.DataLayer;
using update4u.SPS.DataLayer.Transaction;
@@ -80,7 +80,7 @@ namespace C4IT.F4SD
{
LogEntry($"Generating F4SD URI for type: '{type}', GUID: '{EOID}'", LogLevels.Debug);
var builder = new UriBuilder(c4itf4sdmonLinkBase);
- var queryString = HttpUtility.ParseQueryString(builder.Query);
+ var queryString = UrlQueryBuilder.Parse(builder.Query);
switch (type.ToLowerInvariant().Split('.').Last())
{
@@ -1663,7 +1663,7 @@ namespace C4IT.F4SD
presetParamsDyn.SPSActivityClassIncident.Asset = asset.Id;
}
var type = TicketAndServiceRequestEnabled ? "SPSActivityTypeTicket" : "SPSActivityTypeIncident";
- var presetParams = HttpUtility.UrlEncode(JsonConvert.SerializeObject(presetParamsDyn));
+ var presetParams = WebUtility.UrlEncode(JsonConvert.SerializeObject(presetParamsDyn));
var directLink = string.Format(TicketDirectLinkCreateTemplate, F4SDM42WebApiController.defaultInstance.BaseUrl, type, presetParams);
return new DirectLink()
{
@@ -1848,7 +1848,7 @@ namespace C4IT.F4SD
viewOptionsDyn.type = CIName;
viewOptionsDyn.viewType = "action";
viewOptionsDyn.actionId = TicketCloseActionId;
- var viewOptions = HttpUtility.UrlEncode(JsonConvert.SerializeObject(viewOptionsDyn));
+ var viewOptions = WebUtility.UrlEncode(JsonConvert.SerializeObject(viewOptionsDyn));
var ticketDirectLinkPreview = string.Format(TicketDirectLinkPreviewTemplate, F4SDM42WebApiController.defaultInstance.BaseUrl, CIName, ActivityEOID);
var ticketDirectLinkEdit = string.Format(TicketDirectLinkEditTemplate, F4SDM42WebApiController.defaultInstance.BaseUrl, CIName, ActivityEOID);
@@ -2305,7 +2305,7 @@ namespace C4IT.F4SD
}
zipArchive.Dispose();
memoryStream.Position = 0L;
- HttpResponseMessage httpResponseMessage = request.CreateResponse(HttpStatusCode.OK);
+ HttpResponseMessage httpResponseMessage = HttpResponseExtensions.CreateResponse(request, HttpStatusCode.OK);
httpResponseMessage.Content = new StreamContent(memoryStream);
httpResponseMessage.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
@@ -2727,4 +2727,41 @@ namespace C4IT.F4SD
Roles = new List();
}
}
+
+ internal sealed class UrlQueryBuilder
+ {
+ private readonly List> _values = new List>();
+
+ private UrlQueryBuilder()
+ {
+ }
+
+ public static UrlQueryBuilder Parse(string query)
+ {
+ var builder = new UrlQueryBuilder();
+ var normalizedQuery = (query ?? string.Empty).TrimStart('?');
+
+ foreach (var pair in normalizedQuery.Split(new[] { '&' }, StringSplitOptions.RemoveEmptyEntries))
+ {
+ var separatorIndex = pair.IndexOf('=');
+ var key = separatorIndex >= 0 ? pair.Substring(0, separatorIndex) : pair;
+ var value = separatorIndex >= 0 ? pair.Substring(separatorIndex + 1) : string.Empty;
+
+ builder.Add(WebUtility.UrlDecode(key), WebUtility.UrlDecode(value));
+ }
+
+ return builder;
+ }
+
+ public void Add(string key, string value)
+ {
+ if (!string.IsNullOrEmpty(key))
+ _values.Add(new KeyValuePair(key, value ?? string.Empty));
+ }
+
+ public override string ToString()
+ {
+ return string.Join("&", _values.Select(pair => $"{WebUtility.UrlEncode(pair.Key)}={WebUtility.UrlEncode(pair.Value)}"));
+ }
+ }
}
diff --git a/F4SDM42WebApi/F4SDM42WebApiController.cs b/F4SDM42WebApi/F4SDM42WebApiController.cs
index f86aab3..f6a3770 100644
--- a/F4SDM42WebApi/F4SDM42WebApiController.cs
+++ b/F4SDM42WebApi/F4SDM42WebApiController.cs
@@ -6,16 +6,14 @@ using System.Net;
using System.Net.Http;
using System.Reflection;
using System.Threading.Tasks;
-using System.Web;
-using System.Web.Http;
-using System.Web.Http.Controllers;
-using System.Web.OData;
-using System.Web.OData.Query;
using Matrix42.Common;
using Matrix42.Contracts.ServiceManagement.ServiceContracts;
+using Matrix42.Hosting.Contracts;
using Matrix42.Pandora.Contracts;
using Matrix42.Services.Description.Contracts;
+using Matrix42.WebApi.Contracts;
+using Matrix42.WebApi.Contracts.OData;
using update4u.SPS.Utility.GlobalConfiguration;
using C4IT.F4SDM;
@@ -42,36 +40,25 @@ namespace C4IT.F4SD
private readonly F4SDHelperService _f4stHelperService;
- public string BaseUrl => $"{Request.RequestUri.Scheme}://{Request.RequestUri.Host}";
+ public string BaseUrl => Request?.RequestUri == null ? string.Empty : $"{Request.RequestUri.Scheme}://{Request.RequestUri.Host}";
public string EndpointBaseUrl => $"{BaseUrl}/m42Services/api/c4itf4sdwebapi";
- public F4SDM42WebApiController(
- //IObjectService objectService,
- //IIncidentService incidentService,
- IJournalService journalService
- //IFragmentService fragmentService,
- , IEntityDataService entityDataService
- , IPandoraUserProfile userProfile
- )
+
+ public F4SDM42WebApiController(IDependencyResolver resolver)
{
defaultInstance = this;
- //_objectService = objectService;
- //_fragmentService = fragmentService;
- //_incidentService = Guard.NullArgument(incidentService, "incidentService");
-
- _entityDataService = entityDataService;
- _journalService = journalService;
+ _entityDataService = resolver?.TryGet();
+ _journalService = resolver?.TryGet();
_globalConfigurationProvider = GlobalConfigurationProvider.Instance;
_f4stHelperService = new F4SDHelperService();
- _userProfile = userProfile;
+ _userProfile = resolver?.TryGet();
+ EnsureInitialized();
}
- private static object initLock = new object();
- protected override void Initialize(HttpControllerContext controllerContext)
+ private static readonly object initLock = new object();
+ private static void EnsureInitialized()
{
- base.Initialize(controllerContext);
try
{
- //System.Diagnostics.Debugger.Launch();
lock (initLock)
{
if (IsInitialized || F4SDM42LogsWebApiController.IsInitialized)
@@ -311,18 +298,18 @@ namespace C4IT.F4SD
Values = vals.ToArray()
};
//CacheOutputAttribute.RegisterResponseEtag($"enum_{enumeration.Name}_{(int)mode}", $"{enumeration.Name}_{(int)mode}", cultureInvariant: false, userInvariant: true, val);
- return Request.CreateResponse(HttpStatusCode.OK, enumeration);
+ return HttpResponseExtensions.CreateResponse(Request, HttpStatusCode.OK, enumeration);
}
- [Route("getMyRoleMemberships", Order = 2), HttpGet]
+ [Route("getMyRoleMemberships"), HttpGet]
public async Task getMyRoleMemberships()
{
var User = _userProfile.GetInteractiveUserInfo();
var filter = AsqlHelper.BuildInCondition("ID", new Guid[] { User.Id });
- return Request.CreateResponse(HttpStatusCode.OK, await _f4stHelperService.UserPermissionsInfo(filter));
+ return HttpResponseExtensions.CreateResponse(Request, HttpStatusCode.OK, await _f4stHelperService.UserPermissionsInfo(filter));
}
- [Route("getRoleMemberships", Order = 1), HttpGet]
+ [Route("getRoleMemberships"), HttpGet]
public async Task getRoleMemberships([FromUri] GetRoleMembershipsRequest req)
{
var filter = "";
@@ -342,7 +329,7 @@ namespace C4IT.F4SD
if (!string.IsNullOrEmpty(filter))
{
- return Request.CreateResponse(HttpStatusCode.OK, await _f4stHelperService.UserPermissionsInfo(filter));
+ return HttpResponseExtensions.CreateResponse(Request, HttpStatusCode.OK, await _f4stHelperService.UserPermissionsInfo(filter));
}
else
{
@@ -350,11 +337,11 @@ namespace C4IT.F4SD
}
}
- [Route("getRoleMemberships/{userId}", Order = 1), HttpGet]
+ [Route("getRoleMemberships/{userId}"), HttpGet]
public async Task getRoleMembershipForUser(Guid userId)
{
var filter = AsqlHelper.BuildInCondition("ID", new Guid[] { userId });
- return Request.CreateResponse(HttpStatusCode.OK, await _f4stHelperService.UserPermissionsInfo(filter));
+ return HttpResponseExtensions.CreateResponse(Request, HttpStatusCode.OK, await _f4stHelperService.UserPermissionsInfo(filter));
}
[Obsolete]
@@ -391,7 +378,7 @@ namespace C4IT.F4SD
.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries)
.Select(part =>
{
- var decodedPart = HttpUtility.UrlDecode(part)?.Trim();
+ var decodedPart = WebUtility.UrlDecode(part)?.Trim();
if (string.IsNullOrWhiteSpace(decodedPart))
return null;
@@ -477,10 +464,9 @@ namespace C4IT.F4SD
public static bool IsInitialized { get; private set; } = false;
- private static object initLock = new object();
- protected override void Initialize(HttpControllerContext controllerContext)
+ private static readonly object initLock = new object();
+ private static void EnsureInitialized()
{
- base.Initialize(controllerContext);
try
{
lock (initLock)
@@ -502,20 +488,15 @@ namespace C4IT.F4SD
public F4SDM42LogsWebApiController()
{
_f4stHelperService = new F4SDHelperService();
+ EnsureInitialized();
}
[Route(""), HttpGet]
- [EnableQuery]
public IEnumerable getLog2(ODataQueryOptions queryOptions)
{
try
{
- IQueryable queryable = _f4stHelperService.privGetLog2().AsQueryable();
- if (queryOptions.Filter != null)
- {
- queryable = queryOptions.Filter.ApplyTo(queryable, new ODataQuerySettings()).Cast();
- }
- return queryable;
+ return ApplyLogFilter(_f4stHelperService.privGetLog2(), queryOptions);
}
catch (Exception E)
{
@@ -528,12 +509,7 @@ namespace C4IT.F4SD
[HttpGet]
public int Log2Count(ODataQueryOptions queryOptions)
{
- IQueryable queryable = _f4stHelperService.privGetLog2().AsQueryable();
- if (queryOptions.Filter != null)
- {
- queryable = queryOptions.Filter.ApplyTo(queryable, new ODataQuerySettings()).Cast();
- }
- return queryable.Count();
+ return ApplyLogFilter(_f4stHelperService.privGetLog2(), queryOptions).Count();
}
[Route("{id}")]
@@ -542,6 +518,28 @@ namespace C4IT.F4SD
{
return _f4stHelperService.privGetLog2(id);
}
+
+ private static IEnumerable ApplyLogFilter(IEnumerable entries, ODataQueryOptions queryOptions)
+ {
+ var result = entries ?? Enumerable.Empty();
+ var filter = queryOptions?.Filter;
+
+ if (!string.IsNullOrWhiteSpace(filter))
+ {
+ result = result.Where(entry =>
+ (entry.Message?.IndexOf(filter, StringComparison.OrdinalIgnoreCase) ?? -1) >= 0 ||
+ (entry.logLvl?.IndexOf(filter, StringComparison.OrdinalIgnoreCase) ?? -1) >= 0 ||
+ (entry.Theme?.IndexOf(filter, StringComparison.OrdinalIgnoreCase) ?? -1) >= 0);
+ }
+
+ if (queryOptions?.Skip != null)
+ result = result.Skip(queryOptions.Skip.Value);
+
+ if (queryOptions?.Top != null)
+ result = result.Take(queryOptions.Top.Value);
+
+ return result;
+ }
}
public class cGetPropertyBody
diff --git a/F4SDM42WebApi/M42SandboxedExtension.targets b/F4SDM42WebApi/M42SandboxedExtension.targets
new file mode 100644
index 0000000..56bd181
--- /dev/null
+++ b/F4SDM42WebApi/M42SandboxedExtension.targets
@@ -0,0 +1,63 @@
+
+
+ $(MSBuildProjectDirectory)\BasePackage\Assemblies\
+ $(MSBuildProjectDirectory)\Root\InstalledPackages\Assemblies\$(M42ExtensionId)\
+ $(MSBuildProjectName)*.*
+ win-x64;linux-x64
+
+
+
+
+ <_M42RidList Include="$(M42DefaultRids)" />
+
+
+
+
+
+ true
+
+
+
+
+
+ <_M42FlatRoot Include="$(TargetDir)$(M42AssemblyPattern)" />
+
+
+
+
+
+
+
+
+
+
+
+ <_M42Rid Include="$(TargetDir)**\$(M42AssemblyPattern)" />
+
+
+
+
+
+
+
+
+
diff --git a/F4SDM42WebApi/package.json b/F4SDM42WebApi/package.json
new file mode 100644
index 0000000..23694de
--- /dev/null
+++ b/F4SDM42WebApi/package.json
@@ -0,0 +1,16 @@
+{
+ "Id": "d8cbffca-0b43-4acc-80ea-c944e7420cee",
+ "Vendor": "Consulting4IT GmbH",
+ "Name": "C4IT.F4SD.M42WebApi",
+ "Version": "1.3.0.0",
+ "Prerequisites": {
+ "MinimalRequiredProductVersion": "26.1.0",
+ "DependentPackages": []
+ },
+ "SetupDirectives": {
+ "MaintenanceMode": false,
+ "RecycleWebApplication": false,
+ "RestartM42WindowsServices": false
+ },
+ "Sandboxed": true
+}