58 Commits

Author SHA1 Message Date
Meik
b8ad580ae5 fix: sync configuration version from assembly 2026-07-03 08:04:21 +02:00
Meik
e5122c677f docs: document final 26.1 migration process 2026-07-03 00:35:20 +02:00
Meik
5d5f113d89 fix: update overview operation audiences 2026-07-02 23:57:12 +02:00
Meik
7588f83965 chore: name web service operation files by operation 2026-07-02 23:54:06 +02:00
Meik
ca2cf9581b fix: merge synchronized web service operations 2026-07-02 23:50:28 +02:00
Meik
8bfc3d497f chore: move query binding helpers 2026-07-02 23:06:50 +02:00
Meik
edbd34de61 fix: read missing parameters from query 2026-07-02 23:05:06 +02:00
Meik
93d1fc20b4 fix: restore legacy pickup route 2026-07-02 22:55:06 +02:00
Meik
a3a929e229 fix: bind legacy web api parameters from uri 2026-07-02 22:43:14 +02:00
Meik
9521693e27 fix: close isAlive responses 2026-07-02 10:33:05 +02:00
Meik
089c52fa99 chore: remove obsolete web api project files 2026-07-02 09:02:07 +02:00
Meik
10ef66ef25 chore: remove obsolete root matrix42 libraries 2026-07-02 08:56:29 +02:00
Meik
28c2733e5b build: restart matrix42 services after package install 2026-07-02 08:47:55 +02:00
Meik
31d2ff8e64 build: sign package assemblies in one invocation 2026-07-01 17:12:03 +02:00
Meik
a72bd5a012 build: declare release signed solution mappings 2026-07-01 17:08:19 +02:00
Meik
a6230478d3 test: remove unused logs odata requests 2026-07-01 16:58:14 +02:00
Meik
fc9b957591 docs: document matrix42 sandbox migration learnings 2026-07-01 16:49:41 +02:00
Meik
4526b0ebe4 test: use legacy query routes in postman 2026-07-01 16:38:55 +02:00
Meik
3124f6c97b test: derive overview relation request from counts 2026-07-01 16:31:12 +02:00
Meik
ec9fc5fb47 test: set direct link type to ticket 2026-07-01 16:26:48 +02:00
Meik
7c32c816ec fix: route web api parameters through path 2026-07-01 16:15:53 +02:00
Meik
49d1259a84 fix: bind web api get parameters from uri 2026-07-01 15:57:48 +02:00
Drechsler, Meik
196d638263 Bump Version 2026-07-01 15:30:45 +02:00
Meik
551a7f4017 fix: align direct link parameter names 2026-07-01 15:26:02 +02:00
Meik
2632c340c5 build: separate package artifacts by configuration 2026-07-01 15:18:33 +02:00
Meik
e089781795 build: add signed release configuration 2026-07-01 15:16:45 +02:00
Meik
6cbafa0f35 build: make release signing optional 2026-07-01 15:13:03 +02:00
Meik
5ba8d23bcc test: allow empty isalive wrapper body 2026-07-01 15:00:08 +02:00
Meik
c95a6c1145 build: sign release package assemblies 2026-07-01 14:58:38 +02:00
Meik
9a07024fdd build: derive package version from assembly version 2026-07-01 14:33:34 +02:00
Meik
c12c1ab7d2 fix: avoid null api responses 2026-07-01 14:23:28 +02:00
Meik
bdab9f37ba fix: return empty ticket list when no tickets found 2026-07-01 14:20:08 +02:00
Meik
6cb9e3b5fd fix: return native web api responses 2026-07-01 09:44:48 +02:00
Meik
80265ec1da test: cover overview counts scopes 2026-07-01 09:38:52 +02:00
Meik
8ba97b6baf test: capture ticket variables from list response 2026-07-01 09:35:47 +02:00
Meik
3ef49054ca chore: clean up journal migration diagnostics 2026-07-01 09:34:00 +02:00
Meik
e9be853362 test: use basic auth in postman collection 2026-07-01 09:29:19 +02:00
Meik
5e489cdae0 fix: load aurora search dependencies 2026-07-01 09:13:22 +02:00
Meik
1b780c4c44 test: add postman collection for web api 2026-07-01 09:08:12 +02:00
Meik
6f30452ed8 fix: load pandora services request properties 2026-07-01 08:56:54 +02:00
Meik
d1b41814a2 fix: register api explorer in sandbox host 2026-07-01 01:20:19 +02:00
Meik
f84d840e51 fix: simplify journal history service loading 2026-07-01 01:09:11 +02:00
Meik
258ca8a837 fix: load ticket history through journal portal api 2026-07-01 00:50:23 +02:00
Meik
45b8e1d223 fix: fallback journal history when storage resolution fails 2026-07-01 00:42:03 +02:00
Meik
d472923442 fix: isolate journal storage dependency in sandbox 2026-07-01 00:36:01 +02:00
Meik
62a44568d1 fix: allow journal notification proxy generation 2026-07-01 00:32:11 +02:00
Meik
1e3ec1cc22 fix: avoid journal service webapi explorer dependency 2026-07-01 00:29:04 +02:00
Meik
587a38b149 fix: load auth bizlogic for service connection 2026-07-01 00:18:26 +02:00
Meik
661c2b388c fix: load service connection dependencies for journal service 2026-07-01 00:14:06 +02:00
Meik
5acaaa75b4 fix: invoke journal service compatibly across 26.1 patches 2026-07-01 00:07:26 +02:00
Meik
3d6a8f514c diagnose: surface missing method details for ticket history 2026-06-30 23:57:59 +02:00
Meik
ec69a95c22 fix: remove legacy binding redirects for 26.1 2026-06-30 23:51:05 +02:00
Meik
0eca913fde fix: load journal bizlogic for m42 journal service 2026-06-30 19:59:00 +02:00
Meik
d0ac84f12c fix: use matrix42 journal service interface 2026-06-30 19:46:52 +02:00
Meik
d8fbd445d1 fix: avoid storage rendering for ticket history 2026-06-30 19:31:40 +02:00
Meik
66f1131863 fix: read ticket history without journal service DI 2026-06-30 19:13:07 +02:00
Meik
de9a226272 build: bump m42 package to 1.4.0.17 2026-06-30 18:57:21 +02:00
Meik
a9a9e28924 fix: avoid direct journal service method binding 2026-06-30 18:55:58 +02:00
42 changed files with 2302 additions and 281 deletions

View File

@@ -19,6 +19,7 @@ Global
Debug_and_copy|Any CPU = Debug_and_copy|Any CPU
Debug|Any CPU = Debug|Any CPU
Release_and_copy|Any CPU = Release_and_copy|Any CPU
Release_signed|Any CPU = Release_signed|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
@@ -28,6 +29,8 @@ Global
{D8CBFFCA-0B43-4ACC-80EA-C944E7420CEE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D8CBFFCA-0B43-4ACC-80EA-C944E7420CEE}.Release_and_copy|Any CPU.ActiveCfg = Release_and_copy|Any CPU
{D8CBFFCA-0B43-4ACC-80EA-C944E7420CEE}.Release_and_copy|Any CPU.Build.0 = Release_and_copy|Any CPU
{D8CBFFCA-0B43-4ACC-80EA-C944E7420CEE}.Release_signed|Any CPU.ActiveCfg = Release_signed|Any CPU
{D8CBFFCA-0B43-4ACC-80EA-C944E7420CEE}.Release_signed|Any CPU.Build.0 = Release_signed|Any CPU
{D8CBFFCA-0B43-4ACC-80EA-C944E7420CEE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D8CBFFCA-0B43-4ACC-80EA-C944E7420CEE}.Release|Any CPU.Build.0 = Release|Any CPU
{EB95E1FB-7A9E-4894-BD28-2D0BE2715EBE}.Debug_and_copy|Any CPU.ActiveCfg = Debug|Any CPU
@@ -36,6 +39,8 @@ Global
{EB95E1FB-7A9E-4894-BD28-2D0BE2715EBE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EB95E1FB-7A9E-4894-BD28-2D0BE2715EBE}.Release_and_copy|Any CPU.ActiveCfg = Release_and_copy|Any CPU
{EB95E1FB-7A9E-4894-BD28-2D0BE2715EBE}.Release_and_copy|Any CPU.Build.0 = Release_and_copy|Any CPU
{EB95E1FB-7A9E-4894-BD28-2D0BE2715EBE}.Release_signed|Any CPU.ActiveCfg = Release_signed|Any CPU
{EB95E1FB-7A9E-4894-BD28-2D0BE2715EBE}.Release_signed|Any CPU.Build.0 = Release_signed|Any CPU
{EB95E1FB-7A9E-4894-BD28-2D0BE2715EBE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EB95E1FB-7A9E-4894-BD28-2D0BE2715EBE}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection

View File

@@ -1,11 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
<configuration />

View File

@@ -9,6 +9,11 @@
<LangVersion>latestmajor</LangVersion>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
<Configurations>Debug;Release;Debug_and_copy;Release_and_copy;Release_signed</Configurations>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Release_signed'">
<Optimize>true</Optimize>
</PropertyGroup>
<ItemGroup>

View File

@@ -1,15 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Http" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

View File

