SharePoint Addins mit eigener config Datei

SharePoint AddIns: Eigene Konfiguration & DLLs effizient verwalten
03/2020
Michael F. | Solution Engineer

TL;DR

Der Artikel zeigt, wie SharePoint Addins mit eigener Konfigurationsdatei in .NET geladen werden und wie mittels PrivatePath-Probing Assemblies in Unterverzeichnissen korrekt aufgelöst werden.

Dynamische Konfiguration von DLLs

In einer .NET-Anwendung, die über die AddIn-Technologie mehrere DLLs dynamisch lädt, benötigen SharePoint Addins mit eigener Config Datei häufig separate Konfigurationsdaten für eine saubere und entkoppelte Konfiguration. Da AddIns von der Hauptanwendung entkoppelt sind, dürfen diese Daten nicht in der App.config hinterlegt werden. Die Konfigurationssektion wird im AddIn selbst definiert – was beim Laden der App.config zu einer Exception führen kann, wenn die entsprechende Assembly in einem Unterverzeichnis liegt und nicht gefunden wird.

Programmstruktur

Eine Anwendung mit einem separaten AddIn-Verzeichnis, das die AddIn-DLLs und die entsprechenden Konfigurationsdateien enthält (hier im Beispiel mit nur einem einzigen AddIn – „AddInRoutinen“).

Visual Studio Projektstruktur mit AddInHandling, AddInRoutinen-DLLs und Debug-Ausgabeverzeichnis im Explorer

Durchführung

Gehen wir davon aus, dass das AddIn eine eigene Konfigurationsdatei besitzt. Darin ist eine Sektion für die eigentlichen Daten definiert. Nachfolgend wird exemplarisch eine entsprechende Konfigurationsdatei und die Klassendefinition der Section dargestellt. Auf die entsprechenden Attribute zur Beschreibung der ConfigurationProperties sowie der zu verwendenden Basisklassen wird an dieser Stelle nicht näher eingegangen.

Konfigurationsdatei der AddIn-DLL mit Definition einer eigenen Section

1<configuration>
2  <configSections>
3    <section name="routine1Settings"
4             type="AddInRoutinen.Routine1Settings, AddInRoutinen, 
5                   Version=1.0.0.0, Culture=neutral, PublicKeyToken=..." />
6  </configSections>
7
8  <routine1Settings>
9    <serviceParams name="dummy1" setting="test" />
10  </routine1Settings>
11
12  ...
13</configuration>

Die Klasse Routine1Settings ist wie folgt definiert:

1namespace AddInRoutinen
2{
3    public class Routine1Settings : ConfigurationSection
4    {
5        [ConfigurationProperty("serviceParams")]
6        public ServiceParams BeispielServiceParams
7        {
8            get { return (ServiceParams)this["serviceParams"]; }
9            set { this["serviceParams"] = value; }
10        }
11    }
12
13    public class ServiceParams : ConfigurationElement
14    {
15        [ConfigurationProperty("setting", DefaultValue = 1, IsRequired = false)]
16        public int Setting
17        {
18            get { return (int)this["setting"]; }
19            set { this["setting"] = value; }
20        }
21
22        [ConfigurationProperty("name", IsRequired = true)]
23        public string Name
24        {
25            get { return (string)this["name"]; }
26            set { this["name"] = value; }
27        }
28    }
29}

In der AddIn-Routine kann die Datei AddInRoutinen.dll.config mit dem folgenden Codeschnipsel geladen und die Daten der Section ermittelt werden.

1ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
2fileMap.ExeConfigFilename = "AddInRoutinen.dll.config";
3
4Configuration config = ConfigurationManager
5    .OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
6
7Routine1Settings settings = config.GetSection("routine1Settings") as Routine1Settings;

Das Ganze funktioniert auch, solange das AddIn-Assembly und die AddIn.config im selben Verzeichnis wie die Exe der Anwendung liegen. Anders verhält es sich jedoch, wenn ein separater Unterordner für die AddIns existiert. Dies ist besonders sinnvoll, um die AddIns vom eigentlichen Programm zu separieren, sodass die Anwendung nur in diesem Verzeichnis nach den entsprechenden Interfaces sucht.

Das benötigte Assembly zur Deserialisierung der Section wird nur gefunden, wenn in der Konfigurationsdatei der Anwendung (nicht in der AddInRoutinen.config) ein entsprechender Runtime-Verweis mit der Angabe eines PrivatePath vorhanden ist. Standardmäßig sucht das ausführende Programm nur im eigenen Programmordner und im Assembly-Cache. Mit der PrivatePath-Angabe können mehrere Unterordner im Programmverzeichnis durch Kommas getrennt angegeben werden, die ebenfalls nach dem erforderlichen Assembly durchsucht werden sollen.

Benötigter Eintrag in der Konfigurationsdatei des ausführenden Programms

1<configuration>
2  ...
3  <runtime>
4    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
5      <probing privatePath="AddIns" />
6    </assemblyBinding>
7  </runtime>
8  ...
9</configuration>

Eine kleine Ergänzung in der Konfiguration der Anwendung ermöglicht die korrekte Funktionsweise mit separaten Konfigurationsdateien (und Section). Das „Probing“-Element wird leider nicht von IntelliSense vorgeschlagen. Wichtig ist hierbei auch der korrekte Namespace im xmlns-Attribut.

Foto von Michael
Michael F. | Solution Engineer

Mehr zum Thema

Pfeil nach rechts (Verlinkung)
.NET-Ökosystem erklärt: Plattform, SDK, Core, C#, NuGet, Azure und DevOps kompakt und verständlich im Überblick für Entwicklerinnen und Entwickler.
07/2026

.NET: Framework, Plattform, Core? Was steckt eigentlich hinter dem Microsoft-Ökosystem?

Blauer Pfeil nach rechts (Verlinkung)
Microsoft Graph über Power Automate mit Anwendungs-Berechtigungen: Benutzerunabhängige Automatisierung von Office 365 über Azure App Registrierung.
01/2026

Microsoft Graph mit Power Automate & Berechtigungen

Blauer Pfeil nach rechts (Verlinkung)
Business-Central-Webservice in der Praxis: Authentifizierung mit C# sicher umsetzen – Windows Auth, Basic Auth und OAuth2 im Vergleich.
12/2025

Business-Central-Webservice: Authentifizierung in C#

Blauer Pfeil nach rechts (Verlinkung)
Microservices vs. modularer Monolith: Vergleich moderner .NET-Architekturen mit Praxisbeispielen und Entscheidungshilfe für skalierbare Software.
11/2025

Microservices vs. Modularer Monolith Architektur

Blauer Pfeil nach rechts (Verlinkung)