{"id":20431682,"url":"https://github.com/skylinecommunications/slc-s-example_interappcalls","last_synced_at":"2026-05-26T23:04:13.293Z","repository":{"id":222821313,"uuid":"757372718","full_name":"SkylineCommunications/SLC-S-Example_InterAppCalls","owner":"SkylineCommunications","description":"Example solution on how to create an InterApp nuget package using the Skyline.DataMiner.Core.InterApp library.","archived":false,"fork":false,"pushed_at":"2025-12-29T17:11:54.000Z","size":54,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-01-01T22:16:06.739Z","etag":null,"topics":["dataminer","dataminer-solution","example"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/SkylineCommunications.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-02-14T11:10:36.000Z","updated_at":"2025-12-29T17:11:58.000Z","dependencies_parsed_at":"2024-05-29T09:42:33.251Z","dependency_job_id":"4e092ad3-924c-482e-b087-f036f30ca93a","html_url":"https://github.com/SkylineCommunications/SLC-S-Example_InterAppCalls","commit_stats":null,"previous_names":["skylinecommunications/slc-s-example_interappcalls"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/SkylineCommunications/SLC-S-Example_InterAppCalls","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SkylineCommunications%2FSLC-S-Example_InterAppCalls","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SkylineCommunications%2FSLC-S-Example_InterAppCalls/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SkylineCommunications%2FSLC-S-Example_InterAppCalls/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SkylineCommunications%2FSLC-S-Example_InterAppCalls/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/SkylineCommunications","download_url":"https://codeload.github.com/SkylineCommunications/SLC-S-Example_InterAppCalls/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SkylineCommunications%2FSLC-S-Example_InterAppCalls/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33542350,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"ssl_error","status_checked_at":"2026-05-26T15:22:15.568Z","response_time":63,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dataminer","dataminer-solution","example"],"created_at":"2024-11-15T08:12:37.139Z","updated_at":"2026-05-26T23:04:13.268Z","avatar_url":"https://github.com/SkylineCommunications.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Skyline.DataMiner.ConnectorAPI.SkylineCommunications.ExampleConnectorInterAppCalls\n\nThe ConnectorAPI Example NuGet package demonstrates best practices for creating a connector API. This package provides a robust framework of classes designed to facilitate interaction with various connectors, serving as a template for developers looking to implement their own connector APIs efficiently and effectively.\n\n## Considerations\n- **Best Practices**: When building a NuGet package, it's best practice to avoid exposing any classes from external libraries, such as the InterApp Library. This prevents potential versioning issues. In this example package, no public methods or properties use arguments or return types from the InterApp Library to ensure compatibility and stability.\n- **Error Handling**: When building a ConnectorAPI, it's important to carefully consider error handling. In this example, responses should inherit from the IExampleResponse interface, which includes two properties: a boolean Success and a string Description. These properties can be used to provide meaningful error messages when something goes wrong.\n- **Documentation**: Thoroughly documented classes and methods to aid developers in understanding and utilizing the package effectively.\n\n## Creating your own ConnectorAPI\n\n1. To avoid dependency hell issues, instead of all our messages inheriting from the **Message** type. We create some custom interfaces to help the user experience and avoid the dependency issues. In this SDF we created 3 interfaces:\nYou can rename these interfaces occording the your own ConnectorAPI.\n\n\tFor Example **IMyConnectorMessage**, **IMyConnectorRequest**, **IMyConnectorResponse**.\n\t- IExampleInterAppMessage\n\n\t```csharp\n\t/// \u003csummary\u003e\n\t/// Represents an InterApp Message that a Skyline Communications Example InterApp Calls element can receive.\n\t/// \u003c/summary\u003e\n\tpublic interface IExampleInterAppMessage\n\t{\n\t}\n\t```\n\n\t- IExampleRequest\n\n\t```csharp\n\t/// \u003csummary\u003e\n\t/// Base class that hold default properties that every request has.\n\t/// \u003c/summary\u003e\n\tpublic interface IExampleRequest : IExampleInterAppMessage\n\t{\n\t}\n\t```\n\n\t- IExampleResponse\n\n\t```csharp\n\t/// \u003csummary\u003e\n\t/// Base class that hold default properties that every response has.\n\t/// \u003c/summary\u003e\n\tpublic interface IExampleResponse : IExampleInterAppMessage\n\t{\n\t\t/// \u003csummary\u003e\n\t\t/// Indicates if the InterApp Call was successful or not\n\t\t/// \u003c/summary\u003e\n\t\tbool Success { get; set; }\n\n\t\t/// \u003csummary\u003e\n\t\t/// A human readable text representing the response of the InterApp Call.\n\t\t/// \u003c/summary\u003e\n\t\tstring Description { get; set; }\n\n\t\t/// \u003csummary\u003e\n\t\t/// The InterApp Message that triggered this response.\n\t\t/// \u003c/summary\u003e\n\t\tIExampleRequest Request { get; set; }\n\t}\n\t```\n\n\tThese interface will be the ones we expose in the NuGet. This means no dependency hell issues.\n\n1. The second step to sending InterApp messages is to create an object of Type **Message**, which is a Type from the InterApp library. In the example we created a Generic class that to avoid having all that all our message classes need to inherit from **Message**. This way we only have to do it once.\nYou can copy and paste this exact code, and don't forget to rename the **IExampleInterAppMessage** to the one you created in step 1.\n\n\t```csharp\n\t/// \u003csummary\u003e\n\t/// Represents a generic inter-application message that contains data of type \u003ctypeparamref name=\"T\"/\u003e.\n\t/// \u003c/summary\u003e\n\t/// \u003ctypeparam name=\"T\"\u003eThe type of the data contained in the message, which must implement \u003csee cref=\"IExampleInterAppMessage\"/\u003e.\u003c/typeparam\u003e\n\tpublic class GenericInterAppMessage\u003cT\u003e : Message\n\t\twhere T : IExampleInterAppMessage\n\t{\n\t\t/// \u003csummary\u003e\n\t\t/// Initializes a new instance of the \u003csee cref=\"GenericInterAppMessage{T}\"/\u003e class with the specified data.\n\t\t/// \u003c/summary\u003e\n\t\t/// \u003cparam name=\"data\"\u003eThe data contained in the message.\u003c/param\u003e\n\t\tpublic GenericInterAppMessage(T data)\n\t\t{\n\t\t\tData = data;\n\t\t}\n\n\t\t/// \u003csummary\u003e\n\t\t/// Gets the data contained in the message.\n\t\t/// \u003c/summary\u003e\n\t\tpublic T Data { get; }\n\t}\n\t```\n\n1. Now it's time to define all the messages, you need the connector to support. Create a class for each InterApp request and implement the request interface you created in step 1. Do the same thing for all the responses and implement the response interface from step 1.\n\t\n\tTake for example the **SimpleCreateExampleRow** request and it's corresponding response **SimpleCreateExampleRowResult**.\n\t```csharp\n\t/// \u003csummary\u003e\n\t/// InterApp Message that will execute the simple example flow.\n\t/// \u003c/summary\u003e\n\tpublic class SimpleCreateExampleRow : IExampleRequest\n\t{\n\t\t/// \u003csummary\u003e\n\t\t/// The data needed to execute the simple example flow.\n\t\t/// \u003c/summary\u003e\n\t\tpublic MyTableData ExampleData { get; set; }\n\t}\n\n\t/// \u003csummary\u003e\n\t/// InterApp Message that represent the response from the simple example flow.\n\t/// \u003c/summary\u003e\n\tpublic class SimpleCreateExampleRowResult : IExampleResponse\n\t{\n\t\t/// \u003csummary\u003e\n\t\t/// Indicates if the InterApp Call was successful or not\n\t\t/// \u003c/summary\u003e\n\t\tpublic bool Success { get; set; }\n\n\t\t/// \u003csummary\u003e\n\t\t/// A human readable text representing the response of the InterApp Call.\n\t\t/// \u003c/summary\u003e\n\t\tpublic string Description { get; set; }\n\n\t\t/// \u003csummary\u003e\n\t\t/// The InterApp Message that triggered this response.\n\t\t/// \u003c/summary\u003e\n\t\tpublic IExampleRequest Request { get; set; }\n\n\t\t/// \u003csummary\u003e\n\t\t/// The primary key of the row that will be created.\n\t\t/// \u003c/summary\u003e\n\t\tpublic string RowKey { get; set; }\n\t}\n\t```\n\n1. In order to safely be able to serialize/deserialize these object, we'll need to create a white-list of all the types the InterApp serializer can allow. This list needs to be a list of all the **Message** types. You could be wondering, but our messages don't inherit from the **Message** class and you are correct. Therefore we wrap the types in the generic type we created in step 2. The result should be a list of Message types. In this SDF the list looks like this:\n\t```csharp\n\t/// \u003csummary\u003e\n\t/// Gets a list of all the supported InterApp Message Types.\n\t/// \u003c/summary\u003e\n\tpublic static List\u003cType\u003e KnownTypes { get; } = new List\u003cType\u003e\n\t{\n\t\t// Example Messages\n\t\ttypeof(GenericInterAppMessage\u003cSimpleCreateExampleRow\u003e),\n\t\ttypeof(GenericInterAppMessage\u003cSimpleCreateExampleRowResult\u003e),\n\t\ttypeof(GenericInterAppMessage\u003cAdvancedCreateExampleRow\u003e),\n\t\ttypeof(GenericInterAppMessage\u003cAdvancedCreateExampleRowResult\u003e),\n\t\ttypeof(GenericInterAppMessage\u003cDelayedCreateExampleRow\u003e),\n\t\ttypeof(GenericInterAppMessage\u003cDelayedCreateExampleRowResult\u003e),\n\t};\n\t```\n\n1. Now we need a way to translate our exposed messages to an actual **Message** object that the InterApp library understands and the other way around. Therefore we need to add 2 internal methods called **ToMessage** **FromMessage**. Which will translate to and from a **Message** object. In the SDF these look like this and can also be found in the static class Types :\n\n\t```csharp\n\t/// \u003csummary\u003e\n\t/// Converts an \u003csee cref=\"IExampleRequest\"/\u003e message to a \u003csee cref=\"Message\"/\u003e object.\n\t/// \u003c/summary\u003e\n\t/// \u003cparam name=\"message\"\u003eThe \u003csee cref=\"IExampleRequest\"/\u003e message to be converted.\u003c/param\u003e\n\t/// \u003creturns\u003e\n\t/// A \u003csee cref=\"Message\"/\u003e object that represents the specified \u003csee cref=\"IExampleRequest\"/\u003e message.\n\t/// \u003c/returns\u003e\n\t/// \u003cexception cref=\"InvalidOperationException\"\u003eThrown when the message type is unknown.\u003c/exception\u003e\n\tinternal static Message ToMessage(IExampleRequest message)\n\t{\n\t\tswitch (message)\n\t\t{\n\t\t\tcase SimpleCreateExampleRow simpleCreateExampleRow:\n\t\t\t\treturn new GenericInterAppMessage\u003cSimpleCreateExampleRow\u003e(simpleCreateExampleRow);\n\n\t\t\tcase AdvancedCreateExampleRow advancedCreateExampleRow:\n\t\t\t\treturn new GenericInterAppMessage\u003cAdvancedCreateExampleRow\u003e(advancedCreateExampleRow);\n\n\t\t\tcase DelayedCreateExampleRow delayedCreateExampleRow:\n\t\t\t\treturn new GenericInterAppMessage\u003cDelayedCreateExampleRow\u003e(delayedCreateExampleRow);\n\n\t\t\tdefault:\n\t\t\t\tthrow new InvalidOperationException(\"Unknown message type\");\n\t\t}\n\t}\n\t```\n\n\t```csharp\n\t/// \u003csummary\u003e\n\t/// Converts a \u003csee cref=\"Message\"/\u003e object to an \u003csee cref=\"IExampleResponse\"/\u003e.\n\t/// \u003c/summary\u003e\n\t/// \u003cparam name=\"message\"\u003eThe \u003csee cref=\"Message\"/\u003e to be converted.\u003c/param\u003e\n\t/// \u003creturns\u003e\n\t/// An \u003csee cref=\"IExampleResponse\"/\u003e object that represents the data from the specified \u003csee cref=\"Message\"/\u003e.\n\t/// \u003c/returns\u003e\n\t/// \u003cexception cref=\"InvalidOperationException\"\u003eThrown when the message type is unknown.\u003c/exception\u003e\n\tinternal static IExampleResponse FromMessage(Message message)\n\t{\n\t\tswitch (message)\n\t\t{\n\t\t\tcase GenericInterAppMessage\u003cSimpleCreateExampleRowResult\u003e simpleCreateExampleRowResult:\n\t\t\t\treturn simpleCreateExampleRowResult.Data;\n\n\t\t\tcase GenericInterAppMessage\u003cAdvancedCreateExampleRowResult\u003e advancedCreateExampleRowResult:\n\t\t\t\treturn advancedCreateExampleRowResult.Data;\n\n\t\t\tcase GenericInterAppMessage\u003cDelayedCreateExampleRowResult\u003e delayedCreateExampleRowResult:\n\t\t\t\treturn delayedCreateExampleRowResult.Data;\n\n\t\t\tdefault:\n\t\t\t\tthrow new InvalidOperationException(\"Unknown message type\");\n\t\t}\n\t}\n\t```\n\n1. To avoid scripts and connectors having a magic number with the parameter ids of the receiver/responder parameters. We will create a constant class that hold them. That way it's easier to manage if it would ever change. In the SDF we also included a constant with the protocol name, to avoid people sending messages to a wrong element. The class then looks like this.\n\t```csharp\n\t/// \u003csummary\u003e\n\t/// Contains constant values used in the ConnectorAPI.\n\t/// \u003c/summary\u003e\n\tpublic static class Constants\n\t{\n\t\t/// \u003csummary\u003e\n\t\t/// The protocol name of the Skyline Communications Example Connector InterApp Calls.\n\t\t/// \u003c/summary\u003e\n\t\tpublic const string ProtocolName = \"Skyline Communications Example InterApp Calls\";\n\n\t\t/// \u003csummary\u003e\n\t\t/// The ID of the parameter that will receive the InterApp Messages\n\t\t/// \u003c/summary\u003e\n\t\tpublic const int InterAppReceiverPID = 9000000;\n\n\t\t/// \u003csummary\u003e\n\t\t/// The ID of the parameter that will hold the responses for the InterApp Messages\n\t\t/// \u003c/summary\u003e\n\t\tpublic const int InterAppResponsePID = 9000001;\n\t}\n\t```\n\n1. We can then write a wrapper around the InterApp to have a better user experience. The wrapper will have method to send and receive messages, do checks to avoid wrong messages, have default timeout values and hide away the InterApp communication. This class is already very generic you could copy and paste this and change out the interfaces with your own and should be all set.\nYou can find the class in the root of the project, called **ExampleInterAppCalls**. Ofcourse you should also rename the class to something like **MyConnector**, or something else that indicates what the class is about.\n\n1. Now you are set and can start to implement your NuGet in the connector. See the Connector Example on how to implement this. [SLC-C-Example_InterAppCalls](https://github.com/SkylineCommunications/SLC-C-Example_InterAppCalls)\n\n\n\nFor more documentation on InterApp see the [InterApp DataMiner Docs](https://docs.dataminer.services/develop/devguide/ClassLibrary/ClassLibraryInterAppClasses.html?q=InterApp#creating-an-api).\n\n## Getting Started\nHere's a quick guide to help you get started with the ConnectorAPI Example NuGet package:\n\n\nCreate an ExampleInterAppCalls object to get started.\n```csharp\n// For Automation Scripts\nvar exampleElement = new ExampleInterAppCalls(engine.GetUserConnection(), agentId, elementId);\n\n// For Connectors\nvar exampleElement = new ExampleInterAppCalls(protocol.SLNet.RawConnection, agentId, elementId);\n```\n\n\nCreate the message you need to send, for example the '*SimpleCreateExampleRow*'.\n```csharp\nvar simpleRequest = new SimpleCreateExampleRow\n{\n\tExampleData = new MyTableData\n\t{\n\t\tMyDiscreetColumn = DiscreetColumnOption.Discreet2,\n\t\tMyStringColumn = \"Hello World!\",\n\t\tMyNumericColumn = 1_000_000,\n\t},\n};\n```\n\nSend you message to the element.\n```csharp\nvar response = exampleElement.SendSingleResponseMessage(simpleRequest);\n```\n\n\n## About\n\nAn Example Connector API (Inter-App Calls/Messages) for DataMiner elements running the 'Skyline Example Connector InterApp Calls' connector.\n\n### About DataMiner\n\nDataMiner is a transformational platform that provides vendor-independent control and monitoring of devices and services. Out of the box and by design, it addresses key challenges such as security, complexity, multi-cloud, and much more. It has a pronounced open architecture and powerful capabilities enabling users to evolve easily and continuously.\n\nThe foundation of DataMiner is its powerful and versatile data acquisition and control layer. With DataMiner, there are no restrictions to what data users can access. Data sources may reside on premises, in the cloud, or in a hybrid setup.\n\nA unique catalog of 7000+ connectors already exist. In addition, you can leverage DataMiner Development Packages to build you own connectors (also known as \"protocols\" or \"drivers\").\n\n\u003e **Note**\n\u003e See also: [About DataMiner](https://aka.dataminer.services/about-dataminer).\n\n### About Skyline Communications\n\nAt Skyline Communications, we deal in world-class solutions that are deployed by leading companies around the globe. Check out [our proven track record](https://aka.dataminer.services/about-skyline) and see how we make our customers' lives easier by empowering them to take their operations to the next level.\n\n\u003c!-- Uncomment below and add more info to provide more information about how to use this package. --\u003e\n\u003c!-- ## Getting Started --\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskylinecommunications%2Fslc-s-example_interappcalls","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fskylinecommunications%2Fslc-s-example_interappcalls","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskylinecommunications%2Fslc-s-example_interappcalls/lists"}