@@ -62,6 +62,25 @@ $packageJson = [regex]::Replace($packageJson, '"Version"\s*:\s*"[^"]+"', "`"Vers
$packageJson = [regex]::Replace($packageJson, '"LastUpdatedDate"\s*:\s*"[^"]+"', "`"LastUpdatedDate`": `"$(Get-Date -Format 'yyyy-MM-ddTHH:mm:ss')`"")
[System.IO.File]::WriteAllText($packageJsonPath, $packageJson, [System.Text.UTF8Encoding]::new($true))
$configDataPath = Join-Path $packageDir 'install\1010_Config_Data\02-01-0080 C4IT_F4SDConfigurationType.dat'
if (-not (Test-Path -LiteralPath $configDataPath)) {
throw "Configuration data file not found: $configDataPath"
}
$configData = [System.IO.File]::ReadAllText($configDataPath)
$configData = [regex]::Replace(
$configData,
'(<C4IT_AddonConfigClassBase>[\s\S]*?<Version>)[^<]*(</Version>)',
"`${1}$PackageVersion`${2}",
[System.Text.RegularExpressions.RegexOptions]::Singleline
)
if ($configData -notmatch "<Version>$([regex]::Escape($PackageVersion))</Version>") {
throw "Could not update C4IT_F4SDConfigurationType Version to $PackageVersion in $configDataPath"
}
[System.IO.File]::WriteAllText($configDataPath, $configData, [System.Text.UTF8Encoding]::new($true))
$textFileExtensions = @('.json', '.xml', '.dat', '.type', '.class', '.config', '.host')
Get-ChildItem -LiteralPath $packageDir -Recurse -File |
Where-Object { $textFileExtensions -contains $_.Extension.ToLowerInvariant() } |

View File

@@ -1,7 +1,26 @@
<?xml version="1.0" encoding="utf-8" ?>
<host xmlns="urn:m42/host.config">
<modules>
<module assembly="C4ITF4SDM42WebApi" />
<module assembly="Matrix42.DataLayer.Persistence" />
<module assembly="Matrix42.Services.WebApi" />
<module assembly="Matrix42.ServiceRepository.BizLogic" />
<module assembly="Matrix42.Pandora.ServiceStore" />
<module assembly="Matrix42.Pandora.Persistence" />
<module assembly="Matrix42.Pandora.BizLogic" />
<module assembly="Matrix42.Pandora.Services" />
<module assembly="Matrix42.Distributed.Redis.Cache" />
<module assembly="Matrix42.StorageService.BizLogic" />
<module assembly="Matrix42.MsTeamsNotification.BizLogic" />
<module assembly="Matrix42.ServiceConnection.Persistence" />
<module assembly="Matrix42.Auth.BizLogic" />
<module assembly="Matrix42.ServiceConnection.BizLogic" />
<module assembly="Matrix42.Integration.Aurora.General" />
<module assembly="Matrix42.Integration.Aurora.Search.BizLogic" />
<module assembly="update4u.SPS.ComplianceRules.BizLogic" />
<module assembly="update4u.SPS.Security" />
<module assembly="Matrix42.BizLogic.Journal" />
<module assembly="Matrix42.ServiceManager.BizLogic" />
</modules>
<sections></sections>
</host>

View File

@@ -11,12 +11,17 @@
<LangVersion>latestmajor</LangVersion>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
<Configurations>Debug;Release;Debug_and_copy;Release_and_copy;Release_signed</Configurations>
<M42ExtensionId>6673a25d-33d6-4072-91d9-abed4be1a966</M42ExtensionId>
<M42AssemblyPattern>C4ITF4SD*.*</M42AssemblyPattern>
<M42PackageVersion>1.4.0.16</M42PackageVersion>
<M42BuildPackage>true</M42BuildPackage>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Release_signed'">
<Optimize>true</Optimize>
<M42SignAssemblies>true</M42SignAssemblies>
</PropertyGroup>
<ItemGroup>
<Reference Include="Matrix42.Common">
<HintPath>M42Libraries\26.1\Matrix42.Common.dll</HintPath>
@@ -66,6 +71,10 @@
<HintPath>M42Libraries\26.1\System.Net.Http.Formatting.dll</HintPath>
<Private>false</Private>
</Reference>
<Reference Include="System.Web.Http">
<HintPath>M42Libraries\26.1\System.Web.Http.dll</HintPath>
<Private>false</Private>
</Reference>
<Reference Include="update4u.SPS.DataLayer">
<HintPath>M42Libraries\26.1\update4u.SPS.DataLayer.dll</HintPath>
<Private>false</Private>
@@ -82,6 +91,7 @@
<ItemGroup>
<Compile Include="cM42LogEntry.cs" />
<Compile Include="F4SDM42DependencyRegistrator.cs" />
<Compile Include="F4SDHelperService.cs" />
<Compile Include="F4SDM42WebApiController.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />

View File

@@ -210,7 +210,7 @@ namespace C4IT.F4SD
if (activityTable?.Rows == null || activityTable.Rows.Count == 0)
{
LogEntry($"No activity entries found for userSid: '{userSid}'", LogLevels.Warning);
return null;
return new List<cF4SDTicketSummary>();
}
for (int i = 0; i < activityTable.Rows.Count; i++)
@@ -291,7 +291,7 @@ namespace C4IT.F4SD
catch (Exception E)
{
LogException(E);
return null;
return new List<cF4SDTicketSummary>();
}
finally
{
@@ -1407,26 +1407,9 @@ namespace C4IT.F4SD
try
{
await Task.Delay(0);
List<cTicketJournalItem> journalEntries = new List<cTicketJournalItem>();
var entries = F4SDM42WebApiController.defaultInstance.GetJournalService().GetJournalList(activityEOID, false, 0, 50, "<a href=\"#\" class=\"mx-object-journal--link {0} {1}\">{2}</a>", 120);
LogEntry($"{entries.Length} Journal entries found for ObjectID={activityEOID}", LogLevels.Debug);
for (int i = 0; i < entries.Length; i++)
{
Matrix42.Contracts.Platform.Data.JournalEntryInfo item = entries[i];
LogEntry($"Journal entry {i + 1}/{entries.Length}: ID={item.Id}, CreatedDate={item.CreatedDate}, CreatedBy={item.Creator}, Header={item.Header}", LogLevels.Debug);
journalEntries.Add(new cTicketJournalItem()
{
JournalId = item.Id,
ActivityObjectId = activityEOID,
CreatedBy = item.Creator,
CreationDate = (DateTime)item.CreatedDate,
DescriptionHtml = item.Text,
Description = Matrix42.Common.Html.HtmlConverter.ConvertHtmlToPlainText(item.Text),
Header = item.Header,
IsVisibleForUser = item.VisibleInPortal
});
}
return journalEntries;
var entries = LoadJournalEntries(activityEOID);
LogEntry($"{entries.Count} Journal entries found for ObjectID={activityEOID}", LogLevels.Debug);
return CreateTicketJournalItems(activityEOID, entries);
}
catch (Exception E)
{
@@ -1439,6 +1422,151 @@ namespace C4IT.F4SD
}
}
internal static List<cTicketJournalItem> CreateTicketJournalItems(Guid activityEOID, IReadOnlyList<Matrix42.Contracts.Platform.Data.JournalEntryInfo> entries)
{
List<cTicketJournalItem> journalEntries = new List<cTicketJournalItem>();
for (int i = 0; i < entries.Count; i++)
{
Matrix42.Contracts.Platform.Data.JournalEntryInfo item = entries[i];
var text = item.Text ?? string.Empty;
var createdDate = item.CreatedDate ?? DateTime.MinValue;
LogEntry($"Journal entry {i + 1}/{entries.Count}: ID={item.Id}, CreatedDate={createdDate}, CreatedBy={item.Creator}, Header={item.Header}", LogLevels.Debug);
journalEntries.Add(new cTicketJournalItem()
{
JournalId = item.Id,
ActivityObjectId = activityEOID,
CreatedBy = item.Creator,
CreationDate = createdDate,
DescriptionHtml = text,
Description = string.IsNullOrEmpty(text) ? string.Empty : Matrix42.Common.Html.HtmlConverter.ConvertHtmlToPlainText(text),
Header = item.Header,
IsVisibleForUser = item.VisibleInPortal
});
}
return journalEntries;
}
private static IReadOnlyList<Matrix42.Contracts.Platform.Data.JournalEntryInfo> LoadJournalEntries(Guid activityEOID)
{
var journalService = F4SDM42WebApiController.defaultInstance.GetJournalService();
var serviceType = journalService.GetType();
var objectLinkTemplate = "<a href=\"#\" class=\"mx-object-journal--link {0} {1}\">{2}</a>";
var methods = serviceType
.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
.Where(IsJournalReaderMethod)
.OrderByDescending(method => method.GetParameters().Length)
.ToList();
foreach (var method in methods)
{
if (!TryBuildJournalListArguments(method, activityEOID, objectLinkTemplate, out var arguments))
continue;
try
{
var result = method.Invoke(journalService, arguments);
if (result is Matrix42.Contracts.Platform.Data.JournalEntryInfo[] arrayResult)
return arrayResult;
if (result is IEnumerable<Matrix42.Contracts.Platform.Data.JournalEntryInfo> enumerableResult)
return enumerableResult.ToList();
throw new MissingMethodException($"IJournalService.GetJournalList returned unsupported type '{result?.GetType().FullName ?? "<null>"}'.");
}
catch (TargetInvocationException ex) when (ex.InnerException != null)
{
throw ex.InnerException;
}
}
throw new MissingMethodException($"No compatible IJournalService.GetJournalList overload was found on '{serviceType.FullName}'. Available overloads: {string.Join("; ", methods.Select(FormatMethodSignature))}");
}
private static bool IsJournalReaderMethod(MethodInfo method)
{
var methodName = method.Name;
if (methodName.Contains("."))
methodName = methodName.Substring(methodName.LastIndexOf(".", StringComparison.Ordinal) + 1);
if (!(methodName.StartsWith("Get", StringComparison.OrdinalIgnoreCase) || methodName.StartsWith("Load", StringComparison.OrdinalIgnoreCase)))
return false;
if (!methodName.Contains("Journal", StringComparison.OrdinalIgnoreCase))
return false;
if (!method.GetParameters().Any(parameter => parameter.ParameterType == typeof(Guid)))
return false;
var returnType = method.ReturnType;
if (returnType.IsArray)
return returnType.GetElementType()?.FullName == typeof(Matrix42.Contracts.Platform.Data.JournalEntryInfo).FullName;
if (returnType.FullName == typeof(Matrix42.Contracts.Platform.Data.JournalEntryInfo).FullName)
return true;
return returnType.GetInterfaces()
.Where(type => type.IsGenericType)
.Select(type => type.GetGenericArguments().FirstOrDefault())
.Any(type => type?.FullName == typeof(Matrix42.Contracts.Platform.Data.JournalEntryInfo).FullName);
}
private static bool TryBuildJournalListArguments(MethodInfo method, Guid activityEOID, string objectLinkTemplate, out object[] arguments)
{
var parameters = method.GetParameters();
arguments = new object[parameters.Length];
for (int i = 0; i < parameters.Length; i++)
{
var parameter = parameters[i];
var parameterType = parameter.ParameterType;
var parameterName = parameter.Name ?? string.Empty;
var lowerName = parameterName.ToLowerInvariant();
if (parameterType == typeof(Guid))
{
arguments[i] = activityEOID;
}
else if (parameterType == typeof(bool))
{
arguments[i] = false;
}
else if (parameterType == typeof(int))
{
if (lowerName.Contains("time"))
arguments[i] = 120;
else if (lowerName.Contains("count") || lowerName.Contains("take") || lowerName.Contains("limit") || lowerName.Contains("size"))
arguments[i] = 50;
else
arguments[i] = 0;
}
else if (parameterType == typeof(string))
{
arguments[i] = lowerName.Contains("template") || lowerName.Contains("link") ? objectLinkTemplate : null;
}
else if (parameterType == typeof(string[]))
{
arguments[i] = null;
}
else if (parameter.HasDefaultValue)
{
arguments[i] = parameter.DefaultValue;
}
else
{
return false;
}
}
return true;
}
private static string FormatMethodSignature(MethodInfo method)
{
return $"{method.ReturnType.FullName} {method.Name}({string.Join(", ", method.GetParameters().Select(parameter => $"{parameter.ParameterType.FullName} {parameter.Name}"))})";
}
internal async Task<bool> updateActivitySolution(Guid objectId, string solutionHtml)
{

View File

@@ -0,0 +1,38 @@
using System;
using System.Web.Http;
using System.Web.Http.Description;
using Matrix42.Hosting.Contracts;
using C4IT.Logging;
using static C4IT.Logging.cLogManager;
namespace C4IT.F4SD
{
public class F4SDM42DependencyRegistrator : IDependencyRegistrator
{
public void Register(IDependencyContainer container, IDependencyResolver resolver)
{
if (container == null)
throw new ArgumentNullException(nameof(container));
if (resolver == null)
throw new ArgumentNullException(nameof(resolver));
try
{
if (resolver.TryGet(typeof(IApiExplorer)) != null)
return;
}
catch
{
// Existing mapping is incomplete in the sandbox host. Register a concrete instance below.
}
var httpConfiguration = new HttpConfiguration();
container.RegisterInstance(typeof(IApiExplorer), new ApiExplorer(httpConfiguration));
LogEntry("Registered System.Web.Http.Description.IApiExplorer for Matrix42 sandbox host.", LogLevels.Debug);
}
}
}

View File

@@ -64,7 +64,6 @@ namespace C4IT.F4SD
{
try
{
//System.Diagnostics.Debugger.Launch();
lock (initLock)
{
if (IsInitialized || F4SDM42LogsWebApiController.IsInitialized)
@@ -81,11 +80,6 @@ namespace C4IT.F4SD
catch { };
}
internal IJournalService GetJournalService()
{
return GetRequiredService<IJournalService>();
}
private T GetRequiredService<T>() where T : class
{
var service = _resolver.TryGet<T>();
@@ -95,26 +89,40 @@ namespace C4IT.F4SD
throw new InvalidOperationException($"Required Matrix42 service is not registered: {typeof(T).FullName}");
}
internal IJournalService GetJournalService()
{
return GetRequiredService<IJournalService>();
}
[Route("getDirectLinkCreateTicket"), HttpGet]
public async Task<F4SDHelperService.DirectLink> getDirectLinkCreateTicket(string sid = "", string assetname = "")
public async Task<F4SDHelperService.DirectLink> getDirectLinkCreateTicket([FromUri] string sid = "", [FromUri] string assetname = "")
{
await Task.Delay(0);
return await _f4stHelperService.getDirectLinkCreateTicket(sid, assetname);
sid = QueryValue(sid, nameof(sid));
assetname = QueryValue(assetname, nameof(assetname));
return await _f4stHelperService.getDirectLinkCreateTicket(sid, assetname)
?? new F4SDHelperService.DirectLink();
}
[Route("getDirectLinkF4SD"), HttpGet]
public async Task<string> getDirectLinkF4SD(Guid EOID, string Type)
public async Task<string> getDirectLinkF4SD([FromUri] Guid eoid, [FromUri] string type)
{
return await _f4stHelperService.getDirectLinkF4SD(EOID, Type);
eoid = QueryValue(eoid, nameof(eoid));
type = QueryValue(type, nameof(type));
return await _f4stHelperService.getDirectLinkF4SD(eoid, type) ?? string.Empty;
}
[Route("getTicketList"), HttpGet]
public async Task<List<cF4SDTicketSummary>> getTicketList(
string sid,
int hours,
int queueoption = 0,
string queues = ""
[FromUri] string sid,
[FromUri] int hours,
[FromUri] int queueoption = 0,
[FromUri] string queues = ""
)
{
sid = QueryValue(sid, nameof(sid));
hours = QueryValue(hours, nameof(hours));
queueoption = QueryValue(queueoption, nameof(queueoption));
queues = QueryValue(queues, nameof(queues));
var decodedPairs = ParseQueues(queues);
// Nun weiterreichen an Service
@@ -123,35 +131,42 @@ namespace C4IT.F4SD
hours,
queueoption,
decodedPairs
);
) ?? new List<cF4SDTicketSummary>();
}
[Route("getTicketDetails"), HttpGet]
public async Task<cF4SDTicket> getTicketDetails(Guid objectId)
public async Task<cF4SDTicket> getTicketDetails([FromUri] Guid objectId)
{
objectId = QueryValue(objectId, nameof(objectId));
var tickets = await _f4stHelperService.getTicketDetails(new List<Guid>() { objectId });
if (tickets.Count > 0)
if (tickets?.Count > 0)
return tickets[0];
else
return null;
return new cF4SDTicket { TicketObjectId = objectId };
}
[Route("getTicketHistory"), HttpGet]
public async Task<List<cTicketJournalItem>> getTicketHistory(Guid objectId)
public async Task<List<cTicketJournalItem>> getTicketHistory([FromUri] Guid objectId)
{
return await _f4stHelperService.GetJournalEntries(objectId);
objectId = QueryValue(objectId, nameof(objectId));
return await _f4stHelperService.GetJournalEntries(objectId) ?? new List<cTicketJournalItem>();
}
[Route("getTicketOverviewCounts"), HttpGet]
public async Task<F4SDHelperService.TicketOverviewCountsResult> getTicketOverviewCounts(
string sid,
string scope = "personal",
string keys = "",
int queueoption = 0,
string queues = ""
[FromUri] string sid,
[FromUri] string scope = "personal",
[FromUri] string keys = "",
[FromUri] int queueoption = 0,
[FromUri] string queues = ""
)
{
sid = QueryValue(sid, nameof(sid));
scope = QueryValue(scope, nameof(scope));
keys = QueryValue(keys, nameof(keys));
queueoption = QueryValue(queueoption, nameof(queueoption));
queues = QueryValue(queues, nameof(queues));
var parsedKeys = (keys ?? string.Empty)
.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
.Select(key => key.Trim())
@@ -159,7 +174,8 @@ namespace C4IT.F4SD
.ToList();
var decodedQueues = ParseQueues(queues);
return await _f4stHelperService.getTicketOverviewCounts(sid, scope, parsedKeys, queueoption, decodedQueues);
return await _f4stHelperService.getTicketOverviewCounts(sid, scope, parsedKeys, queueoption, decodedQueues)
?? new F4SDHelperService.TicketOverviewCountsResult();
}
[Route("getTicketOverviewCountsByRoles"), HttpPost]
@@ -183,21 +199,28 @@ namespace C4IT.F4SD
parsedKeys,
request?.QueueOption ?? 0,
decodedQueues
);
) ?? new F4SDHelperService.TicketOverviewCountsByRoleResult();
}
[Route("getTicketOverviewRelations"), HttpGet]
public async Task<List<F4SDHelperService.TicketOverviewRelationDto>> getTicketOverviewRelations(
string sid,
string scope = "personal",
string key = "",
int count = 0,
int queueoption = 0,
string queues = ""
[FromUri] string sid,
[FromUri] string scope = "personal",
[FromUri] string key = "",
[FromUri] int count = 0,
[FromUri] int queueoption = 0,
[FromUri] string queues = ""
)
{
sid = QueryValue(sid, nameof(sid));
scope = QueryValue(scope, nameof(scope));
key = QueryValue(key, nameof(key));
count = QueryValue(count, nameof(count));
queueoption = QueryValue(queueoption, nameof(queueoption));
queues = QueryValue(queues, nameof(queues));
var decodedQueues = ParseQueues(queues);
return await _f4stHelperService.getTicketOverviewRelations(sid, scope, key, count, queueoption, decodedQueues);
return await _f4stHelperService.getTicketOverviewRelations(sid, scope, key, count, queueoption, decodedQueues)
?? new List<F4SDHelperService.TicketOverviewRelationDto>();
}
/*
[Route("updateActivitySolution/{objectId}"), HttpPost]
@@ -211,9 +234,12 @@ namespace C4IT.F4SD
*/
[Route("getPickup/{name}"), HttpGet]
//[CacheOutput(UseETAG = true)]
public async Task<HttpResponseMessage> getPickup(string name, EntityEnumerationVisibilityMode mode = EntityEnumerationVisibilityMode.None, Int32 group = -1)
public async Task<EntityEnumeration> getPickup([FromUri] string name, [FromUri] EntityEnumerationVisibilityMode mode = EntityEnumerationVisibilityMode.None, [FromUri] Int32 group = -1)
{
await Task.Delay(0);
name = QueryValue(name, nameof(name));
mode = QueryValue(mode, nameof(mode));
group = QueryValue(group, nameof(group));
EntityEnumeration enumerationTemp = GetEnumeration(name, mode);
var vals = enumerationTemp.Values;
@@ -234,7 +260,7 @@ 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 enumeration;
}
[Route("getMyRoleMemberships"), HttpGet]
@@ -245,12 +271,15 @@ namespace C4IT.F4SD
throw new UnauthorizedAccessException("Cannot determine the interactive Matrix42 user.");
var filter = AsqlHelper.BuildInCondition("ID", new Guid[] { userId });
return await _f4stHelperService.UserPermissionsInfo(filter);
return await _f4stHelperService.UserPermissionsInfo(filter) ?? new UserPermissionsInfo();
}
[HttpGet]
[Route("getRoleMemberships")]
public async Task<object> getRoleMemberships(string sid = "", string upn = "", Guid? id = null)
public async Task<object> getRoleMemberships([FromUri] string sid = "", [FromUri] string upn = "", [FromUri] Guid? id = null)
{
sid = QueryValue(sid, nameof(sid));
upn = QueryValue(upn, nameof(upn));
id = QueryValue(id, nameof(id));
var filter = "";
if (id != null && id.Value != Guid.Empty)
@@ -268,12 +297,10 @@ namespace C4IT.F4SD
if (!string.IsNullOrEmpty(filter))
{
return await _f4stHelperService.UserPermissionsInfo(filter);
}
else
{
return null;
return await _f4stHelperService.UserPermissionsInfo(filter) ?? new UserPermissionsInfo();
}
return new UserPermissionsInfo();
}
public class TicketOverviewCountsByRolesRequest
@@ -374,6 +401,38 @@ namespace C4IT.F4SD
?? Guid.Empty;
}
private string GetQueryValue(string name)
{
return Request?.GetQueryNameValuePairs()
.FirstOrDefault(pair => string.Equals(pair.Key, name, StringComparison.OrdinalIgnoreCase))
.Value;
}
private string QueryValue(string value, string name)
{
return GetQueryValue(name) ?? value ?? string.Empty;
}
private int QueryValue(int value, string name)
{
return int.TryParse(GetQueryValue(name), out var parsed) ? parsed : value;
}
private Guid QueryValue(Guid value, string name)
{
return Guid.TryParse(GetQueryValue(name), out var parsed) ? parsed : value;
}
private Guid? QueryValue(Guid? value, string name)
{
return Guid.TryParse(GetQueryValue(name), out var parsed) ? parsed : value;
}
private TEnum QueryValue<TEnum>(TEnum value, string name) where TEnum : struct
{
return Enum.TryParse<TEnum>(GetQueryValue(name), true, out var parsed) ? parsed : value;
}
private static List<cApiM42TicketQueueInfo> ParseQueues(string queues)
{
return (queues ?? string.Empty)
@@ -396,26 +455,33 @@ namespace C4IT.F4SD
}
[Route("isAlive"), HttpGet]
public HttpResponseMessage isAlive()
public IHttpActionResult isAlive()
{
return new HttpResponseMessage(HttpStatusCode.NoContent);
var response = new HttpResponseMessage(HttpStatusCode.NoContent)
{
RequestMessage = Request
};
response.Headers.ConnectionClose = true;
return ResponseMessage(response);
}
[Route("loglevel"), HttpGet]
public async Task<string> setDebugMode(string debug = "0")
public async Task<string> setDebugMode([FromUri] string debug = "0")
{
var CM = MethodBase.GetCurrentMethod();
LogMethodBegin(CM);
try
{
await Task.Delay(0);
debug = QueryValue(debug, nameof(debug));
DefaultLogger.Manager.Level = debug == "1" || debug.Equals("true", StringComparison.OrdinalIgnoreCase) ? LogLevels.Debug : LogLevels.Info;
return DefaultLogger.Manager.Level.ToString();
}
catch (Exception E)
{
LogException(E);
return null;
return string.Empty;
}
finally
{
@@ -424,16 +490,23 @@ namespace C4IT.F4SD
}
[Route("log"), HttpGet]
public HttpResponseMessage getLog(string download = "0", int count = 50, string filter = "")
public IHttpActionResult getLog([FromUri] string download = "0", [FromUri] int count = 50, [FromUri] string filter = "")
{
try
{
return _f4stHelperService.privGetLog(download, count, Request, filter);
download = QueryValue(download, nameof(download));
count = QueryValue(count, nameof(count));
filter = QueryValue(filter, nameof(filter));
var response = _f4stHelperService.privGetLog(download, count, Request, filter);
if (response == null)
return new StatusCodeResult(HttpStatusCode.NoContent);
return new ResponseMessageResult(response);
}
catch (Exception E)
{
LogException(E);
return null;
return new StatusCodeResult(HttpStatusCode.InternalServerError);
}
}
}
@@ -483,7 +556,7 @@ namespace C4IT.F4SD
catch (Exception E)
{
LogException(E);
return null;
return Enumerable.Empty<cM42LogEntry>();
}
}
@@ -498,7 +571,7 @@ namespace C4IT.F4SD
[OperationType(OperationType.GetObject)]
public cM42LogEntry GetClass(int id)
{
return _f4stHelperService.privGetLog2(id);
return _f4stHelperService.privGetLog2(id) ?? new cM42LogEntry { LineNumber = id };
}
private static IEnumerable<cM42LogEntry> ApplyLogFilter(IEnumerable<cM42LogEntry> entries, ODataQueryOptions<cM42LogEntry> queryOptions)

View File

