Old SDK removed
New dotnet SDK added - Release
diff --git a/sdks/dotnet/basyx-core/BaSyx.Utils/AssemblyHandling/AssemblyUtils.cs b/sdks/dotnet/basyx-core/BaSyx.Utils/AssemblyHandling/AssemblyUtils.cs
new file mode 100644
index 0000000..33f30f2
--- /dev/null
+++ b/sdks/dotnet/basyx-core/BaSyx.Utils/AssemblyHandling/AssemblyUtils.cs
@@ -0,0 +1,67 @@
+/*******************************************************************************
+* Copyright (c) 2020 Robert Bosch GmbH
+* Author: Constantin Ziesche (constantin.ziesche@bosch.com)
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License 2.0 which is available at
+* http://www.eclipse.org/legal/epl-2.0
+*
+* SPDX-License-Identifier: EPL-2.0
+*******************************************************************************/
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+
+namespace BaSyx.Utils.AssemblyHandling
+{
+    public static class AssemblyUtils
+    {
+        private class AssemblyNameComparer : EqualityComparer<AssemblyName>
+        {
+            public override bool Equals(AssemblyName x, AssemblyName y)
+            {
+                if (x.FullName == y.FullName)
+                    return true;
+                else
+                    return false;
+            }
+
+            public override int GetHashCode(AssemblyName obj)
+            {
+                unchecked
+                {
+                    var result = 0;
+                    result = (result * 397) ^ obj.FullName.GetHashCode();
+                    return result;
+                }
+            }
+        }
+        /// <summary>
+        /// Returns all loaded or referenced assemblies within the current application domain. Microsoft or system assemblies are excluded.
+        /// </summary>
+        /// <returns></returns>
+        public static List<Assembly> GetLoadedAssemblies()
+        {
+            List<Assembly> assemblies = AppDomain.CurrentDomain.GetAssemblies()
+                    .Where(a => !a.FullName.StartsWith("Microsoft") && !a.FullName.StartsWith("System"))
+                    .ToList();
+            List<AssemblyName> assemblyNames = new List<AssemblyName>();
+            foreach (var assembly in assemblies)
+            {
+                List<AssemblyName> referencedAssemblyNames = assembly.GetReferencedAssemblies().ToList();
+                assemblyNames.AddRange(referencedAssemblyNames);
+            }
+            assemblyNames = assemblyNames
+                .Distinct(new AssemblyNameComparer())
+                .Where(a => !a.FullName.StartsWith("Microsoft") && !a.FullName.StartsWith("System"))?
+                .ToList();
+
+            List<Assembly> referencedAssemblies = assemblyNames.ConvertAll(c => Assembly.Load(c));
+            assemblies.AddRange(referencedAssemblies);
+
+            return assemblies;
+        }
+    }
+}
diff --git a/sdks/dotnet/basyx-core/BaSyx.Utils/BaSyx.Utils.csproj b/sdks/dotnet/basyx-core/BaSyx.Utils/BaSyx.Utils.csproj
new file mode 100644
index 0000000..dd8b905
--- /dev/null
+++ b/sdks/dotnet/basyx-core/BaSyx.Utils/BaSyx.Utils.csproj
@@ -0,0 +1,45 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <TargetFramework>netstandard2.0</TargetFramework>
+    <Configurations>Debug;Release</Configurations>
+    <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
+    <Authors>Constantin Ziesche</Authors>
+    <Copyright>Copyright 2019 - Robert Bosch GmbH</Copyright>
+    <PackageProjectUrl>https://wiki.eclipse.org/BaSyx</PackageProjectUrl>
+    <RepositoryUrl>https://git.eclipse.org/r/plugins/gitiles/basyx/basyx/+/master/sdks/csnet/</RepositoryUrl>
+    <PackageLicenseUrl></PackageLicenseUrl>
+    <Description>The official BaSyx Collection of Utility Functions for building a BaSys Environment</Description>
+    <Company>Robert Bosch GmbH</Company>
+    <PackageTags>BaSys BaSyx Utils Utilities</PackageTags>
+    <PackageLicenseExpression>EPL-2.0</PackageLicenseExpression>
+    <RunPostBuildEvent>OnOutputUpdated</RunPostBuildEvent>
+    <PackageIcon>basyxlogo.png</PackageIcon>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <None Include="basyxlogo.png" Pack="true" PackagePath="\" />
+  </ItemGroup>
+  
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+   <DebugType>full</DebugType>
+  </PropertyGroup>
+  
+  <ItemGroup>
+    <PackageReference Include="M2MqttDotnetCore" Version="1.0.8" />
+    <PackageReference Include="Microsoft.AspNetCore.Mvc.Abstractions" Version="2.2.0" />
+    <PackageReference Include="Microsoft.AspNetCore.Mvc.Formatters.Json" Version="2.2.0" />
+    <PackageReference Include="Microsoft.AspNetCore.Rewrite" Version="2.2.0" />
+    <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="3.1.0" />
+    <PackageReference Include="Microsoft.Extensions.Options" Version="3.1.0" />
+    <PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
+    <PackageReference Include="NLog" Version="4.6.8" />
+    <PackageReference Include="NLog.Web.AspNetCore" Version="4.9.0" />
+    <PackageReference Include="XSerializer" Version="0.4.2" />
+  </ItemGroup>
+  
+  <Target Name="PostBuild" AfterTargets="PostBuildEvent">
+    <Exec Command="IF EXIST %25BASYX_REPO%25 ( dotnet pack &quot;$(ProjectPath)&quot; --no-build --include-source --include-symbols --output &quot;%25BASYX_REPO%25&quot; ) ELSE ( ECHO BASYX_REPO Environment Variable not found)" />
+  </Target>
+
+</Project>
diff --git a/sdks/dotnet/basyx-core/BaSyx.Utils/Client/Http/LegacyHttpClient.cs b/sdks/dotnet/basyx-core/BaSyx.Utils/Client/Http/LegacyHttpClient.cs
new file mode 100644
index 0000000..f4bfd38
--- /dev/null
+++ b/sdks/dotnet/basyx-core/BaSyx.Utils/Client/Http/LegacyHttpClient.cs
@@ -0,0 +1,69 @@
+/*******************************************************************************
+* Copyright (c) 2020 Robert Bosch GmbH
+* Author: Constantin Ziesche (constantin.ziesche@bosch.com)
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License 2.0 which is available at
+* http://www.eclipse.org/legal/epl-2.0
+*
+* SPDX-License-Identifier: EPL-2.0
+*******************************************************************************/
+using Newtonsoft.Json;
+using System;
+using System.Net;
+using System.Text;
+
+namespace BaSyx.Utils.Client.Http
+{
+    public class LegacyHttpClient
+    {
+        private static readonly JsonSerializerSettings jsonSerializerSettings;
+
+        static LegacyHttpClient()
+        {
+            jsonSerializerSettings = new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore, Formatting = Formatting.Indented };
+        }
+
+        public HttpWebRequest CreateRequest(Uri uri, string method, object content)
+        {
+            var request = WebRequest.CreateHttp(uri);
+            request.Method = method;
+            request.Accept = "application/json";
+
+            if (content != null)
+            {
+                string body = JsonConvert.SerializeObject(content, jsonSerializerSettings);
+                if (!string.IsNullOrEmpty(body))
+                {
+                    var payload = Encoding.ASCII.GetBytes(body);
+                    request.ContentType = "application/json";
+                    request.ContentLength = payload.Length;
+
+                    using (var stream = request.GetRequestStream())
+                    {
+                        stream.Write(payload, 0, payload.Length);
+                    }
+                }
+            }
+            return request;
+        }
+
+        private HttpWebResponse SendRequest(HttpWebRequest request)
+        {
+            try
+            {
+                var response = (HttpWebResponse)request.GetResponse();
+                return response;
+            }
+            catch (Exception e)
+            {
+                Console.Out.WriteLine(e.Message);
+                if (e is WebException)
+                    return (HttpWebResponse)((WebException)e).Response;
+                else if (e.InnerException != null && e.InnerException is WebException)
+                    return (HttpWebResponse)((WebException)e.InnerException).Response;
+                return null;
+            }
+        }
+    }
+}
diff --git a/sdks/dotnet/basyx-core/BaSyx.Utils/Client/Http/SimpleHttpClient.cs b/sdks/dotnet/basyx-core/BaSyx.Utils/Client/Http/SimpleHttpClient.cs
new file mode 100644
index 0000000..d52d1a9
--- /dev/null
+++ b/sdks/dotnet/basyx-core/BaSyx.Utils/Client/Http/SimpleHttpClient.cs
@@ -0,0 +1,193 @@
+/*******************************************************************************
+* Copyright (c) 2020 Robert Bosch GmbH
+* Author: Constantin Ziesche (constantin.ziesche@bosch.com)
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License 2.0 which is available at
+* http://www.eclipse.org/legal/epl-2.0
+*
+* SPDX-License-Identifier: EPL-2.0
+*******************************************************************************/
+using BaSyx.Utils.ResultHandling;
+using BaSyx.Utils.Settings.Sections;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using System;
+using System.Collections.Generic;
+using System.Net;
+using System.Net.Http;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace BaSyx.Utils.Client.Http
+{
+    public abstract class SimpleHttpClient
+    {
+        public HttpClient HttpClient { get; }
+        public HttpClientHandler HttpClientHandler { get; }
+        public JsonSerializerSettings JsonSerializerSettings { get; protected set; }
+
+        protected SimpleHttpClient()
+        {
+            HttpClientHandler = new HttpClientHandler() { MaxConnectionsPerServer = 100, UseProxy = false };
+            HttpClient = new HttpClient(HttpClientHandler);
+
+            JsonSerializerSettings = new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore, Formatting = Formatting.Indented, DefaultValueHandling = DefaultValueHandling.Include };
+        }
+
+        protected virtual void LoadProxy(ProxyConfiguration proxyConfiguration)
+        {
+            if (proxyConfiguration == null)
+                return;
+
+            if (proxyConfiguration.UseProxy && !string.IsNullOrEmpty(proxyConfiguration.ProxyAddress))
+            {
+                HttpClientHandler.UseProxy = true;
+                if (!string.IsNullOrEmpty(proxyConfiguration.UserName) && !string.IsNullOrEmpty(proxyConfiguration.Password))
+                {
+                    NetworkCredential credential;
+                    if (!string.IsNullOrEmpty(proxyConfiguration.Domain))
+                        credential = new NetworkCredential(proxyConfiguration.UserName, proxyConfiguration.Password, proxyConfiguration.Domain);
+                    else
+                        credential = new NetworkCredential(proxyConfiguration.UserName, proxyConfiguration.Password);
+
+                    HttpClientHandler.Proxy = new WebProxy(proxyConfiguration.ProxyAddress, false, null, credential);
+                }
+                else
+                    HttpClientHandler.Proxy = new WebProxy(proxyConfiguration.ProxyAddress);
+            }
+            else
+                HttpClientHandler.UseProxy = false;
+        }
+
+        protected virtual IResult<HttpResponseMessage> SendRequest(HttpRequestMessage message, int timeout)
+        {
+            try
+            {
+                var task = HttpClient.SendAsync(message);
+                if (Task.WhenAny(task, Task.Delay(timeout)).Result == task)
+                {
+                    return new Result<HttpResponseMessage>(true, task.Result);
+                }
+                else
+                {
+                    return new Result<HttpResponseMessage>(false, new List<IMessage> { new Message(MessageType.Error, "Error while sending the request: timeout") });
+                }
+            }
+            catch (Exception e)
+            {
+                return new Result<HttpResponseMessage>(e);
+            }
+        }
+
+        protected virtual HttpRequestMessage CreateRequest(Uri uri, HttpMethod method)
+        {
+            return new HttpRequestMessage(method, uri);
+        }
+
+        protected virtual HttpRequestMessage CreateRequest(Uri uri, HttpMethod method, HttpContent content)
+        {           
+            var message = CreateRequest(uri, method);
+            if (content != null)
+                message.Content = content;
+
+            return message;
+        }
+        
+        protected virtual HttpRequestMessage CreateJsonContentRequest(Uri uri, HttpMethod method, object content)
+        {
+            var message = CreateRequest(uri, method, () => 
+            {
+                var serialized = JsonConvert.SerializeObject(content, JsonSerializerSettings);
+                return new StringContent(serialized, Encoding.UTF8, "application/json");
+            });
+            return message;
+        }
+        
+        protected virtual HttpRequestMessage CreateRequest(Uri uri, HttpMethod method, Func<HttpContent> content)
+        {
+            var message = CreateRequest(uri, method);
+            if (content != null)
+                message.Content = content.Invoke();
+
+            return message;
+        }
+
+        protected virtual IResult EvaluateResponse(IResult result, HttpResponseMessage response)
+        {
+            var messageList = new List<IMessage>();
+            messageList.AddRange(result.Messages);
+
+            if (response != null)
+            {
+                var responseString = response.Content.ReadAsStringAsync().Result;
+                if (response.IsSuccessStatusCode)
+                {
+                    messageList.Add(new Message(MessageType.Information, response.ReasonPhrase, ((int)response.StatusCode).ToString()));
+                    return new Result(true, messageList);
+                }
+                else
+                {
+                    messageList.Add(new Message(MessageType.Error, response.ReasonPhrase + "| " + responseString, ((int)response.StatusCode).ToString()));
+                    return new Result(false, messageList);
+                }
+            }
+            messageList.Add(new Message(MessageType.Error, "Evaluation of response failed - Response from host is null", null));
+            return new Result(false, messageList);
+        }
+
+        protected virtual IResult<T> EvaluateResponse<T>(IResult result, HttpResponseMessage response)
+        {
+            var messageList = new List<IMessage>();
+            messageList.AddRange(result.Messages);
+
+            if (response != null)
+            {
+                var responseString = response.Content.ReadAsStringAsync().Result;
+                if (response.IsSuccessStatusCode)
+                {
+                    try
+                    {
+                        responseString = CheckAndExtractResultContruct(responseString);
+                        var requestResult = JsonConvert.DeserializeObject<T>(responseString, JsonSerializerSettings);
+
+                        messageList.Add(new Message(MessageType.Information, response.ReasonPhrase, ((int)response.StatusCode).ToString()));
+                        return new Result<T>(true, requestResult, messageList);
+                    }
+                    catch (Exception e)
+                    {
+                        messageList.Add(new Message(MessageType.Error, e.Message, e.HelpLink));
+                        return new Result<T>(false, messageList);
+                    }
+                }
+                else
+                {
+                    messageList.Add(new Message(MessageType.Error, response.ReasonPhrase + "| " + responseString, ((int)response.StatusCode).ToString()));
+                    return new Result<T>(false, messageList);
+                }
+            }
+            messageList.Add(new Message(MessageType.Error, "Evaluation of response failed - Response from host is null", null));
+            return new Result<T>(false, messageList);
+        }
+
+        private string CheckAndExtractResultContruct(string responseString)
+        {
+            if (responseString == null)
+                return null;
+
+            try
+            {
+                JToken jToken = JToken.Parse(responseString);
+                var jEntity = jToken.SelectToken("entity");
+                if (jEntity != null)
+                    return jEntity.ToString();
+                else
+                    return responseString;
+            }
+            catch
+            {
+                return responseString;
+            }
+        }
+    }
+}
diff --git a/sdks/dotnet/basyx-core/BaSyx.Utils/Client/IMessageClient.cs b/sdks/dotnet/basyx-core/BaSyx.Utils/Client/IMessageClient.cs
new file mode 100644
index 0000000..d3b73da
--- /dev/null
+++ b/sdks/dotnet/basyx-core/BaSyx.Utils/Client/IMessageClient.cs
@@ -0,0 +1,41 @@
+/*******************************************************************************
+* Copyright (c) 2020 Robert Bosch GmbH
+* Author: Constantin Ziesche (constantin.ziesche@bosch.com)
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License 2.0 which is available at
+* http://www.eclipse.org/legal/epl-2.0
+*
+* SPDX-License-Identifier: EPL-2.0
+*******************************************************************************/
+using System;
+using System.Collections.Generic;
+using System.Text;
+using BaSyx.Utils.ResultHandling;
+
+namespace BaSyx.Utils.Client
+{
+    public interface IMessageClient
+    {
+        bool IsConnected { get; }
+
+        IResult Publish(string topic, string message, Action<IMessagePublishedEventArgs> messagePublishedHandler, byte qosLevel, bool retain);
+        IResult Subscribe(string topic, Action<IMessageReceivedEventArgs> messageReceivedHandler, byte qosLevel);
+        IResult Unsubscribe(string topic);
+
+        IResult Start();
+        IResult Stop();
+    }
+    public interface IMessagePublishedEventArgs
+    {
+        bool IsPublished { get; }
+        string MessageId { get; }        
+    }
+    public interface IMessageReceivedEventArgs
+    {
+        string Message { get; }
+        string Topic { get; }
+        byte QosLevel { get; }
+    }
+
+}
diff --git a/sdks/dotnet/basyx-core/BaSyx.Utils/Client/Mqtt/MqttConfig.cs b/sdks/dotnet/basyx-core/BaSyx.Utils/Client/Mqtt/MqttConfig.cs
new file mode 100644
index 0000000..756761a
--- /dev/null
+++ b/sdks/dotnet/basyx-core/BaSyx.Utils/Client/Mqtt/MqttConfig.cs
@@ -0,0 +1,104 @@
+/*******************************************************************************
+* Copyright (c) 2020 Robert Bosch GmbH
+* Author: Constantin Ziesche (constantin.ziesche@bosch.com)
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License 2.0 which is available at
+* http://www.eclipse.org/legal/epl-2.0
+*
+* SPDX-License-Identifier: EPL-2.0
+*******************************************************************************/
+using BaSyx.Utils.Config;
+using BaSyx.Utils.Security;
+using System.Security.Cryptography.X509Certificates;
+using System.Xml.Serialization;
+
+namespace BaSyx.Utils.Client.Mqtt
+{
+    public class MqttConfig : IEventHandlerConfig
+    {
+        [XmlElement]
+        public string ClientId { get; set; }
+        [XmlElement]
+        public string BrokerEndpoint { get; set; }
+        [XmlIgnore]
+        public ICredentials Credentials { get; set; }
+        [XmlElement]
+        public bool SecureConnection { get; set; } = false;
+        [XmlElement]
+        public int PublishTimeout { get; set; } = 5000;
+        [XmlElement]
+        public int ReceiveTimeout { get; set; } = 5000;
+        [XmlIgnore]
+        public ISecurity Security { get; set; }
+        [XmlElement]
+        public MqttConnectConfig MqttConnectConfig { get; set; }
+
+        internal MqttConfig() { }
+
+        public MqttConfig(string clientId, string brokerEndpoint)
+        {
+            ClientId = clientId;
+            BrokerEndpoint = brokerEndpoint;
+            MqttConnectConfig = new MqttConnectConfig();
+        }
+        public MqttConfig(string clientId, string brokerEndpoint, MqttCredentials credentials) : this(clientId, brokerEndpoint)
+        {
+            Credentials = credentials;
+        }
+
+        public MqttConfig(string clientId, string brokerEndpoint, MqttCredentials credentials, MqttSecurity security) : this(clientId, brokerEndpoint, credentials)
+        {
+            Security = security;
+        }
+    }
+
+    public class MqttConnectConfig
+    {
+        [XmlElement]
+        public bool WillRetain { get; set; } = false;
+        [XmlElement]
+        public byte WillQosLevel { get; set; } = 0;
+        [XmlElement]
+        public bool WillFlag { get; set; } = false;
+        [XmlElement]
+        public string WillTopic { get; set; } = null;
+        [XmlElement]
+        public string WillMessage { get; set; } = null;
+        [XmlElement]
+        public bool CleanSession { get; set; } = true;
+        [XmlElement]
+        public ushort KeepAlivePeriod { get; set; } = 60;
+    }
+
+    public class MqttCredentials : ICredentials
+    {
+        public string UserName { get; set; }
+        public string Password { get; set; }
+
+        internal MqttCredentials()
+        { }
+        
+        public MqttCredentials(string userName, string password)
+        {
+            UserName = userName;
+            Password = password;
+        }
+    }
+
+    public class MqttSecurity : ISecurity
+    {
+        public X509Certificate CaCert { get; }
+        public X509Certificate ClientCert { get; }
+
+        public MqttSecurity(X509Certificate caCert)
+        {
+            CaCert = caCert;
+        }
+        public MqttSecurity(X509Certificate caCert, X509Certificate clientCert)
+        {
+            CaCert = caCert;
+            ClientCert = clientCert;
+        }
+    }
+}
diff --git a/sdks/dotnet/basyx-core/BaSyx.Utils/Client/Mqtt/SimpleMqttClient.cs b/sdks/dotnet/basyx-core/BaSyx.Utils/Client/Mqtt/SimpleMqttClient.cs
new file mode 100644
index 0000000..d7676ff
--- /dev/null
+++ b/sdks/dotnet/basyx-core/BaSyx.Utils/Client/Mqtt/SimpleMqttClient.cs
@@ -0,0 +1,229 @@
+/*******************************************************************************
+* Copyright (c) 2020 Robert Bosch GmbH
+* Author: Constantin Ziesche (constantin.ziesche@bosch.com)
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License 2.0 which is available at
+* http://www.eclipse.org/legal/epl-2.0
+*
+* SPDX-License-Identifier: EPL-2.0
+*******************************************************************************/
+using System;
+using System.Text;
+using System.Threading;
+using NLog;
+using uPLibrary.Networking.M2Mqtt;
+using uPLibrary.Networking.M2Mqtt.Messages;
+using BaSyx.Utils.ResultHandling;
+using System.Security.Cryptography.X509Certificates;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace BaSyx.Utils.Client.Mqtt
+{
+    public class SimpleMqttClient : IMessageClient
+    {
+        private MqttClient mqttClient;
+        public readonly MqttConfig MqttConfig;
+
+        private Dictionary<string, Action<IMessageReceivedEventArgs>> topicMessageReceivedHandler = new Dictionary<string, Action<IMessageReceivedEventArgs>>();
+        private Action<IMessagePublishedEventArgs> msgPublishedMethod = null;
+
+        private ManualResetEvent connectionClosedResetEvent;
+        public EventHandler<EventArgs> ConnectionClosed;
+
+        private static Logger logger = LogManager.GetCurrentClassLogger();
+
+        public SimpleMqttClient(MqttConfig config)
+        {
+            MqttConfig = config;        
+        }
+
+        public bool IsConnected
+        {
+            get
+            {
+                if (mqttClient != null)
+                    return mqttClient.IsConnected;
+                else
+                    return false;
+            }
+        }
+        public IResult Publish(string topic, string message) => Publish(topic, message, null, 2, false);
+
+        public IResult Publish(string topic, string message, Action<IMessagePublishedEventArgs> messagePublishedHandler, byte qosLevel, bool retain = false)
+        {
+            if (messagePublishedHandler != null && this.msgPublishedMethod == null)
+            {
+                msgPublishedMethod = messagePublishedHandler;
+                mqttClient.MqttMsgPublished += MqttClient_MqttMsgPublished;
+            }
+
+            byte[] bMessage = Encoding.UTF8.GetBytes(message);
+            
+            ushort messageId = mqttClient.Publish(topic, bMessage, qosLevel, retain);
+            return new Result<ushort>(true, messageId);
+        }
+
+        public IResult Subscribe(string topic, Action<IMessageReceivedEventArgs> messageReceivedHandler, byte qosLevel)
+        {
+            if (string.IsNullOrEmpty(topic))
+                return new Result(new ArgumentNullException("topic", "The topic is null or empty"));
+            if (messageReceivedHandler == null)
+                return new Result(new ArgumentNullException("messageReceivedHandler", "The message received delegate cannot be null since subscribed messages cannot be received"));
+
+            if (!topicMessageReceivedHandler.ContainsKey(topic))
+                topicMessageReceivedHandler.Add(topic, messageReceivedHandler);
+
+            ushort messageId = mqttClient.Subscribe(new string[] { topic }, new byte[] { qosLevel });
+            return new Result<ushort>(true, messageId);
+        }
+
+        public IResult Unsubscribe(string topic)
+        {
+            if (topicMessageReceivedHandler.ContainsKey(topic))
+                topicMessageReceivedHandler.Remove(topic);
+
+            ushort messageId = mqttClient.Unsubscribe(new string[] { topic });
+            return new Result<ushort>(true, messageId);
+        }
+
+        private void MqttClient_MqttMsgPublishReceived(object sender, MqttMsgPublishEventArgs e)
+        {
+            string parentOrSelfTopic = GetParentOrSelfTopic(e.Topic, topicMessageReceivedHandler.Keys);
+            if (topicMessageReceivedHandler.TryGetValue(parentOrSelfTopic, out Action<IMessageReceivedEventArgs> action))
+                action.Invoke(new MqttMsgReceivedEventArgs(e));
+        }
+
+        private string GetParentOrSelfTopic(string topic, Dictionary<string, Action<IMessageReceivedEventArgs>>.KeyCollection keys)
+        {
+            foreach (var key in keys)
+            {
+                if (key == topic)
+                    return key;
+                else
+                {
+                    string[] splittedKey = key.Split('/');
+                    string[] splittedTopic = topic.Split('/');
+                    int minLength = Math.Min(splittedKey.Length, splittedTopic.Length);
+                    for (int i = 0; i < minLength; i++)
+                    {
+                        if (splittedKey[i] != splittedTopic[i])
+                        {
+                            if (splittedKey[i] == "#")
+                                return key;
+                        }
+                    }
+
+                }
+            }
+            return topic;
+        }
+
+        private void MqttClient_MqttMsgSubscribed(object sender, MqttMsgSubscribedEventArgs e)
+        {
+            logger.Debug("Subscribed for id = " + e.MessageId);
+        }
+
+        private void MqttClient_MqttMsgPublished(object sender, uPLibrary.Networking.M2Mqtt.Messages.MqttMsgPublishedEventArgs e)
+        {
+            logger.Debug("Published for id = " + e.MessageId);
+            msgPublishedMethod?.Invoke(new MqttMsgPublishedEventArgs(e));
+        }
+
+        public IResult Start()
+        {
+            Uri endpoint = new Uri(MqttConfig.BrokerEndpoint);
+            MqttSslProtocols protocols = MqttConfig.SecureConnection ? MqttSslProtocols.TLSv1_2 : MqttSslProtocols.None;
+            X509Certificate caCert = null;
+            X509Certificate clientCert = null;
+            if (MqttConfig.Security != null && MqttConfig.Security is MqttSecurity security)
+            {
+                caCert = security.CaCert ?? null;
+                clientCert = security.ClientCert ?? null;
+            }
+            mqttClient = new MqttClient(endpoint.Host, endpoint.Port, MqttConfig.SecureConnection, caCert, clientCert, protocols, null, null);
+            mqttClient.ConnectionClosed += MqttClient_ConnectionClosed;
+            
+            try
+            {
+                byte success;
+                MqttConnectConfig config = MqttConfig.MqttConnectConfig;
+                if (MqttConfig.Credentials is MqttCredentials mqttCreds)
+                    success = mqttClient.Connect(Guid.NewGuid().ToString(), mqttCreds.UserName, mqttCreds.Password, config.WillRetain, config.WillQosLevel, config.WillFlag, config.WillTopic, config.WillMessage, config.CleanSession, config.KeepAlivePeriod);
+                else
+                    success = mqttClient.Connect(Guid.NewGuid().ToString(), null, null, config.WillRetain, config.WillQosLevel, config.WillFlag, config.WillTopic, config.WillMessage, config.CleanSession, config.KeepAlivePeriod);
+
+                if (success != 0)
+                    return new Result(false, new Message(MessageType.Error, "Could not connect to MQTT Broker", success.ToString()));
+
+                mqttClient.MqttMsgPublishReceived += MqttClient_MqttMsgPublishReceived;
+                return new Result(true);
+            }
+            catch (Exception e)
+            {
+                logger.Error(e, "Could not connect MQTT-Broker");
+                return new Result(e);
+            }
+        }
+
+        public IResult Stop()
+        {
+            if (mqttClient != null)
+            {
+                if (mqttClient.IsConnected)
+                {
+                    connectionClosedResetEvent = new ManualResetEvent(false);
+                    //mqttClient.ConnectionClosed += MqttClient_ConnectionClosed;
+                    mqttClient.MqttMsgPublishReceived -= MqttClient_MqttMsgPublishReceived;
+
+                    mqttClient.Disconnect();
+
+                    bool success = connectionClosedResetEvent.WaitOne(5000);
+
+                    if (!success)
+                    {
+                        logger.Error("Could not close MQTT-Client");
+                        return new Result(false, new Message(MessageType.Error, "Could not close MQTT-Client"));
+                    }
+                }
+                mqttClient = null;
+            }
+            return new Result(true);
+        }
+
+        private void MqttClient_ConnectionClosed(object sender, EventArgs e)
+        {
+            connectionClosedResetEvent?.Set();
+            ConnectionClosed?.Invoke(sender, e);
+        }
+    }
+
+    public class MqttMsgPublishedEventArgs : IMessagePublishedEventArgs
+    {
+        public bool IsPublished { get; }
+        public string MessageId { get; }
+        public MqttMsgPublishedEventArgs(uPLibrary.Networking.M2Mqtt.Messages.MqttMsgPublishedEventArgs e)
+        {
+            IsPublished = e.IsPublished;
+            MessageId = e.MessageId.ToString();
+        }
+    }
+    public class MqttMsgReceivedEventArgs : IMessageReceivedEventArgs
+    {
+        public string Message { get; }
+        public string Topic { get; }
+        public byte QosLevel { get; }
+        public bool Retain { get; }
+        public bool DupFlag { get; }
+        public MqttMsgReceivedEventArgs(MqttMsgPublishEventArgs e)
+        {
+            Message = Encoding.UTF8.GetString(e.Message);
+            Topic = e.Topic;
+            QosLevel = e.QosLevel;
+            Retain = e.Retain;
+            DupFlag = e.DupFlag;
+        }
+    }
+
+}
diff --git a/sdks/dotnet/basyx-core/BaSyx.Utils/Config/IEventHandlerConfig.cs b/sdks/dotnet/basyx-core/BaSyx.Utils/Config/IEventHandlerConfig.cs
new file mode 100644
index 0000000..20a0f15
--- /dev/null
+++ b/sdks/dotnet/basyx-core/BaSyx.Utils/Config/IEventHandlerConfig.cs
@@ -0,0 +1,24 @@
+/*******************************************************************************
+* Copyright (c) 2020 Robert Bosch GmbH
+* Author: Constantin Ziesche (constantin.ziesche@bosch.com)
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License 2.0 which is available at
+* http://www.eclipse.org/legal/epl-2.0
+*
+* SPDX-License-Identifier: EPL-2.0
+*******************************************************************************/
+using BaSyx.Utils.Security;
+
+namespace BaSyx.Utils.Config
+{
+    public interface IEventHandlerConfig
+    {
+        string ClientId { get; }
+        string BrokerEndpoint { get; }
+        int PublishTimeout { get; }
+        int ReceiveTimeout { get; }
+        ICredentials Credentials { get; }
+        ISecurity Security { get; }
+    }
+}
diff --git a/sdks/dotnet/basyx-core/BaSyx.Utils/DIExtensions/DIExtension.cs b/sdks/dotnet/basyx-core/BaSyx.Utils/DIExtensions/DIExtension.cs
new file mode 100644
index 0000000..6024254
--- /dev/null
+++ b/sdks/dotnet/basyx-core/BaSyx.Utils/DIExtensions/DIExtension.cs
@@ -0,0 +1,36 @@
+/*******************************************************************************
+* Copyright (c) 2020 Robert Bosch GmbH
+* Author: Constantin Ziesche (constantin.ziesche@bosch.com)
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License 2.0 which is available at
+* http://www.eclipse.org/legal/epl-2.0
+*
+* SPDX-License-Identifier: EPL-2.0
+*******************************************************************************/
+using Microsoft.Extensions.DependencyInjection;
+using System;
+using System.Collections.Generic;
+
+namespace BaSyx.Utils.DIExtensions
+{
+    public class DIExtension : IDIExtension
+    {
+        IDictionary<Type, Type> typeDictionary = new Dictionary<Type, Type>();
+        public DIExtension(IServiceCollection serviceCollection)
+        {
+            foreach (var service in serviceCollection)
+            {
+                typeDictionary[service.ServiceType] = service.ImplementationType;
+            }
+        }
+        public Type GetRegisteredTypeFor(Type t)
+        {
+            return typeDictionary[t];
+        }
+        public bool IsTypeRegistered(Type t)
+        {
+            return typeDictionary.ContainsKey(t);
+        }
+    }
+}
diff --git a/sdks/dotnet/basyx-core/BaSyx.Utils/DIExtensions/IDIExtension.cs b/sdks/dotnet/basyx-core/BaSyx.Utils/DIExtensions/IDIExtension.cs
new file mode 100644
index 0000000..cddc15a
--- /dev/null
+++ b/sdks/dotnet/basyx-core/BaSyx.Utils/DIExtensions/IDIExtension.cs
@@ -0,0 +1,20 @@
+/*******************************************************************************
+* Copyright (c) 2020 Robert Bosch GmbH
+* Author: Constantin Ziesche (constantin.ziesche@bosch.com)
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License 2.0 which is available at
+* http://www.eclipse.org/legal/epl-2.0
+*
+* SPDX-License-Identifier: EPL-2.0
+*******************************************************************************/
+using System;
+
+namespace BaSyx.Utils.DIExtensions
+{
+    public interface IDIExtension
+    {
+        Type GetRegisteredTypeFor(Type t);
+        bool IsTypeRegistered(Type t);
+    }
+}
diff --git a/sdks/dotnet/basyx-core/BaSyx.Utils/DIExtensions/StandardDIConfiguration.cs b/sdks/dotnet/basyx-core/BaSyx.Utils/DIExtensions/StandardDIConfiguration.cs
new file mode 100644
index 0000000..c12a48e
--- /dev/null
+++ b/sdks/dotnet/basyx-core/BaSyx.Utils/DIExtensions/StandardDIConfiguration.cs
@@ -0,0 +1,32 @@
+/*******************************************************************************
+* Copyright (c) 2020 Robert Bosch GmbH
+* Author: Constantin Ziesche (constantin.ziesche@bosch.com)
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License 2.0 which is available at
+* http://www.eclipse.org/legal/epl-2.0
+*
+* SPDX-License-Identifier: EPL-2.0
+*******************************************************************************/
+using BaSyx.Utils.JsonHandling;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.DependencyInjection.Extensions;
+using Microsoft.Extensions.Options;
+
+namespace BaSyx.Utils.DIExtensions
+{
+    public static class StandardDIConfiguration
+    {
+        public static IServiceCollection ConfigureStandardDI(this IServiceCollection services)
+        {
+            services.TryAddSingleton<IDIExtension>(s =>
+            {
+                return new DIExtension(services);
+            });
+            services.AddTransient<IConfigureOptions<MvcJsonOptions>, JsonOptionsSetup>();
+
+            return services;
+        }
+    }
+}
diff --git a/sdks/dotnet/basyx-core/BaSyx.Utils/JsonHandling/CustomTypeSerializer.cs b/sdks/dotnet/basyx-core/BaSyx.Utils/JsonHandling/CustomTypeSerializer.cs
new file mode 100644
index 0000000..b65fbae
--- /dev/null
+++ b/sdks/dotnet/basyx-core/BaSyx.Utils/JsonHandling/CustomTypeSerializer.cs
@@ -0,0 +1,81 @@
+/*******************************************************************************
+* Copyright (c) 2020 Robert Bosch GmbH
+* Author: Constantin Ziesche (constantin.ziesche@bosch.com)
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License 2.0 which is available at
+* http://www.eclipse.org/legal/epl-2.0
+*
+* SPDX-License-Identifier: EPL-2.0
+*******************************************************************************/
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using System;
+
+namespace BaSyx.Utils.JsonHandling
+{
+    public class CustomTypeSerializer : JsonConverter
+    {
+        [ThreadStatic]
+        static bool disabled;
+
+        bool Disabled { get { return disabled; } set { disabled = value; } }
+
+        public override bool CanWrite { get { return !Disabled; } }
+
+        public override bool CanConvert(Type objectType)
+        {
+            return true;
+        }
+        public override bool CanRead => false;
+
+        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
+        {
+            throw new NotImplementedException();
+        }
+
+        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
+        {
+            JToken t;
+            using (new PushValue<bool>(true, () => Disabled, (canWrite) => Disabled = canWrite))
+            {
+                t = JToken.FromObject(value, serializer);
+            }
+
+            if (t.Type != JTokenType.Object)
+            {
+                t.WriteTo(writer);
+            }
+            else
+            {
+                JObject o = (JObject)t;
+                Type type = value.GetType();
+                JObject typeWrapper = new JObject(new JProperty(type.Namespace + "." + type.Name, o));
+
+                typeWrapper.WriteTo(writer);
+            }
+        }
+    }
+
+    public struct PushValue<T> : IDisposable
+    {
+        Func<T> getValue;
+        Action<T> setValue;
+        T oldValue;
+
+        public PushValue(T value, Func<T> getValue, Action<T> setValue)
+        {
+            if (getValue == null || setValue == null)
+                throw new ArgumentNullException();
+            this.getValue = getValue;
+            this.setValue = setValue;
+            this.oldValue = getValue();
+            setValue(value);
+        }
+
+        public void Dispose()
+        {
+            setValue?.Invoke(oldValue);
+        }
+    }
+}
diff --git a/sdks/dotnet/basyx-core/BaSyx.Utils/JsonHandling/DIContractResolver.cs b/sdks/dotnet/basyx-core/BaSyx.Utils/JsonHandling/DIContractResolver.cs
new file mode 100644
index 0000000..8cd421c
--- /dev/null
+++ b/sdks/dotnet/basyx-core/BaSyx.Utils/JsonHandling/DIContractResolver.cs
@@ -0,0 +1,46 @@
+/*******************************************************************************
+* Copyright (c) 2020 Robert Bosch GmbH
+* Author: Constantin Ziesche (constantin.ziesche@bosch.com)
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License 2.0 which is available at
+* http://www.eclipse.org/legal/epl-2.0
+*
+* SPDX-License-Identifier: EPL-2.0
+*******************************************************************************/
+using BaSyx.Utils.DIExtensions;
+using Newtonsoft.Json.Serialization;
+using System;
+
+namespace BaSyx.Utils.JsonHandling
+{
+    public class DIContractResolver : CamelCasePropertyNamesContractResolver
+    {
+        public IDIExtension DIExtension { get; }
+        public IServiceProvider ServiceProvider { get; }
+        public DIContractResolver(IDIExtension diExtension, IServiceProvider serviceProvider)
+        {
+            DIExtension = diExtension;
+            ServiceProvider = serviceProvider;
+        }
+        protected override JsonObjectContract CreateObjectContract(Type objectType)
+        {
+            if (DIExtension.IsTypeRegistered(objectType))
+            {
+                JsonObjectContract contract = DIResolveContract(objectType);
+                contract.DefaultCreator = () => ServiceProvider.GetService(objectType);
+                return contract;
+            }
+
+            return base.CreateObjectContract(objectType);
+        }
+        private JsonObjectContract DIResolveContract(Type objectType)
+        {
+            var registeredType = DIExtension.GetRegisteredTypeFor(objectType);
+            if (registeredType != null)
+                return base.CreateObjectContract(registeredType);
+            else
+                return CreateObjectContract(objectType);
+        }
+    }
+}
diff --git a/sdks/dotnet/basyx-core/BaSyx.Utils/JsonHandling/JsonOptionsSetup.cs b/sdks/dotnet/basyx-core/BaSyx.Utils/JsonHandling/JsonOptionsSetup.cs
new file mode 100644
index 0000000..6cee2c1
--- /dev/null
+++ b/sdks/dotnet/basyx-core/BaSyx.Utils/JsonHandling/JsonOptionsSetup.cs
@@ -0,0 +1,37 @@
+/*******************************************************************************
+* Copyright (c) 2020 Robert Bosch GmbH
+* Author: Constantin Ziesche (constantin.ziesche@bosch.com)
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License 2.0 which is available at
+* http://www.eclipse.org/legal/epl-2.0
+*
+* SPDX-License-Identifier: EPL-2.0
+*******************************************************************************/
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Options;
+using Microsoft.Extensions.DependencyInjection;
+using System;
+using BaSyx.Utils.DIExtensions;
+
+namespace BaSyx.Utils.JsonHandling
+{
+    public class JsonOptionsSetup : IConfigureOptions<MvcJsonOptions>
+    {
+        IServiceProvider serviceProvider;
+
+        public MvcJsonOptions Options { get; private set; }
+        public JsonOptionsSetup(IServiceProvider serviceProvider)
+        {
+            this.serviceProvider = serviceProvider;
+        }
+        public void Configure(MvcJsonOptions options)
+        {
+            options.SerializerSettings.ContractResolver = new DIContractResolver(serviceProvider.GetService<IDIExtension>(), serviceProvider);
+            options.SerializerSettings.NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore;
+            options.SerializerSettings.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter());
+
+            Options = options;
+        }
+    }
+}
diff --git a/sdks/dotnet/basyx-core/BaSyx.Utils/JsonHandling/PrivatePropertyContractResolver.cs b/sdks/dotnet/basyx-core/BaSyx.Utils/JsonHandling/PrivatePropertyContractResolver.cs
new file mode 100644
index 0000000..e6acb36
--- /dev/null
+++ b/sdks/dotnet/basyx-core/BaSyx.Utils/JsonHandling/PrivatePropertyContractResolver.cs
@@ -0,0 +1,37 @@
+/*******************************************************************************
+* Copyright (c) 2020 Robert Bosch GmbH
+* Author: Constantin Ziesche (constantin.ziesche@bosch.com)
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License 2.0 which is available at
+* http://www.eclipse.org/legal/epl-2.0
+*
+* SPDX-License-Identifier: EPL-2.0
+*******************************************************************************/
+using Newtonsoft.Json;
+using Newtonsoft.Json.Serialization;
+using System.Reflection;
+
+namespace BaSyx.Utils.JsonHandling
+{
+    public class PrivatePropertyContractResolver : DefaultContractResolver
+    {
+        protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
+        {
+            var prop = base.CreateProperty(member, memberSerialization);
+
+            if (!prop.Writable)
+            {
+                var property = member as PropertyInfo;
+                if (property != null)
+                {
+                    var hasPrivateSetter = property.GetSetMethod(true) != null;
+                    prop.Writable = hasPrivateSetter;
+                }
+            }
+
+            return prop;
+        }
+
+    }
+}
diff --git a/sdks/dotnet/basyx-core/BaSyx.Utils/Logging/LoggingExtentions.cs b/sdks/dotnet/basyx-core/BaSyx.Utils/Logging/LoggingExtentions.cs
new file mode 100644
index 0000000..ec5584c
--- /dev/null
+++ b/sdks/dotnet/basyx-core/BaSyx.Utils/Logging/LoggingExtentions.cs
@@ -0,0 +1,66 @@
+/*******************************************************************************
+* Copyright (c) 2020 Robert Bosch GmbH
+* Author: Constantin Ziesche (constantin.ziesche@bosch.com)
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License 2.0 which is available at
+* http://www.eclipse.org/legal/epl-2.0
+*
+* SPDX-License-Identifier: EPL-2.0
+*******************************************************************************/
+using BaSyx.Utils.ResultHandling;
+using NLog;
+using System;
+using System.Net.Http;
+using System.Text;
+
+namespace BaSyx.Utils.Logging
+{
+    public static class LoggingExtentions
+    {
+        public static void LogResult(this IResult result, ILogger logger, LogLevel logLevel, string additionalText = null, Exception exp = null)
+        {
+            StringBuilder logText = new StringBuilder();
+            logText.Append("Success: " + result.Success).Append(" || ");
+
+            if (result.Messages != null)
+            {
+                for (int i = 0; i < result.Messages.Count; i++)
+                {
+                    logText.Append("Message[" + i + "] = " + result.Messages[i].Text).Append(" || ");
+                }
+            }
+            if (result.Entity != null && result.Entity is HttpResponseMessage response)
+            {
+                logText.Append("StatusCode: " + ((int)response.StatusCode).ToString()).Append(response.ReasonPhrase).Append(" || ");
+                logText.Append("Body: " + response.Content.ReadAsStringAsync().Result).Append(" || ");
+            }
+            if (!string.IsNullOrEmpty(additionalText))
+                logText.Append("AdditionalText: " + additionalText).Append(" || ");
+
+            string msg = logText.ToString();
+            if (exp != null)
+                logger.Log(logLevel, exp, msg);
+            else
+                logger.Log(logLevel, msg);
+        }
+
+        public static Microsoft.Extensions.Logging.LogLevel GetLogLevel(ILogger logger)
+        {
+            if (logger.IsDebugEnabled)
+                return Microsoft.Extensions.Logging.LogLevel.Debug;
+            else if (logger.IsErrorEnabled)
+                return Microsoft.Extensions.Logging.LogLevel.Error;
+            else if (logger.IsFatalEnabled)
+                return Microsoft.Extensions.Logging.LogLevel.Critical;
+            else if (logger.IsInfoEnabled)
+                return Microsoft.Extensions.Logging.LogLevel.Information;
+            else if (logger.IsTraceEnabled)
+                return Microsoft.Extensions.Logging.LogLevel.Trace;
+            else if (logger.IsWarnEnabled)
+                return Microsoft.Extensions.Logging.LogLevel.Warning;
+            else
+                return Microsoft.Extensions.Logging.LogLevel.None;
+        }
+    }
+}
diff --git a/sdks/dotnet/basyx-core/BaSyx.Utils/ModelHandling/ModelUtils.cs b/sdks/dotnet/basyx-core/BaSyx.Utils/ModelHandling/ModelUtils.cs
new file mode 100644
index 0000000..bab5a82
--- /dev/null
+++ b/sdks/dotnet/basyx-core/BaSyx.Utils/ModelHandling/ModelUtils.cs
@@ -0,0 +1,31 @@
+/*******************************************************************************
+* Copyright (c) 2020 Robert Bosch GmbH
+* Author: Constantin Ziesche (constantin.ziesche@bosch.com)
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License 2.0 which is available at
+* http://www.eclipse.org/legal/epl-2.0
+*
+* SPDX-License-Identifier: EPL-2.0
+*******************************************************************************/
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using System.Text;
+
+namespace BaSyx.Utils.ModelHandling
+{
+    public class ModelUtils
+    {
+        public static IEnumerable<Type> GetTypesWithAttribute(Assembly assembly, Type attributeType)
+        {
+            foreach (Type type in assembly.GetTypes())
+            {
+                if (type.GetCustomAttributes(attributeType, true).Length > 0)
+                {
+                    yield return type;
+                }
+            }
+        }
+    }
+}
diff --git a/sdks/dotnet/basyx-core/BaSyx.Utils/ModelHandling/TreeBuilder.cs b/sdks/dotnet/basyx-core/BaSyx.Utils/ModelHandling/TreeBuilder.cs
new file mode 100644
index 0000000..818b290
--- /dev/null
+++ b/sdks/dotnet/basyx-core/BaSyx.Utils/ModelHandling/TreeBuilder.cs
@@ -0,0 +1,306 @@
+/*******************************************************************************
+* Copyright (c) 2020 Robert Bosch GmbH
+* Author: Constantin Ziesche (constantin.ziesche@bosch.com)
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License 2.0 which is available at
+* http://www.eclipse.org/legal/epl-2.0
+*
+* SPDX-License-Identifier: EPL-2.0
+*******************************************************************************/
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+
+namespace BaSyx.Utils.ModelHandling
+{
+    public class ObjectTreeBuilder : TreeBuilder<object>
+    {
+        protected new List<ObjectTreeBuilder> children;
+        public ObjectTreeBuilder(string rootObjectName, object rootObjectValue) : this(rootObjectName, new List<object>() { rootObjectValue })
+        { }
+        public ObjectTreeBuilder(string rootObjectName, List<object> rootObjectValues) : base(rootObjectName, rootObjectValues)
+        {
+            this.children = new List<ObjectTreeBuilder>();
+        }
+
+        public T GetValue<T>()
+        {
+            if (value != null)
+                return (T)value.FirstOrDefault(c => c.GetType().IsSubclassOf(typeof(T)) || c.GetType() == typeof(T));
+            else
+                return default(T);
+        }
+
+        public new ObjectTreeBuilder AddValue(object value)
+        {
+            this.value.Add(value);
+            return this;
+        }
+
+        public ObjectTreeBuilder AddChild(ObjectTreeBuilder child)
+        {
+            child.Parent = this;
+            this.children.Add(child);
+            return this;
+        }
+
+        public new ObjectTreeBuilder AddChild(string name, params object[] value)
+        {
+            return (AddChild(name, value.ToList()));
+        }
+
+        public new ObjectTreeBuilder AddChild(string name, List<object> value)
+        {
+            var node = new ObjectTreeBuilder(name, value) { Parent = this };
+            children.Add(node);
+            return node;
+        }
+
+        public new ObjectTreeBuilder this[int i]
+        {
+            get { return children[i]; }
+        }
+       
+        public new ObjectTreeBuilder this[string name]
+        {
+            get { return children.FirstOrDefault(s => s.Name == name); }
+        }
+
+        public new ReadOnlyCollection<ObjectTreeBuilder> Children => children.AsReadOnly();
+
+        public new bool HasChild(string childName)
+        {
+            if (children == null || children.Count == 0)
+                return false;
+            else
+            {
+                var child = children.Find(c => c.Name == childName);
+                if (child == null)
+                    return false;
+                else
+                    return true;
+            }
+        }
+
+        public new bool HasChildPath(string childPath)
+        {
+            if (string.IsNullOrEmpty(childPath))
+                return false;
+
+            if (children == null || children.Count == 0)
+                return false;
+            else
+            {
+                if (childPath.Contains("/"))
+                {
+                    string[] splittedPath = childPath.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
+                    if (!HasChild(splittedPath[0]))
+                        return false;
+                    else
+                    {
+                        var child = this[splittedPath[0]];
+                        return (child.HasChildPath(string.Join("/", splittedPath.Skip(1))));
+                    }
+                }
+                else
+                    return HasChild(childPath);
+            }
+        }
+
+        public new ObjectTreeBuilder GetChild(string childPath)
+        {
+            if (string.IsNullOrEmpty(childPath))
+                return null;
+
+            if (children == null || children.Count == 0)
+                return null;
+            else
+            {
+                ObjectTreeBuilder superChild = null;
+                if (childPath.Contains("/"))
+                {
+                    string[] splittedPath = childPath.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
+                    if (!HasChild(splittedPath[0]))
+                        return null;
+                    else
+                    {
+                        var child = this[splittedPath[0]];
+                        superChild = child.GetChild(string.Join("/", splittedPath.Skip(1)));
+                    }
+                }
+                else
+                    superChild = this[childPath];
+
+                return superChild;
+            }
+        }
+
+        public new bool HasChildren()
+        {
+            if (children == null)
+                return false;
+            else
+            {
+                if (children.Count == 0)
+                    return false;
+                else
+                    return true;
+            }
+        }
+
+       
+
+        public new void Traverse(Action<List<object>> action)
+        {
+            action(Value);
+            foreach (var child in children)
+                child.Traverse(action);
+        }
+    }
+    public class TreeBuilder<T>
+    {
+        protected List<T> value;
+        protected List<TreeBuilder<T>> children;
+        public TreeBuilder<T> Parent { get; protected set; }
+        public List<T> Value { get { return value; } }
+        public string Name { get; protected set; }
+
+        public TreeBuilder(string name, T data) : this (name, new List<T>() { data })
+        { }
+
+        public TreeBuilder(string name, List<T> data)
+        {
+            this.Name = name;
+            this.value = data;
+            this.children = new List<TreeBuilder<T>>();
+        }
+
+        public ReadOnlyCollection<TreeBuilder<T>> Children
+        {
+            get { return children.AsReadOnly(); }
+        }
+
+        public TreeBuilder<T> AddValue(T value)
+        {
+            this.value.Add(value);
+            return this;
+        } 
+
+        public TreeBuilder<T> this[int i]
+        {
+            get { return children[i]; }
+        }
+
+        public TreeBuilder<T> this[string name]
+        {
+            get { return children.FirstOrDefault(s => s.Name == name); }
+        }
+
+        public void Traverse(Action<List<T>> action)
+        {
+            action(Value);
+            foreach (var child in children)
+                child.Traverse(action);
+        }
+
+        #region Child-Operations
+        public TreeBuilder<T> AddChild(TreeBuilder<T> child)
+        {
+            child.Parent = this;
+            this.children.Add(child);
+            return this;
+        }
+
+        public TreeBuilder<T> AddChild(string name, params T[] value)
+        {
+            return (AddChild(name, value.ToList()));
+        }
+
+        public TreeBuilder<T> AddChild(string name, List<T> value)
+        {
+            var node = new TreeBuilder<T>(name, value) { Parent = this };
+            children.Add(node);
+            return node;
+        }
+        public bool HasChildPath(string childPath)
+        {
+            if (string.IsNullOrEmpty(childPath))
+                return false;
+
+            if (children == null || children.Count == 0)
+                return false;
+            else
+            {
+                if (childPath.Contains("/"))
+                {
+                    string[] splittedPath = childPath.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
+                    if (!HasChild(splittedPath[0]))
+                        return false;
+                    else
+                    {
+                        var child = this[splittedPath[0]];
+                        return (child.HasChildPath(string.Join("/", splittedPath.Skip(1))));
+                    }
+                }
+                else
+                    return HasChild(childPath);
+            }
+        }
+        public bool HasChildren()
+        {
+            if (children == null)
+                return false;
+            else
+            {
+                if (children.Count == 0)
+                    return false;
+                else
+                    return true;
+            }
+        }
+        public bool HasChild(string childName)
+        {
+            if (children == null || children.Count == 0)
+                return false;
+            else
+            {
+                var child = children.Find(c => c.Name == childName);
+                if (child == null)
+                    return false;
+                else
+                    return true;
+            }
+        }
+
+        public TreeBuilder<T> GetChild(string childPath)
+        {
+            if (string.IsNullOrEmpty(childPath))
+                return null;
+
+            if (children == null || children.Count == 0)
+                return null;
+            else
+            {
+                TreeBuilder<T> superChild = null;
+                if (childPath.Contains("/"))
+                {
+                    string[] splittedPath = childPath.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
+                    if (!HasChild(splittedPath[0]))
+                        return null;
+                    else
+                    {
+                        var child = this[splittedPath[0]];
+                        superChild = child.GetChild(string.Join("/", splittedPath.Skip(1)));
+                    }
+                }
+                else
+                    superChild = this[childPath];
+
+                return superChild;
+            }
+        }
+        #endregion
+    }
+}
diff --git a/sdks/dotnet/basyx-core/BaSyx.Utils/Network/NetworkUtils.cs b/sdks/dotnet/basyx-core/BaSyx.Utils/Network/NetworkUtils.cs
new file mode 100644
index 0000000..e2d6b0f
--- /dev/null
+++ b/sdks/dotnet/basyx-core/BaSyx.Utils/Network/NetworkUtils.cs
@@ -0,0 +1,73 @@
+/*******************************************************************************
+* Copyright (c) 2020 Robert Bosch GmbH
+* Author: Constantin Ziesche (constantin.ziesche@bosch.com)
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License 2.0 which is available at
+* http://www.eclipse.org/legal/epl-2.0
+*
+* SPDX-License-Identifier: EPL-2.0
+*******************************************************************************/
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+
+namespace BaSyx.Utils.Network
+{
+    public static class NetworkUtils
+    {
+        /// <summary>
+        /// This method returns the closest source IP address relative to the the target IP address. 
+        /// The probality of being able to call the target IP hence increases.
+        /// </summary>
+        /// <param name="target">Target IP address to call</param>
+        /// <param name="sources">Source IP address from where to cal the target</param>
+        /// <returns>The closest source IP address to the the target IP address or the Loopback Address</returns>
+        public static IPAddress GetClosestIPAddress(IPAddress target, List<IPAddress> sources)
+        {
+            Dictionary<int, IPAddress> scoredSourceIPAddresses = new Dictionary<int, IPAddress>();
+            byte[] targetBytes = target.GetAddressBytes();
+            foreach (var source in sources)
+            {
+                byte[] sourceBytes = source.GetAddressBytes();
+                int score = CompareIPByteArray(targetBytes, sourceBytes);
+
+                if(!scoredSourceIPAddresses.ContainsKey(score) && score != 0)
+                    scoredSourceIPAddresses.Add(score, source);
+            }
+
+            if(scoredSourceIPAddresses.Count > 0)
+                return scoredSourceIPAddresses[scoredSourceIPAddresses.Keys.Max()];
+
+            return IPAddress.Loopback;
+        }
+
+        private static int CompareIPByteArray(byte[] target, byte[] source)
+        {
+            if (target.Length != source.Length)
+                return 0;
+
+            int score = 0;
+            for (int i = 0; i < source.Length; i++)
+            {
+                if (target[i] == source[i])
+                    score++;
+                else
+                    return score;
+            }
+            return score;
+        }
+
+        public static List<IPAddress> GetAllNetworkIPAddresses()
+        {
+            IPHostEntry host = Dns.GetHostEntry(Dns.GetHostName());
+            List<IPAddress> ipAddresses = new List<IPAddress>();
+            foreach (var ip in host.AddressList)
+            {
+                if (ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
+                    ipAddresses.Add(ip);
+            }
+            return ipAddresses;
+        }
+    }
+}
diff --git a/sdks/dotnet/basyx-core/BaSyx.Utils/PathHandling/Path.cs b/sdks/dotnet/basyx-core/BaSyx.Utils/PathHandling/Path.cs
new file mode 100644
index 0000000..5f377ab
--- /dev/null
+++ b/sdks/dotnet/basyx-core/BaSyx.Utils/PathHandling/Path.cs
@@ -0,0 +1,43 @@
+/*******************************************************************************
+* Copyright (c) 2020 Robert Bosch GmbH
+* Author: Constantin Ziesche (constantin.ziesche@bosch.com)
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License 2.0 which is available at
+* http://www.eclipse.org/legal/epl-2.0
+*
+* SPDX-License-Identifier: EPL-2.0
+*******************************************************************************/
+using System;
+using System.Linq;
+
+namespace BaSyx.Utils.PathHandling
+{
+    public static class Path
+    {
+        public static Uri Append(this Uri uri, params string[] pathElements)
+        {
+            return new Uri(pathElements.Aggregate(uri.AbsoluteUri, (currentElement, pathElement) => string.Format("{0}/{1}", currentElement.TrimEnd('/'), pathElement.TrimStart('/'))));
+        }
+
+        public static string GetFormattedEndpoint(string endpoint, string aggregateId, string entityId, string separator = "/")
+        {
+            if (endpoint[endpoint.Length - 1] == separator[0])
+            {
+                if (!endpoint.Contains(aggregateId))
+                    endpoint += aggregateId + separator + entityId;
+                else
+                    endpoint += entityId;
+            }
+            else
+            {
+                if (!endpoint.Contains(aggregateId))
+                    endpoint += separator + aggregateId + separator + entityId;
+                else
+                    endpoint += separator + entityId;
+            }
+
+            return endpoint;
+        }
+    }
+}
diff --git a/sdks/dotnet/basyx-core/BaSyx.Utils/ResultHandling/FilterExpression.cs b/sdks/dotnet/basyx-core/BaSyx.Utils/ResultHandling/FilterExpression.cs
new file mode 100644
index 0000000..90268c0
--- /dev/null
+++ b/sdks/dotnet/basyx-core/BaSyx.Utils/ResultHandling/FilterExpression.cs
@@ -0,0 +1,116 @@
+/*******************************************************************************
+* Copyright (c) 2020 Robert Bosch GmbH
+* Author: Constantin Ziesche (constantin.ziesche@bosch.com)
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License 2.0 which is available at
+* http://www.eclipse.org/legal/epl-2.0
+*
+* SPDX-License-Identifier: EPL-2.0
+*******************************************************************************/
+using Newtonsoft.Json.Linq;
+using System.Collections.Generic;
+
+namespace BaSyx.Utils.ResultHandling
+{
+    public interface IFilterArgument
+    {
+        FilterArgumentType FilterArgumentType { get; }
+        FilterType FilterType { get; set; }
+    }
+
+    public sealed class KeyValue : IFilterArgument
+    {
+        public FilterType FilterType { get; set; }
+        public string Key { get; set; }
+        public string Value { get; set; }
+        public FilterArgumentType FilterArgumentType => FilterArgumentType.KeyValue;
+    }
+
+    public class FilterExpression : IFilterArgument
+    {
+        public FilterType FilterType { get; set; }
+        public List<IFilterArgument> Arguments { get; set; }
+        public FilterArgumentType FilterArgumentType => FilterArgumentType.FilterExpression;
+
+        public static FilterExpression Parse(JObject query)
+        {
+            if (query != null)
+            {
+                FilterExpression filterExpression = new FilterExpression();
+                filterExpression.FilterType = FilterType.Parse(query.SelectToken("name").Value<string>());
+                var argsArray = (JArray)query.SelectToken("args");
+                if (argsArray.HasValues)
+                {
+                    filterExpression.Arguments = new List<IFilterArgument>();
+                    FilterExpression subFilter = new FilterExpression();
+                    subFilter.Arguments = new List<IFilterArgument>();  
+                    foreach (var item in argsArray)
+                    {
+                        subFilter.FilterType = FilterType.Parse(item.SelectToken("name").Value<string>());
+                        if (subFilter.FilterType == FilterType.AND || subFilter.FilterType == FilterType.OR)
+                        {
+                            var argObj = Parse((JObject)item);
+                            subFilter.Arguments.Add(argObj);
+                        }
+                        else
+                        {
+                            var keyValueArg = new KeyValue();
+                            keyValueArg.FilterType = FilterType.Parse(item.SelectToken("name").Value<string>());
+                            keyValueArg.Key = item.SelectToken("args[0]").ToString();
+                            keyValueArg.Value = item.SelectToken("args[1]").ToString();
+
+                            subFilter.Arguments.Add(keyValueArg);
+                        }
+                    }
+                    filterExpression.Arguments.Add(subFilter);
+                }
+                return filterExpression;
+            }
+            return null;
+        }
+    }
+
+   
+
+    public enum FilterArgumentType : int
+    {
+        KeyValue = 0,
+        FilterExpression = 1
+    }
+
+    public sealed class FilterType
+    {
+        private readonly string Name;
+        private readonly int Value;
+
+        public static readonly FilterType EQUALS = new FilterType(1, "eq");
+        public static readonly FilterType AND = new FilterType(2, "and");
+        public static readonly FilterType OR = new FilterType(3, "or");
+
+        private FilterType(int value, string name)
+        {
+            Name = name;
+            Value = value;
+        }
+
+        public override string ToString()
+        {
+            return Name;
+        }
+
+        public static FilterType Parse(string s)
+        {
+            switch (s.ToLower())
+            {
+                case "eq": return EQUALS;
+                case "and": return AND;
+                case "or": return OR;
+                default:
+                    break;
+            }
+            return null;
+        }
+
+    }
+}
diff --git a/sdks/dotnet/basyx-core/BaSyx.Utils/ResultHandling/IMessage.cs b/sdks/dotnet/basyx-core/BaSyx.Utils/ResultHandling/IMessage.cs
new file mode 100644
index 0000000..5085f7b
--- /dev/null
+++ b/sdks/dotnet/basyx-core/BaSyx.Utils/ResultHandling/IMessage.cs
@@ -0,0 +1,20 @@
+/*******************************************************************************
+* Copyright (c) 2020 Robert Bosch GmbH
+* Author: Constantin Ziesche (constantin.ziesche@bosch.com)
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License 2.0 which is available at
+* http://www.eclipse.org/legal/epl-2.0
+*
+* SPDX-License-Identifier: EPL-2.0
+*******************************************************************************/
+namespace BaSyx.Utils.ResultHandling
+{
+    public interface IMessage
+    {
+        MessageType MessageType { get; set; }
+        string Code { get; set; }
+        string Text { get; set; }
+        string ToString();
+    }
+}
diff --git a/sdks/dotnet/basyx-core/BaSyx.Utils/ResultHandling/IResult.cs b/sdks/dotnet/basyx-core/BaSyx.Utils/ResultHandling/IResult.cs
new file mode 100644
index 0000000..19fc256
--- /dev/null
+++ b/sdks/dotnet/basyx-core/BaSyx.Utils/ResultHandling/IResult.cs
@@ -0,0 +1,40 @@
+/*******************************************************************************
+* Copyright (c) 2020 Robert Bosch GmbH
+* Author: Constantin Ziesche (constantin.ziesche@bosch.com)
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License 2.0 which is available at
+* http://www.eclipse.org/legal/epl-2.0
+*
+* SPDX-License-Identifier: EPL-2.0
+*******************************************************************************/
+using BaSyx.Utils.JsonHandling;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Runtime.Serialization;
+
+namespace BaSyx.Utils.ResultHandling
+{
+    public interface IResult
+    {
+        [DataMember(EmitDefaultValue = false, IsRequired = false)]
+        Type EntityType { get; }
+        [DataMember(EmitDefaultValue = false, IsRequired = false)]
+        object Entity { get; }
+        [DataMember(IsRequired = true)]
+        bool Success { get; }
+        [DataMember(EmitDefaultValue = false, IsRequired = false)]
+        bool? IsException { get; }
+        [DataMember(EmitDefaultValue = false, IsRequired = false)]
+        MessageCollection Messages { get; }
+
+        T GetEntity<T>();
+    }
+
+    public interface IResult<out TEntity> : IResult
+    {
+        [JsonConverter(typeof(CustomTypeSerializer))]
+        new TEntity Entity { get; }
+    }
+}
diff --git a/sdks/dotnet/basyx-core/BaSyx.Utils/ResultHandling/Message.cs b/sdks/dotnet/basyx-core/BaSyx.Utils/ResultHandling/Message.cs
new file mode 100644
index 0000000..83a3221
--- /dev/null
+++ b/sdks/dotnet/basyx-core/BaSyx.Utils/ResultHandling/Message.cs
@@ -0,0 +1,75 @@
+/*******************************************************************************
+* Copyright (c) 2020 Robert Bosch GmbH
+* Author: Constantin Ziesche (constantin.ziesche@bosch.com)
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License 2.0 which is available at
+* http://www.eclipse.org/legal/epl-2.0
+*
+* SPDX-License-Identifier: EPL-2.0
+*******************************************************************************/
+using System.Globalization;
+using System.Net;
+using System.Threading;
+
+namespace BaSyx.Utils.ResultHandling
+{
+    public class Message : IMessage
+    {
+        public MessageType MessageType { get; set; }
+        public string Text { get; set; }
+        public string Code { get; set; }
+
+        public Message(MessageType messageType, string text) : this(messageType, text, null)
+        { }
+        public Message(MessageType messageType, string text, string code)
+        {
+            MessageType = messageType;
+            Text = text;
+            Code = code;
+        }
+
+
+        public override string ToString()
+        {
+            if(!string.IsNullOrEmpty(Code))
+                return string.Format(CultureInfo.CurrentCulture, "{0} | {1} - {2}", MessageType, Code, Text);
+            else
+                return string.Format(CultureInfo.CurrentCulture, "{0} | {1}", MessageType, Text);
+        }
+    }
+
+    public class HttpMessage : Message
+    {
+        public HttpStatusCode HttpStatusCode { get; set; }
+
+        public HttpMessage(MessageType messageType, HttpStatusCode httpStatusCode) : base(messageType, httpStatusCode.ToString(), ((int)httpStatusCode).ToString())
+        {
+            HttpStatusCode = httpStatusCode;
+        }
+    }
+
+    public class NotFoundMessage : Message
+    {
+        public NotFoundMessage() : base(MessageType.Information, "NotFound", "404")
+        { }
+
+        public NotFoundMessage(string what) : base(MessageType.Information, what + " not found", "404")
+        { }
+    }
+
+    public class ConflictMessage : Message
+    {
+        public ConflictMessage() : base(MessageType.Information, "Conflict", "409")
+        { }
+
+        public ConflictMessage(string what) : base(MessageType.Information, what + " already exists", "409")
+        { }
+    }
+
+    public class EmptyMessage : Message
+    {
+        public EmptyMessage() : base(MessageType.Information, "Empty")
+        { }
+    }
+}
diff --git a/sdks/dotnet/basyx-core/BaSyx.Utils/ResultHandling/MessageCollection.cs b/sdks/dotnet/basyx-core/BaSyx.Utils/ResultHandling/MessageCollection.cs
new file mode 100644
index 0000000..bb315cd
--- /dev/null
+++ b/sdks/dotnet/basyx-core/BaSyx.Utils/ResultHandling/MessageCollection.cs
@@ -0,0 +1,29 @@
+/*******************************************************************************
+* Copyright (c) 2020 Robert Bosch GmbH
+* Author: Constantin Ziesche (constantin.ziesche@bosch.com)
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License 2.0 which is available at
+* http://www.eclipse.org/legal/epl-2.0
+*
+* SPDX-License-Identifier: EPL-2.0
+*******************************************************************************/
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace BaSyx.Utils.ResultHandling
+{
+    public class MessageCollection : List<IMessage>
+    {
+        public override string ToString()
+        {
+            string serializedMessageCollection = string.Empty;
+            if (this.Count > 0)
+                foreach (var item in this)
+                    serializedMessageCollection += item.ToString() + Environment.NewLine;
+
+            return serializedMessageCollection;
+        }
+    }
+}
diff --git a/sdks/dotnet/basyx-core/BaSyx.Utils/ResultHandling/MessageType.cs b/sdks/dotnet/basyx-core/BaSyx.Utils/ResultHandling/MessageType.cs
new file mode 100644
index 0000000..30c942f
--- /dev/null
+++ b/sdks/dotnet/basyx-core/BaSyx.Utils/ResultHandling/MessageType.cs
@@ -0,0 +1,23 @@
+/*******************************************************************************
+* Copyright (c) 2020 Robert Bosch GmbH
+* Author: Constantin Ziesche (constantin.ziesche@bosch.com)
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License 2.0 which is available at
+* http://www.eclipse.org/legal/epl-2.0
+*
+* SPDX-License-Identifier: EPL-2.0
+*******************************************************************************/
+namespace BaSyx.Utils.ResultHandling
+{
+    public enum MessageType : int
+    {
+        Unspecified = 0,
+        Debug = 1,
+        Information = 2,
+        Warning = 3,
+        Error = 4,
+        Fatal = 5,
+        Exception = 6
+    }
+}
diff --git a/sdks/dotnet/basyx-core/BaSyx.Utils/ResultHandling/Result.cs b/sdks/dotnet/basyx-core/BaSyx.Utils/ResultHandling/Result.cs
new file mode 100644
index 0000000..b777186
--- /dev/null
+++ b/sdks/dotnet/basyx-core/BaSyx.Utils/ResultHandling/Result.cs
@@ -0,0 +1,154 @@
+/*******************************************************************************
+* Copyright (c) 2020 Robert Bosch GmbH
+* Author: Constantin Ziesche (constantin.ziesche@bosch.com)
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License 2.0 which is available at
+* http://www.eclipse.org/legal/epl-2.0
+*
+* SPDX-License-Identifier: EPL-2.0
+*******************************************************************************/
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.Serialization;
+
+namespace BaSyx.Utils.ResultHandling
+{
+    public class Result : IResult
+    {
+        public bool Success { get; private set; }
+
+        public bool? IsException { get; }
+
+        public object Entity { get; private set; }
+
+        public Type EntityType { get; private set; }
+
+        private MessageCollection messages;
+
+        public MessageCollection Messages
+        {
+            get
+            {
+                if (this.messages == null)
+                    this.messages = new MessageCollection();
+                return this.messages;
+            }
+        }
+        public Result(bool success) : this(success, null, null, null)
+        { }
+        public Result(bool success, IMessage message) : this(success, new List<IMessage>() { message })
+        { }
+
+        public Result(bool success, List<IMessage> messages) : this(success, null, null, messages)
+        { }
+
+        public Result(bool success, object entity, Type entityType) : this(success, entity, entityType, null)
+        { }
+
+        public Result(Exception e) :
+            this(false, GetMessageListFromException(e))
+        { }
+
+        public Result(IResult result) : this(result.Success, result.Entity, result.EntityType, result.Messages)
+        { }
+
+        public static List<IMessage> GetMessageListFromException(Exception e)
+        {
+            List<IMessage> messageList = new List<IMessage>();
+
+            if (e.InnerException != null)
+                messageList.AddRange(GetMessageListFromException(e.InnerException));
+
+            messageList.Add(GetMessageFromException(e));
+
+            return messageList;
+        }
+
+        public static IMessage GetMessageFromException(Exception e)
+        {
+            var message = new Message(MessageType.Exception, e.GetType().Name + ":" + e.Message);
+
+            return message;
+        }
+
+        public Result(bool success, object entity, Type entityType, List<IMessage> messages)
+        {
+            Success = success;
+
+            if (messages != null)
+                foreach (Message msg in messages)
+                {
+                    if (msg.MessageType == MessageType.Exception)
+                        IsException = true;
+
+                    Messages.Add(msg);
+                }
+
+            if (entity != null && entityType != null)
+            {
+                Entity = entity;
+                EntityType = entityType;
+            }
+
+        }
+
+        public T GetEntity<T>()
+        {
+            if (Entity != null && 
+                (Entity is T ||
+                Entity.GetType().IsAssignableFrom(typeof(T)) ||
+                Entity.GetType().GetInterfaces().Contains(typeof(T))))
+                return (T)Entity;
+            return default(T);
+        }
+        
+        public override string ToString()
+        {
+            string messageTxt = string.Empty;
+            for (int i = 0; i < Messages.Count; i++)
+                messageTxt += Messages[i].ToString() + " || ";
+
+            string entityTxt = string.Empty;
+            if (Entity != null)
+                entityTxt = Entity.ToString();
+
+            var txt =  $"Success: {Success}";
+            if (entityTxt != string.Empty)
+                txt += " | Entity: " + entityTxt;
+            if (messageTxt != string.Empty)
+                txt += " | Messages: " + messageTxt;
+            return txt;
+        }
+    }
+
+    public class Result<TEntity> : Result, IResult<TEntity>
+    {
+        [IgnoreDataMember]
+        public new TEntity Entity { get; private set; }
+        public Result(bool success) : this(success, default(TEntity), new List<IMessage>())
+        { }
+        public Result(bool success, TEntity entity) : this(success, entity, new List<IMessage>())
+        { }
+        public Result(bool success, IMessage message) : this(success, default(TEntity), new MessageCollection { message })
+        { }
+        public Result(bool success, List<IMessage> messages) : this(success, default(TEntity), messages)
+        { }
+        public Result(bool success, TEntity entity, IMessage message) : this(success, entity, new MessageCollection { message })
+        { }
+        public Result(Exception e) : base(e)
+        { }
+        public Result(IResult result) : base(result)
+        { }
+        public Result(bool success, TEntity entity, List<IMessage> messages) : base(success, entity, typeof(TEntity), messages)
+        {
+            Entity = entity;
+        }
+
+        public override string ToString()
+        {
+            return base.ToString();
+        }
+    }
+}
diff --git a/sdks/dotnet/basyx-core/BaSyx.Utils/ResultHandling/ResultTypes/OperationResult.cs b/sdks/dotnet/basyx-core/BaSyx.Utils/ResultHandling/ResultTypes/OperationResult.cs
new file mode 100644
index 0000000..b18b24e
--- /dev/null
+++ b/sdks/dotnet/basyx-core/BaSyx.Utils/ResultHandling/ResultTypes/OperationResult.cs
@@ -0,0 +1,28 @@
+/*******************************************************************************
+* Copyright (c) 2020 Robert Bosch GmbH
+* Author: Constantin Ziesche (constantin.ziesche@bosch.com)
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License 2.0 which is available at
+* http://www.eclipse.org/legal/epl-2.0
+*
+* SPDX-License-Identifier: EPL-2.0
+*******************************************************************************/
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace BaSyx.Utils.ResultHandling.ResultTypes
+{
+    public class OperationResult : Result
+    {
+        public OperationResult(bool success) : base(success)
+        { }
+        public OperationResult(Exception e) : base(e)
+        { }
+        public OperationResult(bool success, IMessage message) : base(success, message)
+        { }
+        public OperationResult(bool success, List<IMessage> messages) : base(success, messages)
+        { }
+    }
+}
diff --git a/sdks/dotnet/basyx-core/BaSyx.Utils/ResultHandling/Utils.cs b/sdks/dotnet/basyx-core/BaSyx.Utils/ResultHandling/Utils.cs
new file mode 100644
index 0000000..fc9be51
--- /dev/null
+++ b/sdks/dotnet/basyx-core/BaSyx.Utils/ResultHandling/Utils.cs
@@ -0,0 +1,103 @@
+/*******************************************************************************
+* Copyright (c) 2020 Robert Bosch GmbH
+* Author: Constantin Ziesche (constantin.ziesche@bosch.com)
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License 2.0 which is available at
+* http://www.eclipse.org/legal/epl-2.0
+*
+* SPDX-License-Identifier: EPL-2.0
+*******************************************************************************/
+using Microsoft.AspNetCore.Mvc;
+using System;
+using System.Diagnostics;
+using System.Net;
+using System.Threading;
+
+namespace BaSyx.Utils.ResultHandling
+{
+    public static class Utils
+    {
+        public static bool RetryUntilSuccessOrTimeout(Func<bool> task, TimeSpan timeout, TimeSpan pause)
+        {
+            if (pause.TotalMilliseconds < 0)
+            {
+                throw new ArgumentException("pause must be >= 0 milliseconds");
+            }
+            var stopwatch = Stopwatch.StartNew();
+            do
+            {
+                if (task())
+                    return true; 
+
+                Thread.Sleep((int)pause.TotalMilliseconds);
+            }
+            while (stopwatch.Elapsed < timeout);
+            return false;
+        }
+
+        public static bool TryParseStatusCode(IResult result, out int iHttpStatusCode)
+        {
+            try
+            {
+                bool success = false;
+                var msgs = result.Messages.FindAll(m => !string.IsNullOrEmpty(m.Code));
+                if (msgs != null && msgs.Count > 0)
+                    foreach (var msg in msgs)
+                    {
+                        success = Enum.TryParse(msg.Code, out HttpStatusCode httpStatusCode);
+                        if (success)
+                        {
+                            iHttpStatusCode = (int)httpStatusCode;
+                            return success;
+                        }
+                    }
+                iHttpStatusCode = (int)HttpStatusCode.BadRequest;
+                return success;
+            }
+            catch
+            {
+                iHttpStatusCode = (int)HttpStatusCode.BadRequest;
+                return false;
+            }
+        }
+
+        public static IActionResult EvaluateResult(IResult result, CrudOperation crud, string route = null)
+        {
+            if (result == null)
+                return new StatusCodeResult(502);
+
+            switch (crud)
+            {
+                case CrudOperation.Create:
+                    if (result.Success && result.Entity != null)
+                        return new CreatedResult(route, result.Entity);
+                    break;
+                case CrudOperation.Retrieve:
+                    if (result.Success && result.Entity != null)
+                        return new OkObjectResult(result.Entity);
+                    else
+                        return new NotFoundObjectResult(result);
+                case CrudOperation.Update:
+                    if (result.Success)
+                        return new OkObjectResult(result.Entity);
+                    break;
+                case CrudOperation.Delete:
+                    if (result.Success)
+                        return new NoContentResult();
+                    break;
+                default:
+                    return new BadRequestObjectResult(result);
+            }
+            return new BadRequestObjectResult(result);
+        }
+
+        public enum CrudOperation
+        {
+            Create,
+            Retrieve,
+            Update,
+            Delete
+        }
+    }
+}
diff --git a/sdks/dotnet/basyx-core/BaSyx.Utils/Security/ICredentials.cs b/sdks/dotnet/basyx-core/BaSyx.Utils/Security/ICredentials.cs
new file mode 100644
index 0000000..c61e27f
--- /dev/null
+++ b/sdks/dotnet/basyx-core/BaSyx.Utils/Security/ICredentials.cs
@@ -0,0 +1,20 @@
+/*******************************************************************************
+* Copyright (c) 2020 Robert Bosch GmbH
+* Author: Constantin Ziesche (constantin.ziesche@bosch.com)
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License 2.0 which is available at
+* http://www.eclipse.org/legal/epl-2.0
+*
+* SPDX-License-Identifier: EPL-2.0
+*******************************************************************************/
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace BaSyx.Utils.Security
+{
+    public interface ICredentials
+    {
+    }
+}
diff --git a/sdks/dotnet/basyx-core/BaSyx.Utils/Security/ISecurity.cs b/sdks/dotnet/basyx-core/BaSyx.Utils/Security/ISecurity.cs
new file mode 100644
index 0000000..4f33969
--- /dev/null
+++ b/sdks/dotnet/basyx-core/BaSyx.Utils/Security/ISecurity.cs
@@ -0,0 +1,20 @@
+/*******************************************************************************
+* Copyright (c) 2020 Robert Bosch GmbH
+* Author: Constantin Ziesche (constantin.ziesche@bosch.com)
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License 2.0 which is available at
+* http://www.eclipse.org/legal/epl-2.0
+*
+* SPDX-License-Identifier: EPL-2.0
+*******************************************************************************/
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace BaSyx.Utils.Security
+{
+    public interface ISecurity
+    {
+    }
+}
diff --git a/sdks/dotnet/basyx-core/BaSyx.Utils/Server/Http/SimpleLocalHttpServer.cs b/sdks/dotnet/basyx-core/BaSyx.Utils/Server/Http/SimpleLocalHttpServer.cs
new file mode 100644
index 0000000..9f537c5
--- /dev/null
+++ b/sdks/dotnet/basyx-core/BaSyx.Utils/Server/Http/SimpleLocalHttpServer.cs
@@ -0,0 +1,153 @@
+/*******************************************************************************
+* Copyright (c) 2020 Robert Bosch GmbH
+* Author: Constantin Ziesche (constantin.ziesche@bosch.com)
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License 2.0 which is available at
+* http://www.eclipse.org/legal/epl-2.0
+*
+* SPDX-License-Identifier: EPL-2.0
+*******************************************************************************/
+using NLog;
+using System;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.IO;
+using System.Net;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace BaSyx.Utils.Server.Http
+{
+    public class SimpleLocalHttpServer
+    {
+        private HttpListener listener;
+        private string _uriPrefix;
+
+        private CancellationTokenSource cancellationToken;
+        private Action<HttpListenerRequest> messageReception = null;
+        private Action<HttpListenerResponse> messageResponse = null;
+        private Action<HttpListenerContext> messageHandler = null;
+
+        private static Logger logger = LogManager.GetCurrentClassLogger();
+
+        public SimpleLocalHttpServer(string uriPrefix)
+        {
+            if (string.IsNullOrEmpty(uriPrefix))
+                throw new ArgumentNullException(nameof(uriPrefix));
+
+            if (!uriPrefix.EndsWith("/"))
+                _uriPrefix = uriPrefix + "/";
+            else
+                _uriPrefix = uriPrefix;
+        }
+
+
+        public void Start()
+        {
+            listener = new HttpListener();
+            listener.Prefixes.Add(_uriPrefix);
+            cancellationToken = new CancellationTokenSource();
+
+            if (!listener.IsListening)
+            {
+                listener.Start();
+
+                Task.Factory.StartNew(async () =>
+                {
+                    while (!cancellationToken.IsCancellationRequested)
+                        await Listen(listener);
+                }, cancellationToken.Token, TaskCreationOptions.LongRunning, TaskScheduler.Current);
+
+                logger.Info("Http-Listener started");
+            }
+        }
+
+        public void Start(Action<HttpListenerRequest> receiveMessageMethod)
+        {
+            messageReception = receiveMessageMethod;
+            Start();
+        }
+
+        public void Start(Action<HttpListenerRequest> receiveMessageMethod, Action<HttpListenerResponse> responseMessageMethod)
+        {
+            messageReception = receiveMessageMethod;
+            messageResponse = responseMessageMethod;
+            Start();
+        }
+
+        public void Start(Action<HttpListenerContext> messageHandlerMethod)
+        {
+            messageHandler = messageHandlerMethod;
+            Start();
+        }
+        private async Task Listen(HttpListener listener)
+        {
+            try
+            {
+                HttpListenerContext context = await listener.GetContextAsync();
+                if (messageHandler != null)
+                    messageHandler.Invoke(context);
+                else
+                {
+                    if (messageReception != null)
+                        messageReception.Invoke(context.Request);
+                    if (messageResponse != null)
+                        messageResponse.Invoke(context.Response);
+                }
+            }
+            catch (Exception e)
+            {
+                logger.Error(e, "Http-Listener Exception: " + e.Message);
+            }
+        }
+
+        public void Stop()
+        {
+            if (listener.IsListening)
+            {
+                cancellationToken.Cancel();
+                listener.Stop();
+                logger.Info("Http-Listener stopped");
+            }
+        }        
+
+        /// <summary>
+        /// Formats the entire response, e.g. suitable for a MessageBox
+        /// </summary>
+        /// <param name="request"></param>
+        /// <returns>Beautiful formatted response</returns>
+        public static string GetCompleteResponseAsString(HttpListenerRequest request)
+        {
+            StringBuilder sb = new StringBuilder();
+            sb.AppendLine("URI: " + request.Url.AbsoluteUri);
+            sb.AppendLine("-----------HEADER-----------");
+
+            NameValueCollection headers = request.Headers;
+            for (int i = 0; i < headers.Count; i++)
+            {
+                string key = headers.GetKey(i);
+                string value = headers.Get(i);
+                sb.AppendLine(key + " = " + value);
+            }
+
+            sb.AppendLine("---------HEADER-END--------");
+
+            sb.AppendLine("-----------BODY-----------");
+            string body = new StreamReader(request.InputStream).ReadToEnd();
+            sb.AppendLine(body);
+            sb.AppendLine("---------BODY-END--------");
+
+            return sb.ToString();
+        }
+
+        public static string GetResponseBodyAsString(HttpListenerRequest request)
+        {
+            string responseBody = null;
+            using (var stream = new StreamReader(request.InputStream))
+                responseBody = stream.ReadToEnd();
+            return responseBody;
+        }
+    }
+}
diff --git a/sdks/dotnet/basyx-core/BaSyx.Utils/Settings/DirectoryWatcher.cs b/sdks/dotnet/basyx-core/BaSyx.Utils/Settings/DirectoryWatcher.cs
new file mode 100644
index 0000000..9790ea6
--- /dev/null
+++ b/sdks/dotnet/basyx-core/BaSyx.Utils/Settings/DirectoryWatcher.cs
@@ -0,0 +1,65 @@
+/*******************************************************************************
+* Copyright (c) 2020 Robert Bosch GmbH
+* Author: Constantin Ziesche (constantin.ziesche@bosch.com)
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License 2.0 which is available at
+* http://www.eclipse.org/legal/epl-2.0
+*
+* SPDX-License-Identifier: EPL-2.0
+*******************************************************************************/
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+
+namespace BaSyx.Utils.Settings
+{
+    public class DirectoryWatcher
+    {
+        private readonly FileSystemWatcher fileSystemWatcher;
+        private readonly string directoryPath;
+
+        public delegate void DirectoryChanged(string fullPath);
+        private readonly DirectoryChanged DirectoryChangedHandler;
+
+        public DirectoryWatcher(string pathToDirectory, string filter, bool createIfNotExists, DirectoryChanged directoryChanged)
+        {
+            if (string.IsNullOrEmpty(pathToDirectory))
+                throw new ArgumentNullException("pathToDirectory");
+            else if (!Directory.Exists(pathToDirectory))
+            {
+                if (createIfNotExists)
+                    Directory.CreateDirectory(pathToDirectory);
+                else
+                    throw new InvalidOperationException(pathToDirectory + "does not exist");
+            }
+            directoryPath = pathToDirectory;
+            DirectoryChangedHandler = directoryChanged;
+
+            fileSystemWatcher = new FileSystemWatcher();
+            fileSystemWatcher.Path = pathToDirectory;
+            fileSystemWatcher.Filter = filter;
+            fileSystemWatcher.NotifyFilter = NotifyFilters.LastWrite;
+
+            fileSystemWatcher.Changed += new FileSystemEventHandler(OnChanged);
+
+            fileSystemWatcher.EnableRaisingEvents = true;
+        }
+
+        private void OnChanged(object sender, FileSystemEventArgs e)
+        {
+            Console.Out.WriteLine("File: " + e.FullPath + " " + e.ChangeType);
+            try
+            {
+                fileSystemWatcher.EnableRaisingEvents = false;
+                DirectoryChangedHandler(e.FullPath);
+            }
+            finally
+            {
+                fileSystemWatcher.EnableRaisingEvents = true;
+            }
+            
+        }
+    }
+}
diff --git a/sdks/dotnet/basyx-core/BaSyx.Utils/Settings/FileWatcher.cs b/sdks/dotnet/basyx-core/BaSyx.Utils/Settings/FileWatcher.cs
new file mode 100644
index 0000000..66125a4
--- /dev/null
+++ b/sdks/dotnet/basyx-core/BaSyx.Utils/Settings/FileWatcher.cs
@@ -0,0 +1,51 @@
+/*******************************************************************************
+* Copyright (c) 2020 Robert Bosch GmbH
+* Author: Constantin Ziesche (constantin.ziesche@bosch.com)
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License 2.0 which is available at
+* http://www.eclipse.org/legal/epl-2.0
+*
+* SPDX-License-Identifier: EPL-2.0
+*******************************************************************************/
+using System;
+using System.IO;
+
+namespace BaSyx.Utils.Settings
+{
+    public class FileWatcher
+    {
+        private readonly FileSystemWatcher fileSystemWatcher;
+        private readonly string filePath;
+
+        public delegate void FileChanged(string fullPath);
+        private readonly FileChanged FileChangedHandler;
+
+        public FileWatcher(string pathToFile, FileChanged fileChanged)
+        {
+            if (string.IsNullOrEmpty(pathToFile))
+                throw new ArgumentNullException("pathToFile");
+            else if (!File.Exists(pathToFile))
+                throw new InvalidOperationException(pathToFile + "does not exist");
+
+            filePath = pathToFile;
+            FileChangedHandler = fileChanged;
+
+            fileSystemWatcher = new FileSystemWatcher();
+            fileSystemWatcher.Path = Path.GetDirectoryName(pathToFile);
+            fileSystemWatcher.Filter = Path.GetFileName(pathToFile);
+            fileSystemWatcher.NotifyFilter = NotifyFilters.LastWrite;
+
+            fileSystemWatcher.Changed += new FileSystemEventHandler(OnChanged);
+
+            fileSystemWatcher.EnableRaisingEvents = true;
+        }
+
+        private void OnChanged(object sender, FileSystemEventArgs e)
+        {
+            Console.Out.WriteLine("File: " + e.FullPath + " " + e.ChangeType);
+            if (e.ChangeType == WatcherChangeTypes.Changed && filePath == e.FullPath)
+                FileChangedHandler(e.FullPath);
+        }
+    }
+}
diff --git a/sdks/dotnet/basyx-core/BaSyx.Utils/Settings/ISettings.cs b/sdks/dotnet/basyx-core/BaSyx.Utils/Settings/ISettings.cs
new file mode 100644
index 0000000..dd3aefa
--- /dev/null
+++ b/sdks/dotnet/basyx-core/BaSyx.Utils/Settings/ISettings.cs
@@ -0,0 +1,21 @@
+/*******************************************************************************
+* Copyright (c) 2020 Robert Bosch GmbH
+* Author: Constantin Ziesche (constantin.ziesche@bosch.com)
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License 2.0 which is available at
+* http://www.eclipse.org/legal/epl-2.0
+*
+* SPDX-License-Identifier: EPL-2.0
+*******************************************************************************/
+using System.Collections.Generic;
+
+namespace BaSyx.Utils.Settings
+{
+    public interface ISettings
+    {
+        string Name { get; }
+        string FilePath { get; set; }
+        Dictionary<string, string> Miscellaneous { get; set; }
+    }
+}
diff --git a/sdks/dotnet/basyx-core/BaSyx.Utils/Settings/ResourceChecker.cs b/sdks/dotnet/basyx-core/BaSyx.Utils/Settings/ResourceChecker.cs
new file mode 100644
index 0000000..805ab68
--- /dev/null
+++ b/sdks/dotnet/basyx-core/BaSyx.Utils/Settings/ResourceChecker.cs
@@ -0,0 +1,82 @@
+/*******************************************************************************
+* Copyright (c) 2020 Robert Bosch GmbH
+* Author: Constantin Ziesche (constantin.ziesche@bosch.com)
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License 2.0 which is available at
+* http://www.eclipse.org/legal/epl-2.0
+*
+* SPDX-License-Identifier: EPL-2.0
+*******************************************************************************/
+using NLog;
+using System;
+using System.IO;
+using System.Reflection;
+
+namespace BaSyx.Utils.Settings
+{
+    public static class ResourceChecker
+    {
+        private static Logger logger = LogManager.GetCurrentClassLogger();
+
+        /// <summary>
+        /// Checks whether a resource is available in the assembly
+        /// </summary>
+        /// <param name="resourceName">Name of the resource</param>
+        /// <param name="createFile">If true, writes the resource to a file in the current executing directory</param>
+        /// <returns>
+        /// true = Resource was found
+        /// false = Resource was not found
+        /// </returns>
+        public static bool CheckResourceAvailability(Assembly sourceAssembly, string nameSpace, string resourceName, bool createFile)
+        {
+            if (File.Exists(resourceName) ||
+                File.Exists(Path.Combine(Path.GetDirectoryName(Assembly.GetCallingAssembly().Location), resourceName)) ||
+                File.Exists(Path.Combine(Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory), resourceName)))
+            {
+                return true;
+            }
+            else if (createFile)
+            {
+                if (WriteEmbeddedRessourceToFile(sourceAssembly, nameSpace, resourceName, null))
+                    return true;
+                else
+                    return false;
+            }
+            else
+                return false;
+        }
+        /// <summary>
+        /// Writes an embedded resource to a file in the executing directory
+        /// </summary>
+        /// <param name="resourceName">Name of the embedded resourcre</param>
+        /// <returns>
+        /// true = Resource was written successfully
+        /// false = Resource was not written successfully
+        /// </returns>
+        public static bool WriteEmbeddedRessourceToFile(Assembly sourceAssembly, string nameSpace, string resourceName, string destinationFilename)
+        {
+            try
+            {
+                Stream configStream = sourceAssembly.GetManifestResourceStream(string.Join(".", nameSpace, resourceName));
+                if (configStream == null)
+                    throw new FileNotFoundException("Resource '" + resourceName + "' not found");
+
+                string filePath = string.IsNullOrEmpty(destinationFilename) ? Path.Combine(Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory), resourceName) : destinationFilename;
+
+                using (var fileStream = File.Create(filePath))
+                {
+                    configStream.Seek(0, SeekOrigin.Begin);
+                    configStream.CopyTo(fileStream);
+                }
+                return (true);
+            }
+            catch (Exception e)
+            {
+                logger.Error(e, "Error creating '" + resourceName + "' from embedded resource. Exception: " + e.ToString());
+                return (false);
+            }
+
+        }
+    }
+}
diff --git a/sdks/dotnet/basyx-core/BaSyx.Utils/Settings/Sections/ClientConfiguration.cs b/sdks/dotnet/basyx-core/BaSyx.Utils/Settings/Sections/ClientConfiguration.cs
new file mode 100644
index 0000000..cdefc0b
--- /dev/null
+++ b/sdks/dotnet/basyx-core/BaSyx.Utils/Settings/Sections/ClientConfiguration.cs
@@ -0,0 +1,25 @@
+/*******************************************************************************
+* Copyright (c) 2020 Robert Bosch GmbH
+* Author: Constantin Ziesche (constantin.ziesche@bosch.com)
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License 2.0 which is available at
+* http://www.eclipse.org/legal/epl-2.0
+*
+* SPDX-License-Identifier: EPL-2.0
+*******************************************************************************/
+using System;
+using System.Xml;
+using System.Xml.Serialization;
+
+namespace BaSyx.Utils.Settings.Sections
+{
+        
+        public class ClientConfiguration
+        {
+            [XmlElement]
+            public string ClientId { get; set; }
+            [XmlElement]
+            public string Endpoint { get; set; }         
+        }
+}
diff --git a/sdks/dotnet/basyx-core/BaSyx.Utils/Settings/Sections/PathConfiguration.cs b/sdks/dotnet/basyx-core/BaSyx.Utils/Settings/Sections/PathConfiguration.cs
new file mode 100644
index 0000000..a84cb57
--- /dev/null
+++ b/sdks/dotnet/basyx-core/BaSyx.Utils/Settings/Sections/PathConfiguration.cs
@@ -0,0 +1,33 @@
+/*******************************************************************************
+* Copyright (c) 2020 Robert Bosch GmbH
+* Author: Constantin Ziesche (constantin.ziesche@bosch.com)
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License 2.0 which is available at
+* http://www.eclipse.org/legal/epl-2.0
+*
+* SPDX-License-Identifier: EPL-2.0
+*******************************************************************************/
+using System;
+using System.Xml;
+using System.Xml.Serialization;
+
+namespace BaSyx.Utils.Settings.Sections
+{
+    
+    public class PathConfiguration
+    {
+        [XmlElement]
+        public string Host { get; set; }
+        [XmlElement]
+        public string BasePath { get; set; }
+        [XmlElement]
+        public string ServicePath { get; set; }
+        [XmlElement]
+        public string AggregatePath { get; set; }
+        [XmlElement]
+        public string EntityPath { get; set; }
+        [XmlElement]
+        public string EntityId { get; set; }
+    }
+}
diff --git a/sdks/dotnet/basyx-core/BaSyx.Utils/Settings/Sections/ProxyConfiguration.cs b/sdks/dotnet/basyx-core/BaSyx.Utils/Settings/Sections/ProxyConfiguration.cs
new file mode 100644
index 0000000..be83617
--- /dev/null
+++ b/sdks/dotnet/basyx-core/BaSyx.Utils/Settings/Sections/ProxyConfiguration.cs
@@ -0,0 +1,31 @@
+/*******************************************************************************
+* Copyright (c) 2020 Robert Bosch GmbH
+* Author: Constantin Ziesche (constantin.ziesche@bosch.com)
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License 2.0 which is available at
+* http://www.eclipse.org/legal/epl-2.0
+*
+* SPDX-License-Identifier: EPL-2.0
+*******************************************************************************/
+using System;
+using System.Xml;
+using System.Xml.Serialization;
+
+namespace BaSyx.Utils.Settings.Sections
+{
+    
+    public class ProxyConfiguration
+    {
+        [XmlElement]
+        public bool UseProxy { get; set; }
+        [XmlElement]
+        public string ProxyAddress { get; set; }
+        [XmlElement]
+        public string Domain { get; set; }
+        [XmlElement]
+        public string UserName { get; set; }
+        [XmlElement]
+        public string Password { get; set; }
+    }
+}
diff --git a/sdks/dotnet/basyx-core/BaSyx.Utils/Settings/Sections/ServerConfiguration.cs b/sdks/dotnet/basyx-core/BaSyx.Utils/Settings/Sections/ServerConfiguration.cs
new file mode 100644
index 0000000..9a0b807
--- /dev/null
+++ b/sdks/dotnet/basyx-core/BaSyx.Utils/Settings/Sections/ServerConfiguration.cs
@@ -0,0 +1,49 @@
+/*******************************************************************************
+* Copyright (c) 2020 Robert Bosch GmbH
+* Author: Constantin Ziesche (constantin.ziesche@bosch.com)
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License 2.0 which is available at
+* http://www.eclipse.org/legal/epl-2.0
+*
+* SPDX-License-Identifier: EPL-2.0
+*******************************************************************************/
+using System;
+using System.Collections.Generic;
+using System.Xml;
+using System.Xml.Serialization;
+
+namespace BaSyx.Utils.Settings.Sections
+{
+    
+    public class ServerConfiguration
+    {
+        [XmlElement]
+        public string ServerId { get; set; }
+        [XmlElement]
+        public HostingConfiguration Hosting { get; set; }
+        [XmlElement]
+        public string DefaultRoute { get; set; }
+
+        public ServerConfiguration()
+        {
+            Hosting = new HostingConfiguration();
+        }
+    }
+
+    
+    public class HostingConfiguration
+    {
+        [XmlElement]
+        public string Environment { get; set; }
+        [XmlArrayItem("Url")]
+        public List<string> Urls { get; set; }
+        [XmlElement]
+        public string ContentPath { get; set; }
+
+        public HostingConfiguration()
+        {
+            Urls = new List<string>();
+        }
+    }
+}
diff --git a/sdks/dotnet/basyx-core/BaSyx.Utils/Settings/ServiceType.cs b/sdks/dotnet/basyx-core/BaSyx.Utils/Settings/ServiceType.cs
new file mode 100644
index 0000000..a967d37
--- /dev/null
+++ b/sdks/dotnet/basyx-core/BaSyx.Utils/Settings/ServiceType.cs
@@ -0,0 +1,20 @@
+/*******************************************************************************
+* Copyright (c) 2020 Robert Bosch GmbH
+* Author: Constantin Ziesche (constantin.ziesche@bosch.com)
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License 2.0 which is available at
+* http://www.eclipse.org/legal/epl-2.0
+*
+* SPDX-License-Identifier: EPL-2.0
+*******************************************************************************/
+namespace BaSyx.Utils.Settings
+{
+    public enum ServiceType
+    {
+        None,
+        Server,
+        Client,
+        Both
+    }
+}
diff --git a/sdks/dotnet/basyx-core/BaSyx.Utils/Settings/Settings.cs b/sdks/dotnet/basyx-core/BaSyx.Utils/Settings/Settings.cs
new file mode 100644
index 0000000..be55b47
--- /dev/null
+++ b/sdks/dotnet/basyx-core/BaSyx.Utils/Settings/Settings.cs
@@ -0,0 +1,218 @@
+/*******************************************************************************
+* Copyright (c) 2020 Robert Bosch GmbH
+* Author: Constantin Ziesche (constantin.ziesche@bosch.com)
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License 2.0 which is available at
+* http://www.eclipse.org/legal/epl-2.0
+*
+* SPDX-License-Identifier: EPL-2.0
+*******************************************************************************/
+using BaSyx.Utils.AssemblyHandling;
+using BaSyx.Utils.Settings.Sections;
+using Newtonsoft.Json;
+using NLog;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Xml;
+using System.Xml.Linq;
+using System.Xml.Serialization;
+using XSerializer;
+using static BaSyx.Utils.Settings.FileWatcher;
+
+namespace BaSyx.Utils.Settings
+{
+
+    public static class SettingsExtensions
+    {
+        public static T As<T>(this Settings settings) where T : Settings
+        {
+            return settings as T;
+        }
+    }
+
+    public abstract class Settings : ISettings
+    {
+        [XmlIgnore]
+        public string Name => this.GetType().Name;
+        [XmlIgnore]
+        public string FilePath { get; set; }
+        [XmlIgnore]
+        public Dictionary<string, string> Miscellaneous { get; set; }
+
+        [XmlElement]
+        public ServiceType OperationMode { get; set; }
+        [XmlElement(IsNullable = true)]
+        public ServerConfiguration ServerConfig { get; set; } = new ServerConfiguration();
+        [XmlElement(IsNullable = true)]
+        public ClientConfiguration ClientConfig { get; set; } = new ClientConfiguration();
+        [XmlElement(IsNullable = true)]
+        public PathConfiguration PathConfig { get; set; } = new PathConfiguration();
+        [XmlElement(IsNullable = true)]
+        public ProxyConfiguration ProxyConfig { get; set; } = new ProxyConfiguration();
+
+        public static string ExecutingDirectory => AppDomain.CurrentDomain.BaseDirectory;//=> Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
+
+        public const string FileExtension = ".xml";
+        public const string MiscellaneousConfig = "Miscellaneous";
+
+        public static SettingsCollection SettingsCollection { get; }
+
+        private static readonly Logger logger = LogManager.GetCurrentClassLogger();
+        private FileWatcher fileWatcher;
+
+        static Settings()
+        {
+            SettingsCollection = new SettingsCollection();
+            string[] files = Directory.GetFiles(ExecutingDirectory, "*Settings.xml", SearchOption.TopDirectoryOnly);
+            if(files?.Length > 0)
+            {
+                List<Assembly> assemblies = AssemblyUtils.GetLoadedAssemblies();
+               
+                for (int i = 0; i < files.Length; i++)
+                {
+                    try
+                    {
+                        XDocument doc = XDocument.Load(files[i]);
+                        string rootName = doc.Root.Name.LocalName;
+                        Type settingsType = assemblies
+                            .SelectMany(a => a.GetTypes())
+                            .Where(t => t.Name == rootName)?
+                            .FirstOrDefault();
+
+                        if (settingsType != null)
+                        {
+                            Settings setting = LoadSettingsFromFile(files[i], settingsType);
+                            if (setting != null)
+                                SettingsCollection.Add(setting);
+                        }
+                        else
+                            logger.Info("Cannot load settings of type: " + rootName + " because type is either never used or not referenced");
+                    }
+                    catch (Exception e)
+                    {
+                        logger.Warn(e, "Cannot load settings file: " + files[i]);
+                    }
+                }
+
+            }
+        }
+
+        protected Settings()
+        {
+            Miscellaneous = new Dictionary<string, string>();
+        }
+
+        public virtual void ConfigureSettingsWatcher(string settingsFilePath, FileChanged settingsFileChangedHandler)
+        {
+            fileWatcher = new FileWatcher(settingsFilePath, settingsFileChangedHandler);
+        }
+
+       
+
+        public static Settings LoadSettingsFromFile(string filePath, Type settingsType)
+        {
+            if (string.IsNullOrEmpty(filePath) || !File.Exists(filePath))
+            {
+                logger.Warn("Settings file does not exist: " + filePath);
+                return null;
+            }
+
+            try
+            {
+                Settings settings = null;
+
+                IXSerializer serializer = XSerializer.XmlSerializer.Create(settingsType);
+                string settingsXml = File.ReadAllText(filePath);
+
+                settings = (Settings)serializer.Deserialize(settingsXml);
+
+                if (settings != null)
+                {
+                    var miscElement = XElement.Load(filePath).Element(MiscellaneousConfig);
+                    if (miscElement != null)
+                        settings.Miscellaneous = miscElement.Elements().Where(e => !e.HasElements).ToDictionary(e => e.Name.LocalName, e => e.Value);
+
+                    settings.FilePath = filePath;
+
+                    if(logger.IsDebugEnabled)
+                        logger.Debug("Settings loaded: " + JsonConvert.SerializeObject(settings, Newtonsoft.Json.Formatting.Indented));
+
+                    return settings;
+                }
+                logger.Warn("No settings of Type " + settingsType.Name + " loaded: " + filePath);
+                return null;
+
+            }
+            catch (Exception e)
+            {
+                logger.Error(e, "Could not load " + filePath);
+                return null;
+            }
+        } 
+        
+        public static T LoadSettingsFromFile<T>(string filePath) where T : Settings, new()
+        {
+            return (T)LoadSettingsFromFile(filePath, typeof(T));
+        }
+
+        public static T LoadSettingsByName<T>(string name) where T : Settings
+        {
+            Settings settings = SettingsCollection.Find(s => s.Name == typeof(T).Name);
+            if (settings != null)
+                return (T)settings;
+            return null;
+        }
+
+        public void SaveSettings(string filePath, Type settingsType)
+        {
+            try
+            {
+                IXSerializer serializer = XSerializer.XmlSerializer.Create(settingsType);
+                string settingsXmlContent = serializer.Serialize(this);
+                File.WriteAllText(filePath, settingsXmlContent);
+
+                logger.Info("Settings saved: " + filePath);
+            }
+            catch (Exception e)
+            {
+                logger.Error(e, "Could not serialize to " + filePath);
+            }
+        }
+    }
+
+    public abstract class Settings<T> : Settings where T : Settings, new()
+    {
+        private static Logger logger = LogManager.GetCurrentClassLogger();
+        public static string FileName => typeof(T).Name + FileExtension;
+
+     
+        public Settings() : base()
+        { }
+
+        public static T CreateSettings() => new T();
+       
+        public void SaveSettings() => SaveSettings(FilePath);
+
+        public void SaveSettings(string filePath) => SaveSettings(filePath, typeof(T));          
+
+        public static T LoadSettings()
+        {
+            Settings settings = LoadSettingsByName(typeof(T).Name);
+            if (settings == null)
+            {
+                string settingsFilePath = Path.Combine(ExecutingDirectory, FileName);
+                settings = LoadSettingsFromFile(settingsFilePath);
+            }
+            if(settings != null)
+                return (T)settings;
+            return null;
+        }
+
+        public static T LoadSettingsByName(string name) => LoadSettingsByName<T>(name);
+        public static T LoadSettingsFromFile(string filePath) => LoadSettingsFromFile<T>(filePath);
+    }
+}
diff --git a/sdks/dotnet/basyx-core/BaSyx.Utils/Settings/SettingsCollection.cs b/sdks/dotnet/basyx-core/BaSyx.Utils/Settings/SettingsCollection.cs
new file mode 100644
index 0000000..81114e9
--- /dev/null
+++ b/sdks/dotnet/basyx-core/BaSyx.Utils/Settings/SettingsCollection.cs
@@ -0,0 +1,26 @@
+/*******************************************************************************
+* Copyright (c) 2020 Robert Bosch GmbH
+* Author: Constantin Ziesche (constantin.ziesche@bosch.com)
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License 2.0 which is available at
+* http://www.eclipse.org/legal/epl-2.0
+*
+* SPDX-License-Identifier: EPL-2.0
+*******************************************************************************/
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace BaSyx.Utils.Settings
+{
+    public class SettingsCollection : List<Settings>
+    {
+        public Settings this[string name] => this.Find(e => e.Name == name);
+
+        public T GetSettings<T>(string name) where T : Settings
+        {
+            return (T)this[name];
+        }
+    }
+}
diff --git a/sdks/dotnet/basyx-core/BaSyx.Utils/Settings/Types/DependencySettings.cs b/sdks/dotnet/basyx-core/BaSyx.Utils/Settings/Types/DependencySettings.cs
new file mode 100644
index 0000000..9a04b90
--- /dev/null
+++ b/sdks/dotnet/basyx-core/BaSyx.Utils/Settings/Types/DependencySettings.cs
@@ -0,0 +1,99 @@
+/*******************************************************************************
+* Copyright (c) 2020 Robert Bosch GmbH
+* Author: Constantin Ziesche (constantin.ziesche@bosch.com)
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License 2.0 which is available at
+* http://www.eclipse.org/legal/epl-2.0
+*
+* SPDX-License-Identifier: EPL-2.0
+*******************************************************************************/
+using BaSyx.Utils.AssemblyHandling;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.DependencyInjection.Extensions;
+using NLog;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Reflection;
+using System.Xml.Serialization;
+
+namespace BaSyx.Utils.Settings.Types
+{
+    public class DependencySettings : Settings<DependencySettings>
+    {
+        private static Logger logger = LogManager.GetCurrentClassLogger();
+
+        public DependencyConfiguration DependencyCollection { get; set; } = new DependencyConfiguration();
+
+
+       
+        public class DependencyConfiguration
+        {
+            [XmlArrayItem("Dependency")]
+            public List<Dependency> Dependencies { get; set; } = new List<Dependency>();
+        }
+
+        public class Dependency
+        {
+            [XmlElement]
+            public string DllPath { get; set; }
+            [XmlElement]
+            public string InterfaceType { get; set; }
+            [XmlElement]
+            public string ImplementationType { get; set; }
+            [XmlElement]
+            public ServiceLifetime ServiceLifetime { get; set; }
+        }
+      
+        public IServiceCollection GetServiceCollection(List<Assembly> externalAssemblies = null)
+        {
+            List<Assembly> assemblies = externalAssemblies ?? AssemblyUtils.GetLoadedAssemblies();
+           
+            if (DependencyCollection?.Dependencies?.Count > 0)
+            {
+                ServiceCollection serviceCollection = new ServiceCollection();
+                foreach (var dependency in DependencyCollection.Dependencies)
+                {
+                    string dllPath = Path.Combine(Settings.ExecutingDirectory, dependency.DllPath);
+                    if(!string.IsNullOrEmpty(dependency.DllPath) && File.Exists(dllPath))
+                    {
+                        try
+                        {
+                            Assembly assembly = Assembly.LoadFrom(dllPath);
+                            if (!assemblies.Contains(assembly))
+                                assemblies.Add(assembly);
+                        }
+                        catch (Exception e)
+                        {
+                            logger.Error(e, "Failed to load assembly " + dllPath);
+                        }
+                     
+                    }
+
+
+                    try
+                    {
+                        Type interfaceType = assemblies.Find(a => a.GetType(dependency.InterfaceType, false) != null)?.GetType(dependency.InterfaceType);
+                        if (interfaceType == null)
+                            throw new DllNotFoundException("Dll not found for interfaceType");
+
+                        Type implementationType = assemblies.Find(a => a.GetType(dependency.ImplementationType, false) != null)?.GetType(dependency.ImplementationType);
+                        if (implementationType == null)
+                            throw new DllNotFoundException("Dll not found for implementationType");
+                        ServiceDescriptor serviceDescriptor = new ServiceDescriptor(interfaceType, implementationType, dependency.ServiceLifetime);
+                        serviceCollection.Add(serviceDescriptor);
+                    }
+                    catch (Exception e)
+                    {
+                        logger.Error(e, "Failed to load dependency " + dependency.ImplementationType + " for interface: " + dependency.InterfaceType);
+                        continue;
+                    }
+                }
+                return serviceCollection;
+            }
+            return null;
+        }
+
+    }
+}
diff --git a/sdks/dotnet/basyx-core/BaSyx.Utils/Settings/Types/ServerSettings.cs b/sdks/dotnet/basyx-core/BaSyx.Utils/Settings/Types/ServerSettings.cs
new file mode 100644
index 0000000..6fad282
--- /dev/null
+++ b/sdks/dotnet/basyx-core/BaSyx.Utils/Settings/Types/ServerSettings.cs
@@ -0,0 +1,29 @@
+/*******************************************************************************
+* Copyright (c) 2020 Robert Bosch GmbH
+* Author: Constantin Ziesche (constantin.ziesche@bosch.com)
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License 2.0 which is available at
+* http://www.eclipse.org/legal/epl-2.0
+*
+* SPDX-License-Identifier: EPL-2.0
+*******************************************************************************/
+using System;
+using System.Xml.Serialization;
+
+namespace BaSyx.Utils.Settings.Types
+{
+    public class ServerSettings : Settings<ServerSettings>
+    {
+        public RegistryConfiguration RegistryConfig { get; set; } = new RegistryConfiguration();
+       
+        public class RegistryConfiguration
+        {
+            [XmlElement]
+            public bool Activated { get; set; }
+            [XmlElement]
+            public string RegistryUrl { get; set; }
+        }
+
+    }
+}
diff --git a/sdks/dotnet/basyx-core/BaSyx.Utils/StringOperations/StringOperations.cs b/sdks/dotnet/basyx-core/BaSyx.Utils/StringOperations/StringOperations.cs
new file mode 100644
index 0000000..db243e0
--- /dev/null
+++ b/sdks/dotnet/basyx-core/BaSyx.Utils/StringOperations/StringOperations.cs
@@ -0,0 +1,49 @@
+/*******************************************************************************
+* Copyright (c) 2020 Robert Bosch GmbH
+* Author: Constantin Ziesche (constantin.ziesche@bosch.com)
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License 2.0 which is available at
+* http://www.eclipse.org/legal/epl-2.0
+*
+* SPDX-License-Identifier: EPL-2.0
+*******************************************************************************/
+using System;
+
+namespace BaSyx.Utils.StringOperations
+{
+    public static class StringOperations
+    {
+        public static string GetValueOrStringEmpty<T>(T? nullable) where T : struct
+        {
+            if (nullable != null)
+            {
+                var value = Nullable.GetUnderlyingType(nullable.GetType());
+                if (value != null && value.IsEnum)
+                    Enum.GetName(Nullable.GetUnderlyingType(nullable.GetType()), nullable.Value);
+                else
+                    return nullable.Value.ToString();
+            }
+            return string.Empty;
+        }
+
+        public static string UppercaseFirst(this string s)
+        {
+            if (string.IsNullOrEmpty(s))
+            {
+                return string.Empty;
+            }
+            return char.ToUpper(s[0]) + s.Substring(1);
+        }
+
+        public static string LowercaseFirst(this string s)
+        {
+            if (string.IsNullOrEmpty(s))
+            {
+                return string.Empty;
+            }
+            return char.ToLower(s[0]) + s.Substring(1);
+        }
+
+    }
+}
diff --git a/sdks/dotnet/basyx-core/BaSyx.Utils/basyxlogo.png b/sdks/dotnet/basyx-core/BaSyx.Utils/basyxlogo.png
new file mode 100644
index 0000000..226a4ff
--- /dev/null
+++ b/sdks/dotnet/basyx-core/BaSyx.Utils/basyxlogo.png
Binary files differ