@@ -6,8 +6,17 @@
<M42DefaultRids Condition="'$(M42DefaultRids)' == ''">win-x64;linux-x64</M42DefaultRids>
<M42PackageName Condition="'$(M42PackageName)' == ''">C4IT - F4SD M42 ESM Integration Configuration Package</M42PackageName>
<M42PackageTemplateDir Condition="'$(M42PackageTemplateDir)' == ''">$(MSBuildProjectDirectory)\..\PackageTemplate</M42PackageTemplateDir>
<M42PackageOutputRoot Condition="'$(M42PackageOutputRoot)' == ''">$(MSBuildProjectDirectory)\..\artifacts</M42PackageOutputRoot>
<M42PackageOutputRoot Condition="'$(M42PackageOutputRoot)' == ''">$(MSBuildProjectDirectory)\..\artifacts\$(Configuration)</M42PackageOutputRoot>
<M42PackageBuildScript Condition="'$(M42PackageBuildScript)' == ''">$(MSBuildProjectDirectory)\BuildM42Package.ps1</M42PackageBuildScript>
<M42SignAssemblies Condition="'$(M42SignAssemblies)' == ''">false</M42SignAssemblies>
<M42SignTool Condition="'$(M42SignTool)' == ''">$(MSBuildProjectDirectory)\..\..\..\Common Code\Tools\signtool.exe</M42SignTool>
<M42SignTimestampUrl Condition="'$(M42SignTimestampUrl)' == ''">http://rfc3161timestamp.globalsign.com/advanced</M42SignTimestampUrl>
<M42SignDescription Condition="'$(M42SignDescription)' == ''">C4IT - F4SD - WebApi for M42</M42SignDescription>
<M42SignOptions Condition="'$(M42SignOptions)' == ''">/a</M42SignOptions>
<_M42SignCertificateArgs Condition="'$(M42SignCertificateFile)' != '' AND '$(M42SignCertificatePassword)' != ''">/f "$(M42SignCertificateFile)" /p "$(M42SignCertificatePassword)"</_M42SignCertificateArgs>
<_M42SignCertificateArgs Condition="'$(M42SignCertificateFile)' != '' AND '$(M42SignCertificatePassword)' == ''">/f "$(M42SignCertificateFile)"</_M42SignCertificateArgs>
<_M42SignCertificateArgs Condition="'$(_M42SignCertificateArgs)' == '' AND '$(M42SignCertificateThumbprint)' != ''">/sha1 "$(M42SignCertificateThumbprint)"</_M42SignCertificateArgs>
<_M42SignCertificateArgs Condition="'$(_M42SignCertificateArgs)' == ''">$(M42SignOptions)</_M42SignCertificateArgs>
</PropertyGroup>
<Target Name="M42_BuildAllRids"
@@ -75,16 +84,46 @@
Condition="'$(M42RootAssembliesDir)' != ''" />
</Target>
<Target Name="M42_SignPackageAssemblies"
BeforeTargets="M42_BuildPackage"
Condition="'$(RuntimeIdentifier)' == '' AND '$(M42SignAssemblies)' == 'true'">
<ItemGroup>
<_M42AssembliesToSign Include="$(M42BasePackageAssembliesDir)\**\*.dll" />
</ItemGroup>
<Error Condition="!Exists('$(M42SignTool)')"
Text="signtool.exe was not found: $(M42SignTool). Set M42SignTool or disable signing with /p:M42SignAssemblies=false." />
<Message Importance="High"
Text="Signing Matrix42 package assemblies with $(M42SignTool)." />
<PropertyGroup>
<_M42AssembliesToSignArgs>@(_M42AssembliesToSign->'&quot;%(FullPath)&quot;', ' ')</_M42AssembliesToSignArgs>
</PropertyGroup>
<Exec Condition="'@(_M42AssembliesToSign)' != ''"
Command="&quot;$(M42SignTool)&quot; sign $(_M42SignCertificateArgs) /tr &quot;$(M42SignTimestampUrl)&quot; /td SHA256 /fd SHA256 /d &quot;$(M42SignDescription)&quot; $(_M42AssembliesToSignArgs)" />
</Target>
<Target Name="M42_BuildPackage"
AfterTargets="Build"
Condition="'$(RuntimeIdentifier)' == '' AND '$(M42BuildPackage)' == 'true'">
<Error Condition="'$(M42PackageVersion)' == ''"
Text="M42PackageVersion is required when M42BuildPackage=true." />
<Error Condition="!Exists('$(M42PackageTemplateDir)\package.json')"
Text="M42 package template not found: $(M42PackageTemplateDir)" />
<Error Condition="!Exists('$(M42BasePackageAssembliesDir)\C4ITF4SDM42WebApi.dll')"
Text="M42 base package assemblies are missing: $(M42BasePackageAssembliesDir)" />
<Exec Command="powershell.exe -NoProfile -ExecutionPolicy Bypass -File &quot;$(M42PackageBuildScript)&quot; -TemplateDir &quot;$(M42PackageTemplateDir)&quot; -AssembliesDir &quot;$(M42BasePackageAssembliesDir)&quot; -OutputRoot &quot;$(M42PackageOutputRoot)&quot; -PackageName &quot;$(M42PackageName)&quot; -PackageVersion &quot;$(M42PackageVersion)&quot;" />
<GetAssemblyIdentity AssemblyFiles="$(M42BasePackageAssembliesDir)\C4ITF4SDM42WebApi.dll">
<Output TaskParameter="Assemblies" ItemName="_M42PackageAssemblyIdentity" />
</GetAssemblyIdentity>
<PropertyGroup>
<_M42PackageAssemblyVersion>@(_M42PackageAssemblyIdentity->'%(Version)')</_M42PackageAssemblyVersion>
</PropertyGroup>
<Error Condition="'$(_M42PackageAssemblyVersion)' == ''"
Text="Could not read AssemblyVersion from $(M42BasePackageAssembliesDir)\C4ITF4SDM42WebApi.dll." />
<Exec Command="powershell.exe -NoProfile -ExecutionPolicy Bypass -File &quot;$(M42PackageBuildScript)&quot; -TemplateDir &quot;$(M42PackageTemplateDir)&quot; -AssembliesDir &quot;$(M42BasePackageAssembliesDir)&quot; -OutputRoot &quot;$(M42PackageOutputRoot)&quot; -PackageName &quot;$(M42PackageName)&quot; -PackageVersion &quot;$(_M42PackageAssemblyVersion)&quot;" />
</Target>
</Project>

View File

@@ -1,10 +0,0 @@
set ProductName="C4IT First Aid Service Desk Matrix42 ESM Addon"
set SignTool=..\..\..\Common Code\Tools\signtool.exe
set TimeStamp=http://rfc3161timestamp.globalsign.com/advanced
"%SignTool%" sign /a /tr %TimeStamp% /td SHA256 /fd SHA256 /d %ProductName% ".\bin\Release\C4ITF4SDM42WebApi.dll" ".\bin\Release\C4ITF4SDM42WebApiHelper.dll"
pause

View File

@@ -1,16 +0,0 @@
{
"Id": "6673a25d-33d6-4072-91d9-abed4be1a966",
"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
}

View File

@@ -5,17 +5,20 @@
<Script Major="2" Minor="1" Build="30" Type="dat" Name="0030_Navigation_C4IT_Addon_ServiceDesk.dat" PackageVersion="1.4" Mode="Merge" Register="false" FilePath="install\0000_Global\0030_Navigation_C4IT_Addon_ServiceDesk.dat" />
<Script Major="2" Minor="1" Build="40" Type="dat" Name="0040_Navigation_C4IT_Addon_ServiceCatalog.dat" PackageVersion="1.4" Mode="Merge" Register="false" FilePath="install\0000_Global\0040_Navigation_C4IT_Addon_ServiceCatalog.dat" />
<Script Major="2" Minor="1" Build="50" Type="dat" Name="02-01-0050 PLSLServiceTypeWebAPI.dat" PackageVersion="1.4" Mode="Merge" Register="false" FilePath="install\0001_WebAPIService\02-01-0050 PLSLServiceTypeWebAPI.dat" />
<Script Major="2" Minor="1" Build="60" Type="dat" Name="02-01-0060 PLSLWebServiceOperationType.dat" PackageVersion="1.4" Mode="Merge" Register="false" FilePath="install\0002_WebServiceOperation\02-01-0060 PLSLWebServiceOperationType.dat" />
<Script Major="2" Minor="1" Build="70" Type="dat" Name="02-01-0070 PLSLWebServiceOperationType.dat" PackageVersion="1.4" Mode="Merge" Register="false" FilePath="install\0002_WebServiceOperation\02-01-0070 PLSLWebServiceOperationType.dat" />
<Script Major="2" Minor="1" Build="80" Type="dat" Name="02-01-0080 PLSLWebServiceOperationType.dat" PackageVersion="1.4" Mode="Merge" Register="false" FilePath="install\0002_WebServiceOperation\02-01-0080 PLSLWebServiceOperationType.dat" />
<Script Major="2" Minor="1" Build="90" Type="dat" Name="02-01-0090 PLSLWebServiceOperationType.dat" PackageVersion="1.4" Mode="Merge" Register="false" FilePath="install\0002_WebServiceOperation\02-01-0090 PLSLWebServiceOperationType.dat" />
<Script Major="2" Minor="1" Build="100" Type="dat" Name="02-01-0100 PLSLWebServiceOperationType.dat" PackageVersion="1.4" Mode="Merge" Register="false" FilePath="install\0002_WebServiceOperation\02-01-0100 PLSLWebServiceOperationType.dat" />
<Script Major="2" Minor="1" Build="110" Type="dat" Name="02-01-0110 PLSLWebServiceOperationType.dat" PackageVersion="1.4" Mode="Merge" Register="false" FilePath="install\0002_WebServiceOperation\02-01-0110 PLSLWebServiceOperationType.dat" />
<Script Major="2" Minor="1" Build="120" Type="dat" Name="02-01-0120 PLSLWebServiceOperationType.dat" PackageVersion="1.4" Mode="Merge" Register="false" FilePath="install\0002_WebServiceOperation\02-01-0120 PLSLWebServiceOperationType.dat" />
<Script Major="2" Minor="1" Build="130" Type="dat" Name="02-01-0130 PLSLWebServiceOperationType.dat" PackageVersion="1.4" Mode="Merge" Register="false" FilePath="install\0002_WebServiceOperation\02-01-0130 PLSLWebServiceOperationType.dat" />
<Script Major="2" Minor="1" Build="60" Type="dat" Name="getdirectlinkcreateticket.dat" PackageVersion="1.4" Mode="Merge" Register="false" FilePath="install\0002_WebServiceOperation\getdirectlinkcreateticket.dat" />
<Script Major="2" Minor="1" Build="70" Type="dat" Name="getdirectlinkf4sd.dat" PackageVersion="1.4" Mode="Merge" Register="false" FilePath="install\0002_WebServiceOperation\getdirectlinkf4sd.dat" />
<Script Major="2" Minor="1" Build="80" Type="dat" Name="getlog.dat" PackageVersion="1.4" Mode="Merge" Register="false" FilePath="install\0002_WebServiceOperation\getlog.dat" />
<Script Major="2" Minor="1" Build="90" Type="dat" Name="getticketdetails.dat" PackageVersion="1.4" Mode="Merge" Register="false" FilePath="install\0002_WebServiceOperation\getticketdetails.dat" />
<Script Major="2" Minor="1" Build="100" Type="dat" Name="gettickethistory.dat" PackageVersion="1.4" Mode="Merge" Register="false" FilePath="install\0002_WebServiceOperation\gettickethistory.dat" />
<Script Major="2" Minor="1" Build="110" Type="dat" Name="getticketlist.dat" PackageVersion="1.4" Mode="Merge" Register="false" FilePath="install\0002_WebServiceOperation\getticketlist.dat" />
<Script Major="2" Minor="1" Build="120" Type="dat" Name="isalive.dat" PackageVersion="1.4" Mode="Merge" Register="false" FilePath="install\0002_WebServiceOperation\isalive.dat" />
<Script Major="2" Minor="1" Build="130" Type="dat" Name="setdebugmode.dat" PackageVersion="1.4" Mode="Merge" Register="false" FilePath="install\0002_WebServiceOperation\setdebugmode.dat" />
<Script Major="2" Minor="1" Build="140" Type="dat" Name="getmyrolememberships.dat" PackageVersion="1.4" Mode="Merge" Register="false" FilePath="install\0002_WebServiceOperation\getmyrolememberships.dat" />
<Script Major="2" Minor="1" Build="150" Type="dat" Name="getpickup.dat" PackageVersion="1.4" Mode="Merge" Register="false" FilePath="install\0002_WebServiceOperation\getpickup.dat" />
<Script Major="2" Minor="1" Build="160" Type="dat" Name="getrolememberships.dat" PackageVersion="1.4" Mode="Merge" Register="false" FilePath="install\0002_WebServiceOperation\getrolememberships.dat" />
<Script Major="2" Minor="1" Build="161" Type="dat" Name="getticketoverviewcounts.dat" PackageVersion="1.4" Mode="Merge" Register="false" FilePath="install\0002_WebServiceOperation\getticketoverviewcounts.dat" />
<Script Major="2" Minor="1" Build="162" Type="dat" Name="getticketoverviewcountsbyroles.dat" PackageVersion="1.4" Mode="Merge" Register="false" FilePath="install\0002_WebServiceOperation\getticketoverviewcountsbyroles.dat" />
<Script Major="2" Minor="1" Build="163" Type="dat" Name="getticketoverviewrelations.dat" PackageVersion="1.4" Mode="Merge" Register="false" FilePath="install\0002_WebServiceOperation\getticketoverviewrelations.dat" />
<Script Major="2" Minor="1" Build="170" Type="dat" Name="02-01-0150 PDRActionType.dat" PackageVersion="1.4" Mode="Merge" Register="false" FilePath="install\0003_UUXActions\02-01-0150 PDRActionType.dat" />
<Script Major="2" Minor="1" Build="180" Type="dat" Name="02-01-0160 PDRActionType.dat" PackageVersion="1.4" Mode="Merge" Register="false" FilePath="install\0003_UUXActions\02-01-0160 PDRActionType.dat" />
<Script Major="2" Minor="1" Build="190" Type="dat" Name="02-01-0170 PDRActionType.dat" PackageVersion="1.4" Mode="Merge" Register="false" FilePath="install\0003_UUXActions\02-01-0170 PDRActionType.dat" />
@@ -42,4 +45,4 @@
<Script Major="2" Minor="1" Build="400" Type="dat" Name="Ticket.Transform_Audience.dat" PackageVersion="1.4" Mode="Merge" Register="false" FilePath="install\1090_Audience\Ticket.Transform_Audience.dat" />
<Script Major="2" Minor="1" Build="410" Type="type" Name="02-01-0020 C4IT_F4SDConfigurationType_create-C4IT_F4SDConfigurationType.type" PackageVersion="1.4" Mode="Merge" Register="false" FilePath="install\ZZZ_SchemaUpdates\02-01-0020 C4IT_F4SDConfigurationType_create-C4IT_F4SDConfigurationType.type" />
<Script Major="2" Minor="1" Build="420" Type="class" Name="C4IT_AddonConfigClassBase-C4IT_AddonConfigClassBase.class" PackageVersion="1.4" Mode="Merge" Register="false" FilePath="install\ZZZ_SchemaUpdates\C4IT_AddonConfigClassBase-C4IT_AddonConfigClassBase.class" />
</SchemaScripts>
</SchemaScripts>

View File

@@ -137,8 +137,9 @@
</xs:schema>
<PLSLWebServiceOperation>
<ID>b3193051-6fe6-cdd2-7d76-08da9bbec2b6</ID>
<RequestContract>{"UsedTypes":{"RequestContract":{"Descriptor":{"sid":{"Type":"StringType"},"assetname":{"Type":"StringType"}}}},"ContractDescriptor":{"ReferenceTo":null,"ReferenceFilter":null,"Required":false,"Obsolete":false,"MaxLength":0,"ResourceKey":null,"Documentation":null,"Title":null,"Paths":null,"Type":"RequestContract"}}</RequestContract>
<Name>getDirectLinkCreateTicket(sid, assetname)</Name>
<ResponseContract>{"UsedTypes":{"C4IT_F4SD_F4SDHelperService+DirectLink":{"Descriptor":{"Link":{"Type":"StringType"},"SubjectParameter":{"Type":"StringType"},"DescriptionParameter":{"Type":"StringType"}}}},"ContractDescriptor":{"ReturnCountType":"NotProvided","Documentation":"Return value","Type":"C4IT_F4SD_F4SDHelperService+DirectLink"}}</ResponseContract>
<RequestContract>{"UsedTypes":{"RequestContract":{"Descriptor":{"sid":{"Type":"StringType","Source":0},"assetname":{"Type":"StringType","Source":0}}}},"ContractDescriptor":{"Type":"RequestContract"}}</RequestContract>
<Name>getDirectLinkCreateTicket(sid,assetname)</Name>
<RouteTemplate>getDirectLinkCreateTicket</RouteTemplate>
<Documentation />
<TypeID>7660e907-769c-e711-a182-f079595b3ec7</TypeID>

View File

@@ -137,8 +137,9 @@
</xs:schema>
<PLSLWebServiceOperation>
<ID>04d0755f-27dd-c4ac-2785-08dac1666661</ID>
<RequestContract>{"UsedTypes":{"RequestContract":{"Descriptor":{"EOID":{"Type":"StringType"},"Type":{"Type":"StringType"}}}},"ContractDescriptor":{"ReferenceTo":null,"ReferenceFilter":null,"Required":false,"Obsolete":false,"MaxLength":0,"ResourceKey":null,"Documentation":null,"Title":null,"Paths":null,"Type":"RequestContract"}}</RequestContract>
<Name>getDirectLinkF4SD(EOID, Type)</Name>
<ResponseContract>{"UsedTypes":{},"ContractDescriptor":{"ReturnCountType":"NotProvided","Documentation":"Return value","Type":"StringType"}}</ResponseContract>
<RequestContract>{"UsedTypes":{"RequestContract":{"Descriptor":{"eoid":{"Type":"GuidType","Source":0},"type":{"Type":"StringType","Source":0}}}},"ContractDescriptor":{"Type":"RequestContract"}}</RequestContract>
<Name>getDirectLinkF4SD(eoid,type)</Name>
<RouteTemplate>getDirectLinkF4SD</RouteTemplate>
<Documentation />
<TypeID>7660e907-769c-e711-a182-f079595b3ec7</TypeID>

View File

@@ -137,8 +137,9 @@
</xs:schema>
<PLSLWebServiceOperation>
<ID>f977a1d8-f21c-c1bc-4ea0-08dac09d3c99</ID>
<RequestContract>{"UsedTypes":{"RequestContract":{"Descriptor":{"download":{"Type":"StringType"},"count":{"Type":"StringType"},"filter":{"Type":"StringType"}}}},"ContractDescriptor":{"ReferenceTo":null,"ReferenceFilter":null,"Required":false,"Obsolete":false,"MaxLength":0,"ResourceKey":null,"Documentation":null,"Title":null,"Paths":null,"Type":"RequestContract"}}</RequestContract>
<Name>getLog(download, count, filter)</Name>
<ResponseContract>{"UsedTypes":{},"ContractDescriptor":{"ReturnCountType":"NotProvided","Documentation":"Return value","Type":"Matrix42_WebApi_Contracts_IHttpActionResult"}}</ResponseContract>
<RequestContract>{"UsedTypes":{"RequestContract":{"Descriptor":{"download":{"Type":"StringType","Source":0},"count":{"Type":"IntType","Source":0},"filter":{"Type":"StringType","Source":0}}}},"ContractDescriptor":{"Type":"RequestContract"}}</RequestContract>
<Name>getLog(download,count,filter)</Name>
<RouteTemplate>log</RouteTemplate>
<Documentation />
<TypeID>7660e907-769c-e711-a182-f079595b3ec7</TypeID>

View File

@@ -137,8 +137,9 @@
</xs:schema>
<PLSLWebServiceOperation>
<ID>6cec89ab-b843-cd6b-d6b5-08db99ad32ee</ID>
<RequestContract>{"UsedTypes":{},"ContractDescriptor":{"ReferenceTo":null,"ReferenceFilter":null,"Required":false,"Obsolete":false,"MaxLength":0,"ResourceKey":null,"Documentation":null,"Title":null,"Paths":null,"Type":"RequestContract"}}</RequestContract>
<Name>getMyRoleMemberships</Name>
<ResponseContract>{"UsedTypes":{},"ContractDescriptor":{"ReturnCountType":"NotProvided","Documentation":"Return value","Type":"System_Object"}}</ResponseContract>
<RequestContract>{"UsedTypes":{},"ContractDescriptor":{"Type":"RequestContract"}}</RequestContract>
<Name>getMyRoleMemberships()</Name>
<RouteTemplate>getMyRoleMemberships</RouteTemplate>
<Documentation />
<TypeID>7660e907-769c-e711-a182-f079595b3ec7</TypeID>

View File

@@ -137,8 +137,9 @@
</xs:schema>
<PLSLWebServiceOperation>
<ID>ef14b892-628c-c1c1-801f-08db99ad32e9</ID>
<RequestContract>{"UsedTypes":{"RequestContract":{"Descriptor":{"name":{"Type":"StringType"},"mode":{"Type":"StringType"},"group":{"Type":"StringType"}}}},"ContractDescriptor":{"ReferenceTo":null,"ReferenceFilter":null,"Required":false,"Obsolete":false,"MaxLength":0,"ResourceKey":null,"Documentation":null,"Title":null,"Paths":null,"Type":"RequestContract"}}</RequestContract>
<Name>getPickup(name, mode, group)</Name>
<ResponseContract>{"UsedTypes":{"Matrix42_Pandora_Contracts_EntityEnumeration":{"Documentation":"Describes Entity Enumeration","Descriptor":{"Name":{"Documentation":"Technical name of the Enumeration","Type":"StringType"},"Values":{"Documentation":"Enumeration Values","Type":["Matrix42_Pandora_Contracts_EntityEnumerationValue"]}},"DisplayName":"Name"},"Matrix42_Pandora_Contracts_EntityEnumerationValue":{"Documentation":"Represents a single value in Entity Enumeration","Descriptor":{"Value":{"Documentation":"Gets or sets a value","Type":"IntType"},"DisplayString":{"Documentation":"Gets or sets the display string for Enumeration Value","Type":"StringType"},"Hidden":{"Documentation":"Gets or sets a Hidden attribute","Type":"BoolType"},"Extentions":{"Documentation":"Additional pickup value attributes","Type":["StringType"]}}}},"ContractDescriptor":{"ReturnCountType":"NotProvided","Documentation":"Return value","Type":"Matrix42_Pandora_Contracts_EntityEnumeration"}}</ResponseContract>
<RequestContract>{"UsedTypes":{"RequestContract":{"Descriptor":{"name":{"Type":"StringType","Source":0},"mode":{"Type":"IntType","Source":0},"group":{"Type":"IntType","Source":0}}}},"ContractDescriptor":{"Type":"RequestContract"}}</RequestContract>
<Name>getPickup(name,mode,group)</Name>
<RouteTemplate>getPickup/{name}</RouteTemplate>
<Documentation />
<TypeID>7660e907-769c-e711-a182-f079595b3ec7</TypeID>

View File

@@ -137,8 +137,9 @@
</xs:schema>
<PLSLWebServiceOperation>
<ID>06747fe1-8113-c51f-4969-08db99ad32f1</ID>
<RequestContract>{"UsedTypes":{"RequestContract":{"Descriptor":{"sid":{"Type":"StringType"},"upn":{"Type":"StringType"},"id":{"Type":"StringType"}}}},"ContractDescriptor":{"ReferenceTo":null,"ReferenceFilter":null,"Required":false,"Obsolete":false,"MaxLength":0,"ResourceKey":null,"Documentation":null,"Title":null,"Paths":null,"Type":"RequestContract"}}</RequestContract>
<Name>getRoleMemberships(sid, upn, id)</Name>
<ResponseContract>{"UsedTypes":{},"ContractDescriptor":{"ReturnCountType":"NotProvided","Documentation":"Return value","Type":"System_Object"}}</ResponseContract>
<RequestContract>{"UsedTypes":{"RequestContract":{"Descriptor":{"sid":{"Type":"StringType","Source":0},"upn":{"Type":"StringType","Source":0},"id":{"Type":"GuidType","Source":0}}}},"ContractDescriptor":{"Type":"RequestContract"}}</RequestContract>
<Name>getRoleMemberships(sid,upn,id)</Name>
<RouteTemplate>getRoleMemberships</RouteTemplate>
<Documentation />
<TypeID>7660e907-769c-e711-a182-f079595b3ec7</TypeID>

View File

@@ -0,0 +1,159 @@
<?xml version="1.0" encoding="utf-8"?>
<NewDataSet>
<xs:schema id="NewDataSet" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:UseCurrentLocale="true">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="PLSLWebServiceOperation">
<xs:complexType>
<xs:sequence>
<xs:element name="ID" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" />
<xs:element name="ResponseContract" minOccurs="0">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="2147483647" />
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="RequestContract" minOccurs="0">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="2147483647" />
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="Name" minOccurs="0">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="1000" />
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="RouteTemplate" minOccurs="0">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="1000" />
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="Documentation" minOccurs="0">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="2147483647" />
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="TypeID" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
<xs:element name="Service" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" />
<xs:element name="SupportedOperation" type="xs:int" minOccurs="0" />
<xs:element name="Type" type="xs:int" minOccurs="0" />
<xs:element name="IsPublic" type="xs:unsignedByte" />
<xs:element name="DocumentationLink" minOccurs="0">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="1000" />
</xs:restriction>
</xs:simpleType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="PDRAudienceClass">
<xs:complexType>
<xs:sequence>
<xs:element name="ID" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" />
<xs:element name="UsedInTypePDRContentWidgetTypeDialog" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
<xs:element name="UsedInTypePDRContentWidgetTypeObjectDetails" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
<xs:element name="UsedInTypePDRDataQueryFilterType" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
<xs:element name="Unrestricted" type="xs:unsignedByte" />
<xs:element name="Configured" type="xs:unsignedByte" />
<xs:element name="UsedInTypePDRActionType" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
<xs:element name="UsedInTypePDRNavigationItemType" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
<xs:element name="ConsiderRelated" type="xs:unsignedByte" />
<xs:element name="UsedInTypePLSLWebServiceOperationType" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
<xs:element name="UsedInTypePLSLServiceTypeWebAPI" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
<xs:element name="UsedInTypePDRContentWidgetTemplateViewType" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
<xs:element name="UsedInTypeSVMEmailSignatureType" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
<xs:element name="StrictAdminControl" type="xs:unsignedByte" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="SchemaRelation-PDRAudienceClass2PDRAudienceClass">
<xs:complexType>
<xs:sequence>
<xs:element name="ID" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
<xs:element name="InheritedFrom" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
<xs:element name="ApplyTo" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="SchemaRelation-PDRAudienceClass2SPSUserClassBase">
<xs:complexType>
<xs:sequence>
<xs:element name="ID" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
<xs:element name="Users" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
<xs:element name="Audiences" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="SchemaRelation-PDRAudienceClass2SPSSecurityClassRole">
<xs:complexType>
<xs:sequence>
<xs:element name="ID" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
<xs:element name="Audiences" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
<xs:element name="Roles" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="SchemaRelation-PDRAudienceClass2SPSOrgUnitClassBase">
<xs:complexType>
<xs:sequence>
<xs:element name="ID" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
<xs:element name="Audiences" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
<xs:element name="OUs" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="SchemaRelation-PDRAudienceClass2SPSLocationClassBase">
<xs:complexType>
<xs:sequence>
<xs:element name="ID" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
<xs:element name="Audiences" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
<xs:element name="Locations" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
<xs:unique name="Constraint1" msdata:PrimaryKey="true">
<xs:selector xpath=".//PLSLWebServiceOperation" />
<xs:field xpath="ID" />
</xs:unique>
<xs:unique name="PDRAudienceClass_Constraint1" msdata:ConstraintName="Constraint1" msdata:PrimaryKey="true">
<xs:selector xpath=".//PDRAudienceClass" />
<xs:field xpath="ID" />
</xs:unique>
</xs:element>
</xs:schema>
<PLSLWebServiceOperation>
<ID>750c8dc4-ada0-c1b0-c877-08da9bbec2e3</ID>
<ResponseContract>{"UsedTypes":{"C4IT_FASD_Base_cF4SDTicket":{"Descriptor":{"AffectedUserId":{"Type":"GuidType"},"AssetId":{"Type":"GuidType"},"CreationDate":{"Type":"DateType"},"ClosingDate":{"Type":"DateType"},"CreationSourceId":{"Type":"IntType"},"CreationSource":{"Type":"StringType"},"Description":{"Type":"StringType"},"DescriptionHtml":{"Type":"StringType"},"PriorityId":{"Type":"IntType"},"Priority":{"Type":"StringType"},"CategoryId":{"Type":"GuidType"},"Category":{"Type":"StringType"},"CategoryHierarchical":{"Type":"StringType"},"CIName":{"Type":"StringType"},"DirectLinkEdit":{"Type":"StringType"},"AssetCIId":{"Type":"GuidType"},"AssetSKUAssetGroupId":{"Type":"IntType"},"AssetSKUAssetGroup":{"Type":"StringType"},"AssetSKUTypeId":{"Type":"IntType"},"AssetSKUType":{"Type":"StringType"},"DirectLinkPreview":{"Type":"StringType"},"DirectLinkClose":{"Type":"StringType"},"AffectedUser":{"Type":"StringType"},"SolutionHtml":{"Type":"StringType"},"Solution":{"Type":"StringType"},"AssetDomain":{"Type":"StringType"},"TicketObjectId":{"Type":"GuidType"},"Name":{"Type":"StringType"},"ActivityType":{"Type":"StringType"},"Summary":{"Type":"StringType"},"Sid":{"Type":"StringType"},"Status":{"Type":"StringType"},"StatusId":{"Type":"IntType"},"Urgency":{"Type":"StringType"},"UrgencyId":{"Type":"IntType"},"Impact":{"Type":"StringType"},"ImpactId":{"Type":"IntType"},"AssetCIName":{"Type":"StringType"},"AssetName":{"Type":"StringType"},"ServiceName":{"Type":"StringType"},"ServiceId":{"Type":"GuidType"},"IsPrimaryAccount":{"Type":"BoolType"}},"DisplayName":"Name"}},"ContractDescriptor":{"ReturnCountType":"NotProvided","Documentation":"Return value","Type":"C4IT_FASD_Base_cF4SDTicket"}}</ResponseContract>
<RequestContract>{"UsedTypes":{"RequestContract":{"Descriptor":{"objectId":{"Type":"GuidType","Source":0}}}},"ContractDescriptor":{"Type":"RequestContract"}}</RequestContract>
<Name>getTicketDetails(objectId)</Name>
<RouteTemplate>getTicketDetails</RouteTemplate>
<Documentation />
<TypeID>7660e907-769c-e711-a182-f079595b3ec7</TypeID>
<Service>dcd66369-4933-ed11-1b9c-e3e293f5401c</Service>
<SupportedOperation>0</SupportedOperation>
<Type>1</Type>
<IsPublic>0</IsPublic>
</PLSLWebServiceOperation>
<PDRAudienceClass>
<ID>336febdb-9a39-ed11-209c-b0c4b3911a8e</ID>
<Unrestricted>1</Unrestricted>
<Configured>1</Configured>
<ConsiderRelated>0</ConsiderRelated>
<UsedInTypePLSLWebServiceOperationType>750c8dc4-ada0-c1b0-c877-08da9bbec2e3</UsedInTypePLSLWebServiceOperationType>
<StrictAdminControl>0</StrictAdminControl>
</PDRAudienceClass>
</NewDataSet>

View File

@@ -137,7 +137,8 @@
</xs:schema>
<PLSLWebServiceOperation>
<ID>94d0317f-a8db-caf0-a353-08da9bbec2dc</ID>
<RequestContract>{"UsedTypes":{"RequestContract":{"Descriptor":{"objectId":{"Type":"StringType"}}}},"ContractDescriptor":{"ReferenceTo":null,"ReferenceFilter":null,"Required":false,"Obsolete":false,"MaxLength":0,"ResourceKey":null,"Documentation":null,"Title":null,"Paths":null,"Type":"RequestContract"}}</RequestContract>
<ResponseContract>{"UsedTypes":{},"ContractDescriptor":{"ReturnCountType":"NotProvided","Documentation":"Return value","Type":"System_Collections_Generic_List`1[C4IT_FASD_Base_cF4SDTicket+cTicketJournalItem]"}}</ResponseContract>
<RequestContract>{"UsedTypes":{"RequestContract":{"Descriptor":{"objectId":{"Type":"GuidType","Source":0}}}},"ContractDescriptor":{"Type":"RequestContract"}}</RequestContract>
<Name>getTicketHistory(objectId)</Name>
<RouteTemplate>getTicketHistory</RouteTemplate>
<Documentation />

View File

@@ -137,8 +137,9 @@
</xs:schema>
<PLSLWebServiceOperation>
<ID>163e04c2-8b5c-c0e6-0535-08da9bbec2df</ID>
<RequestContract>{"UsedTypes":{"RequestContract":{"Descriptor":{"sid":{"Type":"StringType"},"hours":{"Type":"StringType"},"queueoption":{"Type":"StringType"},"queues":{"Type":"StringType"}}}},"ContractDescriptor":{"ReferenceTo":null,"ReferenceFilter":null,"Required":false,"Obsolete":false,"MaxLength":0,"ResourceKey":null,"Documentation":null,"Title":null,"Paths":null,"Type":"RequestContract"}}</RequestContract>
<Name>getTicketList(sid, hours, queueoption, queues)</Name>
<ResponseContract>{"UsedTypes":{},"ContractDescriptor":{"ReturnCountType":"NotProvided","Documentation":"Return value","Type":"System_Collections_Generic_List`1[C4IT_FASD_Base_cF4SDTicketSummary]"}}</ResponseContract>
<RequestContract>{"UsedTypes":{"RequestContract":{"Descriptor":{"sid":{"Type":"StringType","Source":0},"hours":{"Type":"IntType","Source":0},"queueoption":{"Type":"IntType","Source":0},"queues":{"Type":"StringType","Source":0}}}},"ContractDescriptor":{"Type":"RequestContract"}}</RequestContract>
<Name>getTicketList(sid,hours,queueoption,queues)</Name>
<RouteTemplate>getTicketList</RouteTemplate>
<Documentation />
<TypeID>7660e907-769c-e711-a182-f079595b3ec7</TypeID>

View File

@@ -0,0 +1,159 @@
<?xml version="1.0" encoding="utf-8"?>
<NewDataSet>
<xs:schema id="NewDataSet" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:UseCurrentLocale="true">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="PLSLWebServiceOperation">
<xs:complexType>
<xs:sequence>
<xs:element name="ID" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" />
<xs:element name="ResponseContract" minOccurs="0">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="2147483647" />
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="RequestContract" minOccurs="0">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="2147483647" />
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="Name" minOccurs="0">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="1000" />
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="RouteTemplate" minOccurs="0">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="1000" />
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="Documentation" minOccurs="0">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="2147483647" />
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="TypeID" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
<xs:element name="Service" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" />
<xs:element name="SupportedOperation" type="xs:int" minOccurs="0" />
<xs:element name="Type" type="xs:int" minOccurs="0" />
<xs:element name="IsPublic" type="xs:unsignedByte" />
<xs:element name="DocumentationLink" minOccurs="0">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="1000" />
</xs:restriction>
</xs:simpleType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="PDRAudienceClass">
<xs:complexType>
<xs:sequence>
<xs:element name="ID" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" />
<xs:element name="UsedInTypePDRContentWidgetTypeDialog" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
<xs:element name="UsedInTypePDRContentWidgetTypeObjectDetails" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
<xs:element name="UsedInTypePDRDataQueryFilterType" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
<xs:element name="Unrestricted" type="xs:unsignedByte" />
<xs:element name="Configured" type="xs:unsignedByte" />
<xs:element name="UsedInTypePDRActionType" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
<xs:element name="UsedInTypePDRNavigationItemType" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
<xs:element name="ConsiderRelated" type="xs:unsignedByte" />
<xs:element name="UsedInTypePLSLWebServiceOperationType" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
<xs:element name="UsedInTypePLSLServiceTypeWebAPI" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
<xs:element name="UsedInTypePDRContentWidgetTemplateViewType" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
<xs:element name="UsedInTypeSVMEmailSignatureType" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
<xs:element name="StrictAdminControl" type="xs:unsignedByte" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="SchemaRelation-PDRAudienceClass2PDRAudienceClass">
<xs:complexType>
<xs:sequence>
<xs:element name="ID" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
<xs:element name="InheritedFrom" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
<xs:element name="ApplyTo" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="SchemaRelation-PDRAudienceClass2SPSUserClassBase">
<xs:complexType>
<xs:sequence>
<xs:element name="ID" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
<xs:element name="Users" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
<xs:element name="Audiences" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="SchemaRelation-PDRAudienceClass2SPSSecurityClassRole">
<xs:complexType>
<xs:sequence>
<xs:element name="ID" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
<xs:element name="Audiences" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
<xs:element name="Roles" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="SchemaRelation-PDRAudienceClass2SPSOrgUnitClassBase">
<xs:complexType>
<xs:sequence>
<xs:element name="ID" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
<xs:element name="Audiences" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
<xs:element name="OUs" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="SchemaRelation-PDRAudienceClass2SPSLocationClassBase">
<xs:complexType>
<xs:sequence>
<xs:element name="ID" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
<xs:element name="Audiences" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
<xs:element name="Locations" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
<xs:unique name="Constraint1" msdata:PrimaryKey="true">
<xs:selector xpath=".//PLSLWebServiceOperation" />
<xs:field xpath="ID" />
</xs:unique>
<xs:unique name="PDRAudienceClass_Constraint1" msdata:ConstraintName="Constraint1" msdata:PrimaryKey="true">
<xs:selector xpath=".//PDRAudienceClass" />
<xs:field xpath="ID" />
</xs:unique>
</xs:element>
</xs:schema>
<PLSLWebServiceOperation>
<ID>99eef84e-a303-c248-36c5-08ded882fc6c</ID>
<ResponseContract>{"UsedTypes":{"C4IT_F4SD_F4SDHelperService+TicketOverviewCountsResult":{"Descriptor":{"Counts":{"Type":["StringType"]}}}},"ContractDescriptor":{"ReturnCountType":"NotProvided","Documentation":"Return value","Type":"C4IT_F4SD_F4SDHelperService+TicketOverviewCountsResult"}}</ResponseContract>
<RequestContract>{"UsedTypes":{"RequestContract":{"Descriptor":{"sid":{"Type":"StringType","Source":0},"scope":{"Type":"StringType","Source":0},"keys":{"Type":"StringType","Source":0},"queueoption":{"Type":"IntType","Source":0},"queues":{"Type":"StringType","Source":0}}}},"ContractDescriptor":{"Type":"RequestContract"}}</RequestContract>
<Name>getTicketOverviewCounts(sid,scope,keys,queueoption,queues)</Name>
<RouteTemplate>getTicketOverviewCounts</RouteTemplate>
<Documentation />
<TypeID>7660e907-769c-e711-a182-f079595b3ec7</TypeID>
<Service>dcd66369-4933-ed11-1b9c-e3e293f5401c</Service>
<SupportedOperation>0</SupportedOperation>
<Type>1</Type>
<IsPublic>0</IsPublic>
</PLSLWebServiceOperation>
<PDRAudienceClass>
<ID>82d8de08-6cfc-1483-6bfa-da4b9403a82d</ID>
<Unrestricted>1</Unrestricted>
<Configured>1</Configured>
<ConsiderRelated>0</ConsiderRelated>
<UsedInTypePLSLWebServiceOperationType>99eef84e-a303-c248-36c5-08ded882fc6c</UsedInTypePLSLWebServiceOperationType>
<StrictAdminControl>0</StrictAdminControl>
</PDRAudienceClass>
</NewDataSet>

View File

@@ -0,0 +1,159 @@
<?xml version="1.0" encoding="utf-8"?>
<NewDataSet>
<xs:schema id="NewDataSet" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:UseCurrentLocale="true">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="PLSLWebServiceOperation">
<xs:complexType>
<xs:sequence>
<xs:element name="ID" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" />
<xs:element name="ResponseContract" minOccurs="0">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="2147483647" />
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="RequestContract" minOccurs="0">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="2147483647" />
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="Name" minOccurs="0">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="1000" />
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="RouteTemplate" minOccurs="0">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="1000" />
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="Documentation" minOccurs="0">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="2147483647" />
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="TypeID" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
<xs:element name="Service" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" />
<xs:element name="SupportedOperation" type="xs:int" minOccurs="0" />
<xs:element name="Type" type="xs:int" minOccurs="0" />
<xs:element name="IsPublic" type="xs:unsignedByte" />
<xs:element name="DocumentationLink" minOccurs="0">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="1000" />
</xs:restriction>
</xs:simpleType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="PDRAudienceClass">
<xs:complexType>
<xs:sequence>
<xs:element name="ID" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" />
<xs:element name="UsedInTypePDRContentWidgetTypeDialog" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
<xs:element name="UsedInTypePDRContentWidgetTypeObjectDetails" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
<xs:element name="UsedInTypePDRDataQueryFilterType" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
<xs:element name="Unrestricted" type="xs:unsignedByte" />
<xs:element name="Configured" type="xs:unsignedByte" />
<xs:element name="UsedInTypePDRActionType" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
<xs:element name="UsedInTypePDRNavigationItemType" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
<xs:element name="ConsiderRelated" type="xs:unsignedByte" />
<xs:element name="UsedInTypePLSLWebServiceOperationType" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
<xs:element name="UsedInTypePLSLServiceTypeWebAPI" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
<xs:element name="UsedInTypePDRContentWidgetTemplateViewType" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
<xs:element name="UsedInTypeSVMEmailSignatureType" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
<xs:element name="StrictAdminControl" type="xs:unsignedByte" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="SchemaRelation-PDRAudienceClass2PDRAudienceClass">
<xs:complexType>
<xs:sequence>
<xs:element name="ID" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
<xs:element name="InheritedFrom" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
<xs:element name="ApplyTo" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="SchemaRelation-PDRAudienceClass2SPSUserClassBase">
<xs:complexType>
<xs:sequence>
<xs:element name="ID" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
<xs:element name="Users" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
<xs:element name="Audiences" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="SchemaRelation-PDRAudienceClass2SPSSecurityClassRole">
<xs:complexType>
<xs:sequence>
<xs:element name="ID" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
<xs:element name="Audiences" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
<xs:element name="Roles" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="SchemaRelation-PDRAudienceClass2SPSOrgUnitClassBase">
<xs:complexType>
<xs:sequence>
<xs:element name="ID" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
<xs:element name="Audiences" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
<xs:element name="OUs" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="SchemaRelation-PDRAudienceClass2SPSLocationClassBase">
<xs:complexType>
<xs:sequence>
<xs:element name="ID" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
<xs:element name="Audiences" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
<xs:element name="Locations" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
<xs:unique name="Constraint1" msdata:PrimaryKey="true">
<xs:selector xpath=".//PLSLWebServiceOperation" />
<xs:field xpath="ID" />
</xs:unique>
<xs:unique name="PDRAudienceClass_Constraint1" msdata:ConstraintName="Constraint1" msdata:PrimaryKey="true">
<xs:selector xpath=".//PDRAudienceClass" />
<xs:field xpath="ID" />
</xs:unique>
</xs:element>
</xs:schema>
<PLSLWebServiceOperation>
<ID>290c8d51-b8d4-ce74-50c5-08ded882fc72</ID>
<ResponseContract>{"UsedTypes":{"C4IT_F4SD_F4SDHelperService+TicketOverviewCountsByRoleResult":{"Descriptor":{"GeneratedAtUtc":{"Type":"DateType"},"CountsByRole":{"Type":["StringType"]}}}},"ContractDescriptor":{"ReturnCountType":"NotProvided","Documentation":"Return value","Type":"C4IT_F4SD_F4SDHelperService+TicketOverviewCountsByRoleResult"}}</ResponseContract>
<RequestContract>{"UsedTypes":{"RequestContract":{"Descriptor":{"request":{"Type":"C4IT_F4SD_F4SDM42WebApiController+TicketOverviewCountsByRolesRequest","Source":1}}},"C4IT_F4SD_F4SDM42WebApiController+TicketOverviewCountsByRolesRequest":{"Descriptor":{"Sid":{"Type":"StringType"},"RoleGuids":{"Type":["GuidType"]},"Keys":{"Type":["StringType"]},"QueueOption":{"Type":"IntType"},"Queues":{"Type":"StringType"}}}},"ContractDescriptor":{"Type":"RequestContract"}}</RequestContract>
<Name>getTicketOverviewCountsByRoles(request)</Name>
<RouteTemplate>getTicketOverviewCountsByRoles</RouteTemplate>
<Documentation />
<TypeID>7660e907-769c-e711-a182-f079595b3ec7</TypeID>
<Service>dcd66369-4933-ed11-1b9c-e3e293f5401c</Service>
<SupportedOperation>16</SupportedOperation>
<Type>2</Type>
<IsPublic>0</IsPublic>
</PLSLWebServiceOperation>
<PDRAudienceClass>
<ID>82d8de08-72fc-4476-6bfa-da4b9403a848</ID>
<Unrestricted>1</Unrestricted>
<Configured>1</Configured>
<ConsiderRelated>0</ConsiderRelated>
<UsedInTypePLSLWebServiceOperationType>290c8d51-b8d4-ce74-50c5-08ded882fc72</UsedInTypePLSLWebServiceOperationType>
<StrictAdminControl>0</StrictAdminControl>
</PDRAudienceClass>
</NewDataSet>

View File

@@ -136,10 +136,11 @@
</xs:element>
</xs:schema>
<PLSLWebServiceOperation>
<ID>750c8dc4-ada0-c1b0-c877-08da9bbec2e3</ID>
<RequestContract>{"UsedTypes":{"RequestContract":{"Descriptor":{"objectId":{"Type":"StringType"}}}},"ContractDescriptor":{"ReferenceTo":null,"ReferenceFilter":null,"Required":false,"Obsolete":false,"MaxLength":0,"ResourceKey":null,"Documentation":null,"Title":null,"Paths":null,"Type":"RequestContract"}}</RequestContract>
<Name>getTicketDetails(objectId)</Name>
<RouteTemplate>getTicketDetails</RouteTemplate>
<ID>c5dd653a-54d8-c430-c9df-08ded882fc79</ID>
<ResponseContract>{"UsedTypes":{},"ContractDescriptor":{"ReturnCountType":"NotProvided","Documentation":"Return value","Type":"System_Collections_Generic_List`1[C4IT_F4SD_F4SDHelperService+TicketOverviewRelationDto]"}}</ResponseContract>
<RequestContract>{"UsedTypes":{"RequestContract":{"Descriptor":{"sid":{"Type":"StringType","Source":0},"scope":{"Type":"StringType","Source":0},"key":{"Type":"StringType","Source":0},"count":{"Type":"IntType","Source":0},"queueoption":{"Type":"IntType","Source":0},"queues":{"Type":"StringType","Source":0}}}},"ContractDescriptor":{"Type":"RequestContract"}}</RequestContract>
<Name>getTicketOverviewRelations(sid,scope,key,count,queueoption,queues)</Name>
<RouteTemplate>getTicketOverviewRelations</RouteTemplate>
<Documentation />
<TypeID>7660e907-769c-e711-a182-f079595b3ec7</TypeID>
<Service>dcd66369-4933-ed11-1b9c-e3e293f5401c</Service>
@@ -148,11 +149,11 @@
<IsPublic>0</IsPublic>
</PLSLWebServiceOperation>
<PDRAudienceClass>
<ID>336febdb-9a39-ed11-209c-b0c4b3911a8e</ID>
<ID>82d8de08-7afc-f13f-6bfa-da4b9403a863</ID>
<Unrestricted>1</Unrestricted>
<Configured>1</Configured>
<ConsiderRelated>0</ConsiderRelated>
<UsedInTypePLSLWebServiceOperationType>750c8dc4-ada0-c1b0-c877-08da9bbec2e3</UsedInTypePLSLWebServiceOperationType>
<UsedInTypePLSLWebServiceOperationType>c5dd653a-54d8-c430-c9df-08ded882fc79</UsedInTypePLSLWebServiceOperationType>
<StrictAdminControl>0</StrictAdminControl>
</PDRAudienceClass>
</NewDataSet>

View File

@@ -137,8 +137,9 @@
</xs:schema>
<PLSLWebServiceOperation>
<ID>9df9d16f-1a00-cc19-1727-08dac09d3c08</ID>
<RequestContract>{"UsedTypes":{},"ContractDescriptor":{"ReferenceTo":null,"ReferenceFilter":null,"Required":false,"Obsolete":false,"MaxLength":0,"ResourceKey":null,"Documentation":null,"Title":null,"Paths":null,"Type":"RequestContract"}}</RequestContract>
<Name>isAlive</Name>
<ResponseContract>{"UsedTypes":{},"ContractDescriptor":{"ReturnCountType":"NotProvided","Documentation":"Return value","Type":"Matrix42_WebApi_Contracts_IHttpActionResult"}}</ResponseContract>
<RequestContract>{"UsedTypes":{},"ContractDescriptor":{"Type":"RequestContract"}}</RequestContract>
<Name>isAlive()</Name>
<RouteTemplate>isAlive</RouteTemplate>
<Documentation />
<TypeID>7660e907-769c-e711-a182-f079595b3ec7</TypeID>

View File

@@ -137,7 +137,8 @@
</xs:schema>
<PLSLWebServiceOperation>
<ID>14366b3c-b79d-cfe3-ded3-08da9bbec2d7</ID>
<RequestContract>{"UsedTypes":{"RequestContract":{"Descriptor":{"debug":{"Type":"StringType"}}}},"ContractDescriptor":{"ReferenceTo":null,"ReferenceFilter":null,"Required":false,"Obsolete":false,"MaxLength":0,"ResourceKey":null,"Documentation":null,"Title":null,"Paths":null,"Type":"RequestContract"}}</RequestContract>
<ResponseContract>{"UsedTypes":{},"ContractDescriptor":{"ReturnCountType":"NotProvided","Documentation":"Return value","Type":"StringType"}}</ResponseContract>
<RequestContract>{"UsedTypes":{"RequestContract":{"Descriptor":{"debug":{"Type":"StringType","Source":0}}}},"ContractDescriptor":{"Type":"RequestContract"}}</RequestContract>
<Name>setDebugMode(debug)</Name>
<RouteTemplate>loglevel</RouteTemplate>
<Documentation />

View File

@@ -12,7 +12,7 @@
"SetupDirectives": {
"MaintenanceMode": false,
"RecycleWebApplication": false,
"RestartM42WindowsServices": false
"RestartM42WindowsServices": true
},
"Sandboxed": true
}

View File

@@ -1,9 +1,9 @@
using System.Reflection;
[assembly: AssemblyCompany("Consulting4IT GmbH, Germany")]
[assembly: AssemblyCompany("Consulting4IT GmbH")]
[assembly: AssemblyProduct("C4IT - F4SD - WebApi for M42")]
[assembly: AssemblyCopyright("Copyright © 2026, Consulting4IT GmbH, Germany")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyVersion("1.3.0.0")]
[assembly: AssemblyInformationalVersion("1.3.0.0")]
[assembly: AssemblyVersion("1.4.0.0")]
[assembly: AssemblyInformationalVersion("1.4.0.0")]

View File

@@ -1,20 +1,28 @@
# Matrix42 26.1 Extension/Webservice Migration
# Matrix42 26.1 Legacy Extension Migration
Diese Notizen dokumentieren die Learnings aus der Migration der alten F4SD Matrix42 Extension inklusive Custom Web Service auf die Matrix42 26.1 Sandboxed Extension Struktur.
Diese Notizen dokumentieren die bisherigen Learnings aus der Migration einer alten Matrix42 Extension inklusive Custom Web Service auf eine Matrix42 26.1 Sandboxed Extension.
Ausgangspunkt der eigentlichen 26.1-Migration war Commit `6c6ac272cd43` (`feat: support Matrix42 26.1 sandboxed web api`, 2026-06-26 11:44 +0200). Die Punkte hier sind bewusst als Checkliste fuer weitere Extensions formuliert.
Die Anleitung ist bewusst als wiederverwendbare Checkliste fuer weitere Legacy-Pakete formuliert. Sie trennt zwischen belastbaren Ergebnissen, verworfenen Zwischenansaetzen und Punkten, die bei jeder Extension erneut geprueft werden muessen.
## Zielbild
- Extension als .NET 8 Library mit `Matrix42.WebApi.Contracts`.
- Webservice-Controller von `Matrix42.WebApi.Contracts.ApiController` ableiten.
- Controller ueber `Matrix42.Hosting.Contracts.IDependencyResolver` konstruieren.
- Matrix42-Fachservices nicht direkt im Controller-Konstruktor injizieren.
- Host-Konfig so klein wie moeglich halten.
- Paketbau in den Visual-Studio-/MSBuild-Prozess integrieren.
- Runtime zuerst mit minimalen Endpoints pruefen (`isAlive`, einfache Datenabfrage), dann erst komplexere Services aktivieren.
- Matrix42-Fachservices nur dort lazy aufloesen, wo sie wirklich gebraucht werden.
- Host-Konfig mit minimalen Modulen starten und gezielt erweitern.
- Paketbau in MSBuild/Visual Studio integrieren.
- Paketversion aus `AssemblyVersion` ableiten.
- Signing nur fuer eine eigene signed Build-Konfiguration aktivieren.
- Postman-Collection als Regressionstest fuer alte Client-URLs pflegen.
## Projektstruktur und Paketbau
## Ausgangspunkt
Bei einer Portierung eines alten Produktstands muss der Zielstand klar sein. Fuer diesen Branch war der relevante alte Stand `26eac54f94`, nicht der spaetere neue Codezweig.
Wichtiges Learning: Bei einem 26.1-Kompatibilitaetsport keine neuen fachlichen Methoden, Obsolete-Markierungen oder Verhaltensaenderungen aus einem anderen Codezweig uebernehmen. Erst die alte Funktionalitaet lauffaehig machen, dann separate fachliche Aenderungen behandeln.
## Basisprojekt
Bewaehrte Projekt-Eigenschaften:
@@ -23,35 +31,115 @@ Bewaehrte Projekt-Eigenschaften:
<OutputType>Library</OutputType>
<RuntimeIdentifiers>win-x64;linux-x64</RuntimeIdentifiers>
<AppendRuntimeIdentifierToOutputPath>true</AppendRuntimeIdentifierToOutputPath>
<Nullable>disable</Nullable>
<ImplicitUsings>disable</ImplicitUsings>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
<M42ExtensionId>...</M42ExtensionId>
<M42AssemblyPattern>C4ITF4SD*.*</M42AssemblyPattern>
<M42PackageVersion>...</M42PackageVersion>
<M42AssemblyPattern>...</M42AssemblyPattern>
<M42BuildPackage>true</M42BuildPackage>
```
Das Package wird ueber `M42SandboxedExtension.targets` gebaut. Ein erfolgreicher Release-Build erzeugt:
```text
artifacts/<PackageName> v<Version>/
artifacts/<PackageName> v<Version>.zip
```
Build-Befehl:
```powershell
dotnet build "C:\Workspace\C4IT FASD\F4SD_M42WebApi\C4IT - F4SD - M42WebApi.sln" -c Release
```
## Host-Konfig
Referenzen auf Matrix42-DLLs sollen gegen die 26.1 Libraries zeigen und normalerweise `Private=false` haben, damit keine unnoetigen Matrix42-Plattform-DLLs ins Paket kopiert werden.
Die Host-Konfig muss exakt zum Assembly-Namen passen:
```text
C4ITF4SDM42WebApi.dll.host.config
<AssemblyName>.dll.host.config
```
Final bewaehrte Minimal-Konfig:
## Paketbau
Das Paket wird ueber `M42SandboxedExtension.targets` gebaut.
Aktuelle Regeln in diesem Repo:
- `Debug` baut Debug-DLLs und ein Debug-Paket.
- `Release` baut ein unsigniertes Release-Paket.
- `Release_signed` baut ein Release-Paket und aktiviert `M42SignAssemblies=true`.
- Artefakte liegen getrennt nach Konfiguration unter `artifacts/<Configuration>/`.
- Die Package-Version wird aus der `AssemblyVersion` der gebauten WebApi-Assembly gelesen.
- `M42PackageVersion` wurde entfernt und soll nicht wieder eingefuehrt werden.
Die zentrale Version liegt in `SharedAssemblyInfo.cs`.
Beispiele:
```powershell
dotnet build "C:\Workspace\C4IT FASD\F4SD_M42WebApi\C4IT - F4SD - M42WebApi.sln" -c Debug
dotnet build "C:\Workspace\C4IT FASD\F4SD_M42WebApi\C4IT - F4SD - M42WebApi.sln" -c Release
dotnet build "C:\Workspace\C4IT FASD\F4SD_M42WebApi\C4IT - F4SD - M42WebApi.sln" -c Release_signed
```
Visual Studio:
- `Debug`: Debugging und Testpakete.
- `Release`: Release ohne Signierung.
- `Release_signed`: Release mit Signierung.
Bei `Release_signed` werden alle Paket-DLLs in einem einzigen `signtool sign`-Aufruf signiert.
Das vermeidet eine separate Passwortabfrage pro DLL, wenn das Zertifikat interaktiv entsperrt werden muss.
Signierbare MSBuild-Properties:
```powershell
/p:M42SignAssemblies=true
/p:M42SignTool="C:\Path\To\signtool.exe"
/p:M42SignCertificateThumbprint="<thumbprint>"
/p:M42SignCertificateFile="C:\Path\To\certificate.pfx"
/p:M42SignCertificatePassword="<password>"
/p:M42SignTimestampUrl="http://rfc3161timestamp.globalsign.com/advanced"
/p:M42SignOptions="/a"
```
## Package-Struktur
Das neue Paket basiert auf einem `PackageTemplate` mit:
- `package.json`
- `install.xml`
- `install/...`
- `BasePackage/Assemblies` als Build-Ziel fuer Assemblies
Beim Portieren eines Legacy-Pakets:
1. Altes Paket entpacken.
2. WebAPI-Service (`PLSLServiceTypeWebAPI`) und Operationen (`PLSLWebServiceOperation`) identifizieren.
3. Extension-/Assembly-ID beibehalten, wenn ein Update statt einer Neuinstallation gewollt ist.
4. Operation-IDs nur dann aendern, wenn bewusst neue Operationen entstehen sollen.
5. Obsolete oder entfernte Schema-Attribute aus 26.1 entfernen.
6. Nach der ersten lauffaehigen Version die Webservice-Operationen in Matrix42 synchronisieren, exportieren und die synchronisierten Contracts in die Paketdateien mergen.
Wichtiges finales Learning zu Webservice-Operationen:
- Wenn ein Endpoint nur nach "Service synchronisieren" korrekt funktioniert, sind die `PLSLWebServiceOperation`-Contracts im Paket nicht mehr synchron zum Controller.
- Die synchronisierten Operationen exportieren und mit den bestehenden Paketdateien mergen.
- Bestehende `PLSLWebServiceOperation.ID`s nicht durch Export-IDs ersetzen, sonst entstehen auf Bestandssystemen doppelte Operationen.
- Bestehende `PDRAudienceClass.ID`s ebenfalls erhalten.
- Nur fachliche Operation-Felder uebernehmen: `ResponseContract`, `RequestContract`, `Name`, `RouteTemplate`, `SupportedOperation`, `Type`, `IsPublic`.
- Neue Operationen, die bisher nicht im Paket vorhanden waren, duerfen die exportierten IDs verwenden, wenn sie aus dem Zielsystem stammen, auf dem sie bereits synchronisiert wurden.
- Operation-Dateien nach Operation benennen, z. B. `getticketlist.dat`, `getpickup.dat`, `isalive.dat`. Das erleichtert Reviews und verhindert Verwechslungen mit generischen `02-01-xxxx PLSLWebServiceOperationType.dat`-Dateien.
- Jede Datei aus `PackageTemplate/install/0002_WebServiceOperation` muss in `PackageTemplate/install.xml` referenziert sein.
Validierung:
```powershell
# XML parsebar?
python -c "import pathlib,xml.etree.ElementTree as ET; [ET.parse(p) for p in pathlib.Path('PackageTemplate/install/0002_WebServiceOperation').glob('*.dat')]"
# Debug-Paket bauen und pruefen, ob alle Operation-Dateien im Paket liegen
dotnet build "C:\Workspace\C4IT FASD\F4SD_M42WebApi\C4IT - F4SD - M42WebApi.sln" -c Debug
```
Konkretes 26.1-Learning:
- `UsedInTypeSPSActivityTypeAlert` gibt es in 26.1 nicht mehr und muss aus dem Paket entfernt werden.
## Host-Konfig und Module
Mit so wenig Modulen wie moeglich starten. Jedes zusaetzliche Modul kann transitive Unity-Registrierungen erzwingen, die bereits beim Controller- oder Service-Aufbau scheitern.
Minimaler Startpunkt fuer einfache Endpoints:
```xml
<?xml version="1.0" encoding="utf-8" ?>
@@ -63,27 +151,35 @@ Final bewaehrte Minimal-Konfig:
</host>
```
Wichtig: Module nicht auf Vorrat laden. Jedes zusaetzliche Modul kann transitive Unity-Registrierungen erzwingen, die fuer den konkreten Webservice gar nicht benoetigt werden.
Der aktuelle Stand dieser Extension benoetigt fuer alle Funktionen mehr Module, insbesondere wegen Journal, Storage, Pandora, Teams Notification, ServiceConnection, Auth und Aurora Search. Aktuelle Host-Konfig:
Problematische Module in dieser Migration:
- `Matrix42.Pandora.Persistence`
- `Matrix42.Pandora.ServiceStore`
- `Matrix42.Pandora.BizLogic`
- `Matrix42.Pandora.Services`
- `Matrix42.ServiceManager.BizLogic`
- eigenes Webservice-Assembly als Host-Modul
Diese Module fuehrten unter anderem zu Fehlern wie:
```text
IEntityDataService is an interface and cannot be constructed
IUserProfileRepository is an interface and cannot be constructed
IApiExplorer is an interface and cannot be constructed
Could not load type 'System.Web.Routing.RouteTable'
IComplianceRuleManager is an interface and cannot be constructed
```xml
<modules>
<module assembly="C4ITF4SDM42WebApi" />
<module assembly="Matrix42.DataLayer.Persistence" />
<module assembly="Matrix42.Services.WebApi" />
<module assembly="Matrix42.ServiceRepository.BizLogic" />
<module assembly="Matrix42.Pandora.ServiceStore" />
<module assembly="Matrix42.Pandora.Persistence" />
<module assembly="Matrix42.Pandora.BizLogic" />
<module assembly="Matrix42.Pandora.Services" />
<module assembly="Matrix42.Distributed.Redis.Cache" />
<module assembly="Matrix42.StorageService.BizLogic" />
<module assembly="Matrix42.MsTeamsNotification.BizLogic" />
<module assembly="Matrix42.ServiceConnection.Persistence" />
<module assembly="Matrix42.Auth.BizLogic" />
<module assembly="Matrix42.ServiceConnection.BizLogic" />
<module assembly="Matrix42.Integration.Aurora.General" />
<module assembly="Matrix42.Integration.Aurora.Search.BizLogic" />
<module assembly="update4u.SPS.ComplianceRules.BizLogic" />
<module assembly="update4u.SPS.Security" />
<module assembly="Matrix42.BizLogic.Journal" />
<module assembly="Matrix42.ServiceManager.BizLogic" />
</modules>
```
Regel: Wenn ein weiteres Interface nicht aufgeloest werden kann, nicht raten. In den Matrix42-DLLs nach dem Registrator/der Implementierung fuer genau dieses Interface suchen und nur das passende Modul laden.
## Controller-Konstruktion
Nicht so:
@@ -92,16 +188,17 @@ Nicht so:
public MyController(IEntityDataService entityDataService, IJournalService journalService, IPandoraUserProfile userProfile)
```
Diese direkte Konstruktor-Injection zwingt Matrix42/Unity, alle Services schon beim Erzeugen des Controllers aufzuloesen. Dadurch kann bereits `isAlive` scheitern, obwohl der Endpoint selbst keinen dieser Services nutzt.
Das zwingt Unity, alle Services schon beim Erzeugen des Controllers aufzuloesen. Dadurch kann bereits `isAlive` scheitern, obwohl der Endpoint selbst keinen dieser Services braucht.
Besser:
Bewaehrt:
```csharp
private readonly IDependencyResolver _resolver;
public MyController(IDependencyResolver resolver)
public MyController(IDependencyResolver resolver, IEnumerationProvider enumerationProvider)
{
_resolver = resolver ?? throw new ArgumentNullException(nameof(resolver));
_enumerationProvider = enumerationProvider ?? throw new ArgumentNullException(nameof(enumerationProvider));
}
private T GetRequiredService<T>() where T : class
@@ -114,16 +211,23 @@ private T GetRequiredService<T>() where T : class
}
```
Fachservices dann nur im jeweiligen Endpoint oder Helper lazy aufloesen.
Fachservices im jeweiligen Endpoint oder Helper lazy aufloesen.
## Dependency-Registrator
Die Extension kann eigene Sandbox-Registrierungen bereitstellen, wenn der Matrix42-Sandbox-Host eine Plattform-Instanz nicht selbst registriert.
Konkretes Learning:
- Fuer den Journal-Pfad fehlte `System.Web.Http.Description.IApiExplorer`.
- Die Extension registriert eine konkrete `ApiExplorer`-Instanz ueber `IDependencyRegistrator`.
- Das eigene Assembly muss dafuer als Host-Modul geladen werden.
Das ist kein Workaround im fachlichen Code, sondern eine Host-Registrierung fuer eine fehlende Infrastruktur-Dependency.
## WebAPI-Rueckgaben
Matrix42 serialisiert manche Rueckgabetypen anders als klassische ASP.NET Web API.
Bewaehrt:
- Datenendpoints geben direkt Nutzdaten zurueck, z. B. `Task<EntityEnumeration>` oder `Task<object>`.
- `isAlive` gibt `IHttpActionResult` mit `StatusCodeResult(HttpStatusCode.NoContent)` zurueck.
Matrix42 serialisiert `HttpResponseMessage` in dieser Runtime nicht wie klassische ASP.NET Web API, sondern als Nutzdatenobjekt.
Nicht fuer normale Datenendpoints verwenden:
@@ -132,56 +236,158 @@ Task<HttpResponseMessage>
HttpResponseExtensions.CreateResponse(...)
```
In dieser Runtime wurde ein `HttpResponseMessage` als JSON-Objekt serialisiert, z. B. mit `Version`, `Content`, `StatusCode`, `Headers`.
Nicht fuer `isAlive` verwenden:
```csharp
public void isAlive()
```
Das fuehrte zu:
Symptom:
```json
{"result":null,"parameters":{}}
{"Version":"1.1","Content":{...},"StatusCode":200}
```
Bewaehrter Healthcheck:
Bewaehrt:
- Datenendpoints geben direkte Nutzdaten zurueck, z. B. `Task<List<T>>`, `Task<object>` oder `Task<EntityEnumeration>`.
- Leere Listen duerfen nicht `null` sein.
- `isAlive` gibt `IHttpActionResult` mit einem expliziten HTTP-204-Response zurueck.
Healthcheck:
```csharp
[Route("isAlive"), HttpGet]
public IHttpActionResult isAlive()
{
return new StatusCodeResult(HttpStatusCode.NoContent);
var response = new HttpResponseMessage(HttpStatusCode.NoContent)
{
RequestMessage = Request
};
response.Headers.ConnectionClose = true;
return ResponseMessage(response);
}
```
## Pickups/Enumerations
Nicht verwenden:
`IEntityDataService.GetEnumeration(...)` ist bequem, zieht aber die Pandora-Service-Schicht herein. Das war in der Sandbox zu schwer und verursachte transitive Dependency-Probleme.
```csharp
public void isAlive()
```
Bewaehrt ist:
Symptom:
```json
{"result":null,"parameters":{}}
```
## Null-Rueckgaben
Matrix42/Pandora behandelt `null` als fehlerhafte Operation-Response.
Symptom:
```text
Method getTicketList returned null
```
Regel:
- Listenendpoints geben bei "nichts gefunden" `new List<T>()` zurueck.
- Objekte geben ein leeres DTO oder 204 zurueck, aber nicht unbewusst `null`.
- Strings koennen bei Bedarf `string.Empty` statt `null` liefern.
## Routen und Parameterbindung
Finales Learning: Fuer Legacy-Kompatibilitaet muessen Route, `PLSLWebServiceOperation.RouteTemplate`, `[FromUri]` und die alten Client-URLs zusammen betrachtet werden.
Bewaehrte Regeln:
- Die Route-Attribute aus der funktionierenden Legacy-Version uebernehmen.
- Query-basierte Legacy-Endpoints bleiben query-basiert, z. B. `[Route("getTicketList")]`.
- Path-basierte Legacy-Endpoints bleiben path-basiert, z. B. `[Route("getPickup/{name}")]`.
- GET-Parameter mit `[FromUri]` markieren.
- Zusaetzlich einen kleinen zentralen Query-Fallback verwenden, weil in 26.1 einzelne optionale Queryparameter trotz `[FromUri]` nicht immer in der Methode ankamen.
- Keine doppelten Controller-Methoden fuer alte und neue URL-Formen bauen.
- Die Postman-Collection testet bewusst die alten Client-URLs.
Beispiel Query-Route:
```csharp
[Route("getDirectLinkCreateTicket"), HttpGet]
public async Task<DirectLink> getDirectLinkCreateTicket(
[FromUri] string sid = "",
[FromUri] string assetname = "")
{
sid = QueryValue(sid, nameof(sid));
assetname = QueryValue(assetname, nameof(assetname));
...
}
```
Beispiel Path-Route mit zusaetzlichen Queryparametern:
```csharp
[Route("getPickup/{name}"), HttpGet]
public async Task<EntityEnumeration> getPickup(
[FromUri] string name,
[FromUri] EntityEnumerationVisibilityMode mode = EntityEnumerationVisibilityMode.None,
[FromUri] int group = -1)
{
name = QueryValue(name, nameof(name));
mode = QueryValue(mode, nameof(mode));
group = QueryValue(group, nameof(group));
...
}
```
Der zentrale Query-Fallback ist bewusst klein und verwendet die strukturierte WebAPI-API statt eigenes URL-Parsen:
```csharp
private string GetQueryValue(string name)
{
return Request?.GetQueryNameValuePairs()
.FirstOrDefault(pair => string.Equals(pair.Key, name, StringComparison.OrdinalIgnoreCase))
.Value;
}
private string QueryValue(string value, string name)
{
return GetQueryValue(name) ?? value ?? string.Empty;
}
```
Betroffene alte Testformate:
```text
getTicketList?sid=...&hours=...&queueoption=...&queues=...
getDirectLinkCreateTicket?sid=...&assetname=...
getDirectLinkF4SD?eoid=...&type=...
getPickup/<name>?mode=...&group=...
```
## Pickups und Enumerations
`IEntityDataService.GetEnumeration(...)` ist bequem, zieht aber Pandora-Services herein. Das war fuer reine Pickups zu schwer.
Bewaehrt:
```csharp
Matrix42.Persistence.Contracts.IEnumerationProvider
```
Dieser Service wird ueber `Matrix42.DataLayer.Persistence` bereitgestellt und liefert eine `DataTable`. Wenn der alte API-Vertrag `EntityEnumeration` bleiben soll, muss die `DataTable` selbst gemappt werden.
Dieser Service kommt ueber `Matrix42.DataLayer.Persistence` und liefert eine `DataTable`. Wenn der alte API-Vertrag `EntityEnumeration` bleiben soll, muss die `DataTable` selbst gemappt werden.
Gepruefte Alternativen:
- `Matrix42.Pandora.Contracts.IEntityDataService`: liefert direkt `EntityEnumeration`, benoetigt aber Pandora-Module.
- `update4u.SPS.DataLayer.Contracts.IPickupDataService`: liefert ebenfalls nur `DataTable`, bringt gegenueber `IEnumerationProvider` keinen klaren Vorteil.
- `update4u.SPS.DataLayer.Contracts.IPickupDataService`: liefert ebenfalls `DataTable`, ohne klaren Vorteil gegenueber `IEnumerationProvider`.
Pragmatische Empfehlung:
Empfehlung:
- Fuer reine Pickup-Lesefunktionen `IEnumerationProvider` verwenden.
- Nur dann Pandora-Services laden, wenn es keine schlanke Alternative gibt.
- Route-Parameter defensiv behandeln. In dieser Migration kam der Pickup-Name einmal leer an, obwohl die URL ihn enthielt. Ein Fallback auf das letzte URL-Segment hat das stabilisiert.
- Pandora nur laden, wenn ein Endpoint es wirklich benoetigt.
## Aktueller Benutzer
`IPandoraUserProfile` nicht im Controller injizieren. Fuer `getMyRoleMemberships` reicht der Matrix42 Principal:
`IPandoraUserProfile` nicht im Controller injizieren.
Fuer `getMyRoleMemberships` reicht der Matrix42 Principal:
```csharp
var principal = Thread.CurrentPrincipal as IM42Principal;
@@ -192,45 +398,81 @@ var userId = principal?.InteractivePrincipal?.M42Identity?.UserFragmentID
Danach kann der vorhandene ASQL-/Helper-Code mit der `Guid` weiterarbeiten.
## Journal-Service
## Ticket-Historie und Journal
`IJournalService` benoetigt zusaetzliche Matrix42-Service-Module. `Matrix42.ServiceManager.BizLogic` hat in dieser Migration wieder eine transitive `IComplianceRuleManager`-Abhaengigkeit erzeugt und darf deshalb nicht pauschal geladen werden.
Ziel: den Matrix42-Service nutzen, nicht eigene Journal-Logik nachbauen.
Status:
Finaler Ansatz:
- Ticket-Historie ueber `IJournalService` ist mit der Minimal-Host-Konfig nicht abgesichert.
- Fuer weitere Migrationen zuerst pruefen, ob ein kleineres Modul wie `Matrix42.ServiceManager.Services` reicht.
- Wenn nicht, Journal-Daten alternativ ueber DataLayer/ASQL lesen oder den Endpoint bewusst ausklammern.
- `IJournalService` ueber den Matrix42-Resolver laden.
- Keine direkte Konstruktion von `JournalService`.
- Keine eigenen DispatchProxy-/NoOp-Services.
- Keine HTTP-Weiterleitung an interne Admin-APIs.
- Keine Storage-Fallback-Journal-Implementierung als finaler Pfad.
- `GetJournalList` per Reflection gegen die zur Laufzeit vorhandene Signatur aufrufen, weil sich die Signatur zwischen 26.1 Patch-Leveln unterscheiden kann.
## Typische Fehlersymptome und Ursache
Warum Reflection hier akzeptiert wurde:
- Der alte direkte Compile-Time-MethodRef brach mit `MissingMethodException`.
- Die geladene Runtime-DLL hatte eine andere `IJournalService.GetJournalList`-Signatur.
- Die Reflection sucht kompatible Journal-Reader-Methoden und liefert klare Diagnose, wenn keine passende Signatur existiert.
Typische Fehler auf dem Weg:
```text
Cannot create instance of <Controller>: The current type, <Interface>, is an interface and cannot be constructed.
Method not found: IJournalService.GetJournalList(...)
IJournalService could not be resolved
IExternalAuthService is an interface and cannot be constructed
IOAuth2AuthorizeService is an interface and cannot be constructed
IApiExplorer is an interface and cannot be constructed
IRequestPropertiesProvider is an interface and cannot be constructed
IExternalSearchService is an interface and cannot be constructed
```
Meistens direkte Konstruktor-Injection oder ein zu breit geladenes Host-Modul.
Learning: Bei diesen Fehlern nicht weiter im Endpoint herumprobieren, sondern die fehlende Host-Registrierung bzw. das passende Matrix42-Modul identifizieren.
```text
Could not load type 'System.Web.Routing.RouteTable'
## Overview-Endpoints
`getTicketOverviewCounts` liefert Counts fuer mehrere Keys.
`getTicketOverviewRelations` nimmt genau einen `key` und ein `count`.
Postman-Learning:
- `getTicketOverviewCounts personal` und `getTicketOverviewCounts role` leiten `scope`, `overviewKey` und `overviewRelationExpectedCount` ab.
- `getTicketOverviewRelations` nutzt diese Variablen.
- Der Relations-Test erwartet, dass `response.length` dem vorher abgeleiteten Count entspricht.
- Im normalen Collection-Lauf ueberschreibt `role` die Werte von `personal`, weil `role` nach `personal` ausgefuehrt wird.
## Direct Link
Fuer F4SD Direct Links ist der Typ in der alten Integration nicht der Matrix42 ActivityType, sondern der F4SD-Typ.
Postman setzt deshalb nach `getTicketList`:
```javascript
pm.collectionVariables.set("type", "ticket");
```
Ein altes `System.Web`-/WebApi-Modul wurde in der Sandbox aktiviert. Nicht durch eigene `IApiExplorer`-Registrierung kompensieren, sondern die Ursache entfernen.
`objectType` bleibt separat auf `ticket.ActivityType`, falls der technische Matrix42-Typ fuer andere Tests gebraucht wird.
```json
{"Version":"1.1","Content":{...},"StatusCode":200}
```
## Postman-Collection
Ein `HttpResponseMessage` wurde als Nutzdatenobjekt serialisiert. Action-Signatur auf direkten Nutzdatentyp umstellen.
Die Collection ist Teil der Migration und Regression.
```json
{"result":null,"parameters":{}}
```
Regeln:
Ein `void`-Endpoint wurde als Matrix42-Result ohne Nutzdaten serialisiert. Fuer echten NoContent `StatusCodeResult(HttpStatusCode.NoContent)` verwenden.
- Basic Auth ueber Variablen `basicUsername` und `basicPassword`.
- `baseUrl` enthaelt `/m42Services`.
- Legacy-Query-Routen testen, nicht nur neue path-basierte Formen.
- `getTicketList` zieht `eoid` und `ticketObjectId` aus `TicketObjectId`.
- `type` fuer Direct Link bleibt `ticket`.
- `isAlive` erwartet 204 und keinen Body.
- Allgemeiner Test erkennt versehentlich serialisierte `HttpResponseMessage`-Objekte.
## Smoke-Test-Reihenfolge
Nach jeder Paketinstallation in Matrix42:
Nach jeder Paketinstallation:
1. `GET /m42Services/api/<prefix>/isalive`
Erwartung: HTTP 204 No Content.
@@ -238,26 +480,94 @@ Nach jeder Paketinstallation in Matrix42:
Erwartung: JSON-Nutzdaten, keine `HttpResponseMessage`-Huelle.
3. `GET /m42Services/api/<prefix>/getMyRoleMemberships`
Erwartung: aktueller Benutzer und Rollen, kein `IPandoraUserProfile`-Fehler.
4. Komplexere Ticket-/Overview-Endpoints.
5. Journal-/History-Endpoints separat pruefen, weil hier zusaetzliche Services benoetigt werden koennen.
4. `GET /m42Services/api/<prefix>/getTicketList?...`
Erwartung: leere Liste oder Tickets, aber kein `returned null`.
5. Direct Links mit Legacy-Query-Routen.
6. Overview Counts und Relations.
7. Journal-/History-Endpoints zuletzt, weil hier die meisten Matrix42-Services transitiv benoetigt werden.
## Typische Fehlersymptome
```text
Cannot create instance of <Controller>: The current type, <Interface>, is an interface and cannot be constructed.
```
Meist direkte Konstruktor-Injection oder fehlendes Host-Modul.
```text
Could not load type 'System.Web.Routing.RouteTable'
```
Ungeeignetes altes `System.Web`-/WebApi-Modul in der Sandbox. Ursache entfernen, nicht weitere Alt-Abhaengigkeiten nachladen.
```text
IApiExplorer is an interface and cannot be constructed
```
Sandbox-Host stellt diese WebApi-Explorer-Instanz nicht automatisch bereit. Ueber eigenen `IDependencyRegistrator` registrieren.
```json
{"Version":"1.1","Content":{...},"StatusCode":200}
```
Ein `HttpResponseMessage` wurde als DTO serialisiert. Rueckgabe auf direkten Nutzdatentyp umstellen.
```json
{"result":null,"parameters":{}}
```
Void-Endpoint oder falsch behandelte leere Rueckgabe. Fuer NoContent einen `IHttpActionResult` mit HTTP 204 liefern.
```text
Method <name> returned null
```
Endpoint gibt `null` zurueck. Leeres DTO oder leere Liste zurueckgeben.
## Verworfene Zwischenansaetze
Diese Ansaetze haben nicht nachhaltig geholfen und sollen nicht erneut aufgebaut werden:
- Matrix42-Fachinterfaces direkt im Controller-Konstruktor injizieren.
- Immer mehr Module auf Vorrat laden, ohne die konkrete fehlende Registrierung zu kennen.
- `HttpResponseMessage` als Datenantwort verwenden.
- Query-Parameter per eigenem Helper aus `RequestUri` lesen.
- Doppelte Controller-Methoden fuer alte Query-URLs und neue Path-URLs bauen.
- `JournalService` direkt konstruieren.
- NoOp-/Proxy-Abhaengigkeiten fuer Journal-Services erzeugen.
- Journal-Historie aus unvollstaendigen Kommentarfeldern nachbauen.
- Interne Matrix42 Admin-Webservices als finalen Journal-Pfad weiterleiten.
## Migrationsablauf fuer weitere Extensions
1. Alten Package-Inhalt entpacken und Assembly-/Extension-ID identifizieren.
2. Neues 26.1-Projekt ueber Scaffolder/Beispielstruktur anlegen oder bestehendes Projekt angleichen.
3. `Matrix42.WebApi.Contracts` und `Matrix42.Hosting.Contracts` referenzieren.
4. Controller auf `IDependencyResolver` umstellen.
5. Direkte Konstruktor-Injection von Matrix42-Fachinterfaces entfernen.
6. Host-Konfig mit minimalen Modulen starten.
7. Rueckgaben pruefen: direkte Nutzdaten statt `HttpResponseMessage`, `StatusCodeResult` fuer 204.
8. Package-Build ueber MSBuild automatisieren.
9. Paket installieren und Smoke-Tests ausfuehren.
10. Fehlende Services einzeln und begruendet nachladen, nie ganze Pandora-/ServiceManager-Stacks auf Vorrat.
1. Ziel-Commit der Legacy-Funktionalitaet festlegen.
2. Altes Paket entpacken und IDs dokumentieren.
3. Herstellerbeispiel/Scaffolder-Struktur als 26.1-Referenz verwenden.
4. Projekt auf .NET 8 und `Matrix42.WebApi.Contracts.ApiController` umstellen.
5. Controller-Konstruktor auf minimale Infrastruktur-Services reduzieren.
6. Host-Konfig minimal starten.
7. Package-Build in MSBuild integrieren.
8. AssemblyVersion als einzige Package-Versionsquelle verwenden.
9. WebAPI-Rueckgaben auf direkte DTOs/Listen umstellen.
10. `isAlive` auf echten 204 umstellen.
11. Controller-Routen aus der funktionierenden Legacy-Version uebernehmen.
12. GET-Parameter mit `[FromUri]` versehen und fehlende Querywerte zentral ueber `Request.GetQueryNameValuePairs()` nachziehen.
13. Pickups zuerst ueber schlanke Services loesen.
14. Komplexe Matrix42-Services erst bei Bedarf laden.
15. Bei Unity-Fehlern konkrete Implementierung/Registrator suchen.
16. Webservice-Operationen nach erfolgreicher Installation in Matrix42 synchronisieren.
17. Synchronisierte Operationen exportieren und in die Paketdateien mergen, ohne bestehende IDs zu ersetzen.
18. Operation-Dateien sprechend nach Operation benennen und in `install.xml` referenzieren.
19. Postman-Collection fuer alte Client-Routen aufbauen.
20. Paket installieren, Service synchronisieren und Smoke-Tests ausfuehren.
21. Erst nach erfolgreicher Kompatibilitaet fachliche Weiterentwicklungen einbringen.
## Git-/Build-Hinweise in diesem Repo
## Git- und Datei-Hinweise
- Vor Aenderungen `git status` pruefen.
- Geaenderte Textdateien mit CRLF speichern.
- Nach Aenderungen Release-Build ausfuehren.
- Danach committen und pushen.
- Unrelated/untracked Dateien nicht mitcommitten.
- Textdateien in diesem Repo mit CRLF speichern.
- `.dat`-Dateien behalten ihren UTF-8-BOM.
- Controller-/JSON-Dateien ohne unnoetigen BOM lassen.
- Debug-Build fuer Debugging, Release/Release_signed fuer Auslieferung.
- Postman-Collection nach JSON-Aenderungen immer parsen/validieren.

View File

@@ -0,0 +1,934 @@
{
"info": {
"_postman_id": "3c5d2c5b-26e1-4d8e-bf4c-f4sdm42webapi",
"name": "C4IT F4SD M42 WebApi",
"description": "Systematic smoke-test collection for all active endpoints in F4SDM42WebApiController. Configure the collection variables before running. The default baseUrl includes /m42Services.",
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
},
"auth": {
"type": "basic",
"basic": [
{
"key": "username",
"value": "{{basicUsername}}",
"type": "string"
},
{
"key": "password",
"value": "{{basicPassword}}",
"type": "string"
}
]
},
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test(\"Request returns a successful or redirect status\", function () {",
" pm.expect(pm.response.code).to.be.below(400);",
"});",
"",
"if (pm.response.text()) {",
" pm.test(\"Response body is valid JSON when JSON content is returned\", function () {",
" const contentType = pm.response.headers.get(\"Content-Type\") || \"\";",
" if (contentType.toLowerCase().includes(\"json\")) {",
" pm.response.to.be.json;",
" }",
" });",
"",
" const contentType = pm.response.headers.get(\"Content-Type\") || \"\";",
" if (contentType.toLowerCase().includes(\"json\")) {",
" const json = pm.response.json();",
" const isSerializedHttpResponse = json && !Array.isArray(json) &&",
" Object.prototype.hasOwnProperty.call(json, \"Version\") &&",
" Object.prototype.hasOwnProperty.call(json, \"Content\") &&",
" Object.prototype.hasOwnProperty.call(json, \"StatusCode\") &&",
" Object.prototype.hasOwnProperty.call(json, \"IsSuccessStatusCode\");",
"",
" pm.test(\"Response is not a serialized HttpResponseMessage\", function () {",
" pm.expect(isSerializedHttpResponse).to.equal(false);",
" });",
" }",
"}"
]
}
}
],
"variable": [
{
"key": "baseUrl",
"value": "https://srvwsm001.imagoverum.com/m42Services"
},
{
"key": "basicUsername",
"value": "imagoverum\\vvogel"
},
{
"key": "basicPassword",
"value": "Matrix42"
},
{
"key": "sid",
"value": "S-1-5-21-735677975-861733296-3045004705-8205"
},
{
"key": "upn",
"value": ""
},
{
"key": "userId",
"value": "00000000-0000-0000-0000-000000000000"
},
{
"key": "ticketObjectId",
"value": "00000000-0000-0000-0000-000000000000"
},
{
"key": "eoid",
"value": "00000000-0000-0000-0000-000000000000"
},
{
"key": "objectType",
"value": "SPSActivityTypeIncident"
},
{
"key": "type",
"value": "SPSActivityTypeIncident"
},
{
"key": "assetName",
"value": ""
},
{
"key": "hours",
"value": "9999"
},
{
"key": "scope",
"value": "personal"
},
{
"key": "overviewKey",
"value": "open"
},
{
"key": "overviewRelationExpectedCount",
"value": "0"
},
{
"key": "overviewKeys",
"value": "TicketsNew,TicketsActive,TicketsCritical,TicketsNewInfo,IncidentNew,IncidentActive,IncidentCritical,IncidentNewInfo,UnassignedTickets,UnassignedTicketsCritical"
},
{
"key": "queueOption",
"value": "0"
},
{
"key": "queues",
"value": ""
},
{
"key": "roleGuid",
"value": "00000000-0000-0000-0000-000000000000"
},
{
"key": "pickupName",
"value": "DWPUseCasePickup"
},
{
"key": "pickupMode",
"value": "None"
},
{
"key": "pickupGroup",
"value": "-1"
},
{
"key": "logCount",
"value": "50"
},
{
"key": "logFilter",
"value": ""
},
{
"key": "logEntryId",
"value": "0"
}
],
"item": [
{
"name": "01 Health and diagnostics",
"item": [
{
"name": "isAlive returns 204 No Content",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test(\"isAlive returns 204\", function () {",
" pm.response.to.have.status(204);",
"});",
"pm.test(\"No response body or empty Matrix42 wrapper body\", function () {",
" pm.expect([\"\", \"{}\"]).to.include(pm.response.text());",
"});"
]
}
}
],
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "{{baseUrl}}/api/c4itf4sdwebapi/isAlive",
"host": [
"{{baseUrl}}"
],
"path": [
"api",
"c4itf4sdwebapi",
"isAlive"
]
}
}
},
{
"name": "loglevel enable debug",
"request": {
"method": "GET",
"header": [
{
"key": "Accept",
"value": "text/plain"
}
],
"url": {
"raw": "{{baseUrl}}/api/c4itf4sdwebapi/loglevel?debug=1",
"host": [
"{{baseUrl}}"
],
"path": [
"api",
"c4itf4sdwebapi",
"loglevel"
],
"query": [
{
"key": "debug",
"value": "1"
}
]
}
}
},
{
"name": "loglevel reset info",
"request": {
"method": "GET",
"header": [
{
"key": "Accept",
"value": "text/plain"
}
],
"url": {
"raw": "{{baseUrl}}/api/c4itf4sdwebapi/loglevel?debug=0",
"host": [
"{{baseUrl}}"
],
"path": [
"api",
"c4itf4sdwebapi",
"loglevel"
],
"query": [
{
"key": "debug",
"value": "0"
}
]
}
}
},
{
"name": "log text response",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "{{baseUrl}}/api/c4itf4sdwebapi/log?download=0&count={{logCount}}&filter={{logFilter}}",
"host": [
"{{baseUrl}}"
],
"path": [
"api",
"c4itf4sdwebapi",
"log"
],
"query": [
{
"key": "download",
"value": "0"
},
{
"key": "count",
"value": "{{logCount}}"
},
{
"key": "filter",
"value": "{{logFilter}}"
}
]
}
}
},
{
"name": "log file download",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "{{baseUrl}}/api/c4itf4sdwebapi/log?download=1&count={{logCount}}&filter={{logFilter}}",
"host": [
"{{baseUrl}}"
],
"path": [
"api",
"c4itf4sdwebapi",
"log"
],
"query": [
{
"key": "download",
"value": "1"
},
{
"key": "count",
"value": "{{logCount}}"
},
{
"key": "filter",
"value": "{{logFilter}}"
}
]
}
}
}
]
},
{
"name": "02 Tickets",
"item": [
{
"name": "getTicketList by SID",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test(\"Ticket list is an array\", function () {",
" const text = pm.response.text();",
" pm.expect(text).to.not.equal(\"\");",
" const json = pm.response.json();",
" pm.expect(Array.isArray(json)).to.equal(true);",
"});",
"",
"const tickets = pm.response.text() ? pm.response.json() : null;",
"if (Array.isArray(tickets) && tickets.length > 0) {",
" const ticket = tickets[0];",
" if (ticket.TicketObjectId) {",
" pm.collectionVariables.set(\"ticketObjectId\", ticket.TicketObjectId);",
" pm.collectionVariables.set(\"eoid\", ticket.TicketObjectId);",
" }",
" if (ticket.ActivityType) {",
" pm.collectionVariables.set(\"objectType\", ticket.ActivityType);",
" }",
" pm.collectionVariables.set(\"type\", \"ticket\");",
" pm.test(\"Captured ticket object id and type\", function () {",
" pm.expect(pm.collectionVariables.get(\"eoid\")).to.match(/^[0-9a-fA-F-]{36}$/);",
" pm.expect(pm.collectionVariables.get(\"type\")).to.be.a(\"string\").and.not.empty;",
" });",
"}"
]
}
}
],
"request": {
"method": "GET",
"header": [
{
"key": "Accept",
"value": "application/json"
}
],
"url": {
"raw": "{{baseUrl}}/api/c4itf4sdwebapi/getTicketList?sid={{sid}}&hours={{hours}}&queueoption={{queueOption}}&queues={{queues}}",
"host": [
"{{baseUrl}}"
],
"path": [
"api",
"c4itf4sdwebapi",
"getTicketList"
],
"query": [
{
"key": "sid",
"value": "{{sid}}"
},
{
"key": "hours",
"value": "{{hours}}"
},
{
"key": "queueoption",
"value": "{{queueOption}}"
},
{
"key": "queues",
"value": "{{queues}}"
}
]
}
}
},
{
"name": "getTicketDetails by objectId",
"request": {
"method": "GET",
"header": [
{
"key": "Accept",
"value": "application/json"
}
],
"url": {
"raw": "{{baseUrl}}/api/c4itf4sdwebapi/getTicketDetails?objectId={{eoid}}",
"host": [
"{{baseUrl}}"
],
"path": [
"api",
"c4itf4sdwebapi",
"getTicketDetails"
],
"query": [
{
"key": "objectId",
"value": "{{eoid}}"
}
]
}
}
},
{
"name": "getTicketHistory by objectId",
"request": {
"method": "GET",
"header": [
{
"key": "Accept",
"value": "application/json"
}
],
"url": {
"raw": "{{baseUrl}}/api/c4itf4sdwebapi/getTicketHistory?objectId={{eoid}}",
"host": [
"{{baseUrl}}"
],
"path": [
"api",
"c4itf4sdwebapi",
"getTicketHistory"
],
"query": [
{
"key": "objectId",
"value": "{{eoid}}"
}
]
}
}
},
{
"name": "getDirectLinkCreateTicket",
"request": {
"method": "GET",
"header": [
{
"key": "Accept",
"value": "application/json"
}
],
"url": {
"raw": "{{baseUrl}}/api/c4itf4sdwebapi/getDirectLinkCreateTicket?sid={{sid}}&assetname={{assetName}}",
"host": [
"{{baseUrl}}"
],
"path": [
"api",
"c4itf4sdwebapi",
"getDirectLinkCreateTicket"
],
"query": [
{
"key": "sid",
"value": "{{sid}}"
},
{
"key": "assetname",
"value": "{{assetName}}"
}
]
}
}
},
{
"name": "getDirectLinkF4SD",
"request": {
"method": "GET",
"header": [
{
"key": "Accept",
"value": "text/plain"
}
],
"url": {
"raw": "{{baseUrl}}/api/c4itf4sdwebapi/getDirectLinkF4SD?eoid={{eoid}}&type={{type}}",
"host": [
"{{baseUrl}}"
],
"path": [
"api",
"c4itf4sdwebapi",
"getDirectLinkF4SD"
],
"query": [
{
"key": "eoid",
"value": "{{eoid}}"
},
{
"key": "type",
"value": "{{type}}"
}
]
}
}
}
]
},
{
"name": "03 Ticket overview",
"item": [
{
"name": "getTicketOverviewCounts personal",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"const overviewCountsPersonalJson = pm.response.json();",
"const overviewCountsPersonal = overviewCountsPersonalJson.counts || overviewCountsPersonalJson.Counts || {};",
"const overviewPreferredKeysPersonal = (pm.collectionVariables.get(\"overviewKeys\") || \"\")",
" .split(\",\")",
" .map(key => key.trim())",
" .filter(Boolean);",
"const overviewRelationKeyPersonal = overviewPreferredKeysPersonal.find(key => Number(overviewCountsPersonal[key] || 0) > 0)",
" || Object.keys(overviewCountsPersonal).find(key => Number(overviewCountsPersonal[key] || 0) > 0)",
" || overviewPreferredKeysPersonal[0]",
" || Object.keys(overviewCountsPersonal)[0]",
" || \"\";",
"const overviewRelationCountPersonal = overviewRelationKeyPersonal ? Number(overviewCountsPersonal[overviewRelationKeyPersonal] || 0) : 0;",
"",
"pm.collectionVariables.set(\"scope\", \"personal\");",
"pm.collectionVariables.set(\"overviewKey\", overviewRelationKeyPersonal);",
"pm.collectionVariables.set(\"overviewRelationExpectedCount\", String(overviewRelationCountPersonal));",
"",
"pm.test(\"Captured personal overview relation parameters\", function () {",
" pm.expect(overviewCountsPersonal).to.be.an(\"object\");",
" pm.expect(pm.collectionVariables.get(\"scope\")).to.equal(\"personal\");",
" pm.expect(pm.collectionVariables.get(\"overviewKey\")).to.be.a(\"string\").and.not.empty;",
" pm.expect(Number(pm.collectionVariables.get(\"overviewRelationExpectedCount\"))).to.be.at.least(0);",
"});"
]
}
}
],
"request": {
"method": "GET",
"header": [
{
"key": "Accept",
"value": "application/json"
}
],
"url": {
"raw": "{{baseUrl}}/api/c4itf4sdwebapi/getTicketOverviewCounts?sid={{sid}}&scope=personal&keys={{overviewKeys}}&queueoption={{queueOption}}&queues={{queues}}",
"host": [
"{{baseUrl}}"
],
"path": [
"api",
"c4itf4sdwebapi",
"getTicketOverviewCounts"
],
"query": [
{
"key": "sid",
"value": "{{sid}}"
},
{
"key": "scope",
"value": "personal"
},
{
"key": "keys",
"value": "{{overviewKeys}}"
},
{
"key": "queueoption",
"value": "{{queueOption}}"
},
{
"key": "queues",
"value": "{{queues}}"
}
]
}
}
},
{
"name": "getTicketOverviewCounts role",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"const overviewCountsRoleJson = pm.response.json();",
"const overviewCountsRole = overviewCountsRoleJson.counts || overviewCountsRoleJson.Counts || {};",
"const overviewPreferredKeysRole = (pm.collectionVariables.get(\"overviewKeys\") || \"\")",
" .split(\",\")",
" .map(key => key.trim())",
" .filter(Boolean);",
"const overviewRelationKeyRole = overviewPreferredKeysRole.find(key => Number(overviewCountsRole[key] || 0) > 0)",
" || Object.keys(overviewCountsRole).find(key => Number(overviewCountsRole[key] || 0) > 0)",
" || overviewPreferredKeysRole[0]",
" || Object.keys(overviewCountsRole)[0]",
" || \"\";",
"const overviewRelationCountRole = overviewRelationKeyRole ? Number(overviewCountsRole[overviewRelationKeyRole] || 0) : 0;",
"",
"pm.collectionVariables.set(\"scope\", \"role\");",
"pm.collectionVariables.set(\"overviewKey\", overviewRelationKeyRole);",
"pm.collectionVariables.set(\"overviewRelationExpectedCount\", String(overviewRelationCountRole));",
"",
"pm.test(\"Captured role overview relation parameters\", function () {",
" pm.expect(overviewCountsRole).to.be.an(\"object\");",
" pm.expect(pm.collectionVariables.get(\"scope\")).to.equal(\"role\");",
" pm.expect(pm.collectionVariables.get(\"overviewKey\")).to.be.a(\"string\").and.not.empty;",
" pm.expect(Number(pm.collectionVariables.get(\"overviewRelationExpectedCount\"))).to.be.at.least(0);",
"});"
]
}
}
],
"request": {
"method": "GET",
"header": [
{
"key": "Accept",
"value": "application/json"
}
],
"url": {
"raw": "{{baseUrl}}/api/c4itf4sdwebapi/getTicketOverviewCounts?sid={{sid}}&scope=role&keys={{overviewKeys}}&queueoption={{queueOption}}&queues={{queues}}",
"host": [
"{{baseUrl}}"
],
"path": [
"api",
"c4itf4sdwebapi",
"getTicketOverviewCounts"
],
"query": [
{
"key": "sid",
"value": "{{sid}}"
},
{
"key": "scope",
"value": "role"
},
{
"key": "keys",
"value": "{{overviewKeys}}"
},
{
"key": "queueoption",
"value": "{{queueOption}}"
},
{
"key": "queues",
"value": "{{queues}}"
}
]
}
}
},
{
"name": "getTicketOverviewCountsByRoles",
"request": {
"method": "POST",
"header": [
{
"key": "Accept",
"value": "application/json"
},
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\r\n \"Sid\": \"{{sid}}\",\r\n \"RoleGuids\": [\r\n \"{{roleGuid}}\"\r\n ],\r\n \"Keys\": [\r\n \"open\",\r\n \"overdue\"\r\n ],\r\n \"QueueOption\": {{queueOption}},\r\n \"Queues\": \"{{queues}}\"\r\n}"
},
"url": {
"raw": "{{baseUrl}}/api/c4itf4sdwebapi/getTicketOverviewCountsByRoles",
"host": [
"{{baseUrl}}"
],
"path": [
"api",
"c4itf4sdwebapi",
"getTicketOverviewCountsByRoles"
]
}
}
},
{
"name": "getTicketOverviewRelations",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"const overviewRelations = pm.response.text() ? pm.response.json() : [];",
"const expectedOverviewRelationCount = Number(pm.collectionVariables.get(\"overviewRelationExpectedCount\") || 0);",
"",
"pm.test(\"Overview relations count matches captured overview count\", function () {",
" pm.expect(Array.isArray(overviewRelations)).to.equal(true);",
" pm.expect(overviewRelations.length).to.equal(expectedOverviewRelationCount);",
"});"
]
}
}
],
"request": {
"method": "GET",
"header": [
{
"key": "Accept",
"value": "application/json"
}
],
"url": {
"raw": "{{baseUrl}}/api/c4itf4sdwebapi/getTicketOverviewRelations?sid={{sid}}&scope={{scope}}&key={{overviewKey}}&count={{overviewRelationExpectedCount}}&queueoption={{queueOption}}&queues={{queues}}",
"host": [
"{{baseUrl}}"
],
"path": [
"api",
"c4itf4sdwebapi",
"getTicketOverviewRelations"
],
"query": [
{
"key": "sid",
"value": "{{sid}}"
},
{
"key": "scope",
"value": "{{scope}}"
},
{
"key": "key",
"value": "{{overviewKey}}"
},
{
"key": "count",
"value": "{{overviewRelationExpectedCount}}"
},
{
"key": "queueoption",
"value": "{{queueOption}}"
},
{
"key": "queues",
"value": "{{queues}}"
}
]
}
}
}
]
},
{
"name": "04 Pickups and roles",
"item": [
{
"name": "getPickup by name",
"request": {
"method": "GET",
"header": [
{
"key": "Accept",
"value": "application/json"
}
],
"url": {
"raw": "{{baseUrl}}/api/c4itf4sdwebapi/getPickup/{{pickupName}}?mode={{pickupMode}}&group={{pickupGroup}}",
"host": [
"{{baseUrl}}"
],
"path": [
"api",
"c4itf4sdwebapi",
"getPickup",
"{{pickupName}}"
],
"query": [
{
"key": "mode",
"value": "{{pickupMode}}"
},
{
"key": "group",
"value": "{{pickupGroup}}"
}
]
}
}
},
{
"name": "getMyRoleMemberships current user",
"request": {
"method": "GET",
"header": [
{
"key": "Accept",
"value": "application/json"
}
],
"url": {
"raw": "{{baseUrl}}/api/c4itf4sdwebapi/getMyRoleMemberships",
"host": [
"{{baseUrl}}"
],
"path": [
"api",
"c4itf4sdwebapi",
"getMyRoleMemberships"
]
}
}
},
{
"name": "getRoleMemberships by SID",
"request": {
"method": "GET",
"header": [
{
"key": "Accept",
"value": "application/json"
}
],
"url": {
"raw": "{{baseUrl}}/api/c4itf4sdwebapi/getRoleMemberships?sid={{sid}}",
"host": [
"{{baseUrl}}"
],
"path": [
"api",
"c4itf4sdwebapi",
"getRoleMemberships"
],
"query": [
{
"key": "sid",
"value": "{{sid}}"
}
]
}
}
},
{
"name": "getRoleMemberships by UPN",
"request": {
"method": "GET",
"header": [
{
"key": "Accept",
"value": "application/json"
}
],
"url": {
"raw": "{{baseUrl}}/api/c4itf4sdwebapi/getRoleMemberships?upn={{upn}}",
"host": [
"{{baseUrl}}"
],
"path": [
"api",
"c4itf4sdwebapi",
"getRoleMemberships"
],
"query": [
{
"key": "upn",
"value": "{{upn}}"
}
]
}
}
},
{
"name": "getRoleMemberships by user id",
"request": {
"method": "GET",
"header": [
{
"key": "Accept",
"value": "application/json"
}
],
"url": {
"raw": "{{baseUrl}}/api/c4itf4sdwebapi/getRoleMemberships?id={{userId}}",
"host": [
"{{baseUrl}}"
],
"path": [
"api",
"c4itf4sdwebapi",
"getRoleMemberships"
],
"query": [
{
"key": "id",
"value": "{{userId}}"
}
]
}
}
}
]
}
]
}