Laden...
Avatar #avatar-4119.png
Abt myCSharp.de - Team
Principal Software Engineer Dabei seit 20.07.2008 16.792 Beiträge
Benutzerbeschreibung
Als Principal Software Engineer berate und unterstütze in Form von Entwicklungsleistung aktiv Projekte und Unternehmen in Sachen technischer Zukunft mit dem Fokus auf auf .NET und hoch-moderne Web-Anwendungen/-Landschaften in der Cloud. Ich präsentiere die Technologien von Morgen und helfe bei der Analyse der korrekten Strategie und Methodiken für die Umsetzung. Neben meinem Tech-Blog SCHWABENCODE.com bin ich seit 2011 in exekutiver Funktion dieses Forums tätig, schreibe Artikel und halte ab und zu Vorträge in kleineren Runden zum Thema Cloud, Web-Development und IoT. Seit 2015 wurde ich jedes Jahr zum Microsoft MVP für (.NET / Azure) ernannt.

Forenbeiträge von Abt Ingesamt 16.792 Beiträge

18.03.2024 - 14:59 Uhr

Situation ist egal: Du hast beim Abschicken keinen Zugriff aud den Handler oder dessen Logik. Der Handler wird intern vom Client gecalled, wenn die Operation ausgeführt wird. Deswegen registriert man den Handler.

Sollen Deine Request isoliert sein / willste Zeugs aus anderen Requests vergessen: HttpRequestMessage verwenden.
Da kannst auch Cookies einzeln setzen / löschen / resetten etc etc etc.. Der Handler ist für Deine Situation nicht wirklich so gedacht.

18.03.2024 - 14:33 Uhr

Bist Du Dir sicher? So wrappt man eigentlich keine HTTP API. Weder als Client-Wrapper noch als Provider-Umsetzung.

Deshalb muss ich irgendwie allein von der HttpClientInstanz aus auf den CookieContainerzugreifen.

So funktioniert das Prinzip jeglicher Handler aber nicht; auch hier nicht. Ein Handler wird bei der Ausführung der Operation (zB Send) gecallt - nicht davor.
Du hast hier keine direkte Zugriffsmöglichkeit. Vielleicht, ohne es zu wissen, vielleicht über Reflection. Aber ich bin mir sicher, dass Du den falschen Weg verfolgst, wenn Du das brauchen solltest.

17.03.2024 - 22:07 Uhr

Willst Du jeden Request individuell konfigurieren, so verwende die HttpRequestMessage-Methoden. Dort kannst Du entsprechend auch den Header anpassen.

Der Handler ist explizit für das generelle Handling der Instanz.

05.03.2024 - 14:43 Uhr

Der Domain Layer ist aber nicht die Logik, sondern eben die Domäne. Das gleiche wie ich oben beschrieben hab.

Dein Bild ist im Endeffekt die kleinste Ausbaustufe für die Basis einer 3-Tier-Architektur. Ein "großen Produktservice" würde man in modernen Architekturen jedoch eher nicht mehr machen. Wird zu oft zu einer großen, unwartbaren monolithischen Klasse. Sofern der UserContext das Ding von EF ist - gehört auch das zum DAL.

Und ja: Deine Logik kennt die Datenschicht - nicht umgekehrt.

02.03.2024 - 18:35 Uhr

Zitat von Th69

Die Assembly ist aber wohl eingebunden (wie man im Bild beim Projektmappen-Explorer sieht).

Das hab ich übersehen, aber was man sieht ist, dass es sich um ein .NET Framework Projekt handelt.
Nur bei .NET Fx Projekten siehst Du heute alle die References aka "Verweise" auf diese Art. Bei .NET 5+ heisst das in VS Dependencies bzw. "Abhängigkeiten". Diese Darstellung der Verweise sind reine GAC-Verweise.

Das wird vermutlich auch das Problem sein: die Version im GAC kennt einfach keine Pipeline, weil sie veraltet ist. Auch hier gilt: Verweis entfernen und NuGet verwenden.

Und: von .NET Framework auf .NET 6+ wechseln (aktuell ist 8).

02.03.2024 - 18:27 Uhr

Zitat von ill_son

Das Buch heißt "Dependency Injection Principles, practices and patterns" von Mark Seemann.

Ich kenn das Buch, das steht da nicht drin. Das hast falsch rum verstanden.
Wie Th69 schreibt geht das auch gar nicht.

02.03.2024 - 00:30 Uhr

Zitat von mmair07

Das Hosten direkt übers Web fällt aus, da die App auch ohne Internet funktionieren muss.

Im referenzierten Link steht das auch nicht anders.

Leider gibt es so nur schwierig Alternativen, da wir einfach an eine Rahmenanwendung gebunden sind, die mit .Net Framework 4.x läuft und das auch so bleiben wird.

Was meinst Du, Side by Side oder was ist der Issue? Du kannst moderne .NET Applikationen (nicht .NET Framework) mit eingebetteter Runtime ausliefern, sodass völlig egal is, was auf der Zielmaschine läuft. Das .NET Fx bleibt unberührt.

auf allen Plattformen lief EmbedIO Reibungslos, bis auf IOS.

Wenn Du nicht sagst, was "läuft nicht" bedeutet, kann Dir niemand helfen. Niemand kann hellsehen.
Einfach mal den Fehler beschreiben oder bei EmbedIO nachschauen, ob jemand den Fehler schon mal hatte). Es ist eher nicht wahrscheinlich jemand zweites auf Anhieb mit Deiner Situation von EmbedIO und MAUI zu finden.

Es soll einfach eine Alternative gefunden werden, um in allen Teilen (.NET Framework 4.x unter Windows, Android und IOS )

Sei Dir aber bewusst, das EmbedIO eher ein Workaround ist, als eine Alternative zu Dingen wie Uno/MAUI... .NET Fx ist vorbei und es ist ratsamer bei solchen Abhängigkeiten zweigleisig zu fahren.

Gibt bei EmbedIO laut GitHub-Seite de facto keine Weiterentwicklung mehr, quasi das ganze Projekt basiert auf einer Person -  und das kann jederzeit eingestellt werden. Eine Business-Anwendung würde ich darauf eher nicht basieren lassen; mit Pech hast beim nächsten Apple SDK Update nen Problem.

02.03.2024 - 00:12 Uhr

Selektier den Fehler in der Liste und drück F1, dann kommst Du zur Fehlerbeschreibung von CS0246
Dir fehlt eine Referenz auf eine Assembly (dll) oder ein NuGet-Paket; wo auch immer Deine "Pipeline" eben definiert ist.

Schaue ich in die Dokumentation von RunspaceFactory.CreateRunspace Method sieht man, dass diese offenbar mit dem Paket System.Management.Automation mitkommt.

=> Was ist NuGet, und welche Funktion hat es?

02.03.2024 - 00:02 Uhr

Im Buch wird erwähnt, dass die Datenzugriffsschicht von der Logikschickt abhängen soll und nicht andersherum bzw. auch, dass jede Schicht die Interfaces, die sie verlangt, selbst definieren soll.

Welches Buch ist das?

Frage: Wie mache ich dass, wenn die Datenschicht in einer eigenen Bibliothek vorliegt?

Getrennte Bibliotheken sind nur ein organisatorisches Mittel in einer Solution, hat aber keine Auswirkung auf die Softwarearchitektur an für sich.

Die Logik kennt die Datenschicht

public class UserService(IUserRepository userRepository)

Ob das IUserRepository nun durch eine zusätzlich Lib-Referenz kommt oder nicht, ist hier unerheblich.

Eigentlich braucht man hier keinerlei Glue-Code.


https://github.com/BenjaminAbt/AspNetCoreEnterprisePlatform ist mein ASP.NET Core Schulungscode von 2022.

Beispiel: das "Tenants" ist die Domäne (nach Domain Driven Design), wobei Features.Tenants das eigentliche Domänen-Projekt ist.
Darin enthalten ist sowohl die Logik, wie auch die Datenverantwortung der Domäne. Es würde aber keine Rolle spielen, wenn die Daten in einem extra Organisationprojekt zB "Features.Tenants.Database" liegen würden. Das würde organisatorisch gewisse Dinge erleichtern wie Multi-Database, aber nicht die Software Architektur.

Mein Beispiel hat auch (relativ) viele Projekte; sind aber alles organisatorische Mittel einer Plattform (das Schulungsziel). In den meisten Fällen, vor allem bei kleineren Anwedungen, hat man sehr viel weniger Projekte.

29.02.2024 - 13:28 Uhr

Da dies eigentlich nur für Missbrauchszwecke verwendet wird, ist das Thema gesperrt.

28.02.2024 - 12:40 Uhr

Zitat von T-Virus

Ist für mich halt eine Red Flag, weil dies auch auf einen Entwicklungsstopp oder einfach ein Ende des Projekts hindeutet.

Das es die Mehrheit der Nuget Pakete betreffen würde denke ich auch, hab schon einiges veraltete oder tote Pakete gefunden.

Aber 99% halte selbst ich für zu hoch oder hast du eine Statistik dafür?

99% ist natürlich aus der Luft gegriffen, aber fast jedes Projekt, das ne Zeitlang existiert, hat Issue-Leichen. Das ist auch überhaupt nicht schlimm und ist natürlich kein Anzeichen, dass das Projekt tot ist. Die Commit-History ist die einzig relevante Metrik zu sagen, ob an einem Projekt gearbeitet wird oder nicht.

Warum .NET selbst?

Es geht mir nur darum, dass es ein einziges Open Issue gibt was seit Jahren rumgammelt und es auch seit 4 Jahren kein comitt mehr gibt.

Man muss halt auch den Inhalt des Issues lesen.

Das zusammen zeigt mir, dass das Projekt im Grunde tot ist bzw. sich nichts mehr tut.

Ist wahrscheinlich auch tot, aber das kannste halt auch nur an der Commit-History sagen, wie man sieht. Issue-Management bei Open Source Projekten haben exakt 0 Aussagekraft (leider? Gott sei dank?).

Davon abgesehen, völlig egal ob ein Projekt tot ist oder nicht: dscNRW hat den betreffenden Inhalt ja bereits übersetzt und dadurch weiß man, dass man sich den Code einfach mal anschauen kann, wie andere das so tun. Open Source sei dank.

28.02.2024 - 11:58 Uhr

LaTex Doc Automation ist aber eine riesige Frickelei von String-Kombinationen. Ohne entsprechendes Paket - gibt nen paar auf GitHub - ist das auch purer Schmerz. Hinzu kommt, dass das alles super umständlich bis gar nicht validiert werden kann - mit OpenXML hat man wenigstens die Validierungssicherheit und es gibt nen fertiges SDK.

28.02.2024 - 10:48 Uhr

Auf OpenXML wirst eigentlich direkt in den Microsoft Docs verwiesen, da alle Interop-Dokumentationen (außer die Klasse selbst) im Archiv liegen.
Getting started with the Open XML SDK

Das ist der aktuelle Stand der Technik, um mit OpenXML-Dateien (wie docx) umzugehen.

Der Interop-Support ist seit Jahren abgekündigt und funktioniert auch nicht mehr mit den neuesten Office-Versionen, da ja die Runtime auf WebView2 gewechselt wurde.

28.02.2024 - 10:41 Uhr

Zitat von T-Virus

Mit einem Open Issue von 2018 würde ich das Paket sicherlich nicht installieren.

Das allein ist hat keine Aussagekraft. Dann dürftest Du 99% der NuGet Pakete nicht verwenden, geschweige denn .NET selbst.

Vor allem bei einem Issue hier, das offenbar ein Self-Reminder des Autors ist.

28.02.2024 - 10:38 Uhr

Du hast ja eine docx Datei; hat das einen Grund wieso Du mit Interop statt mit OpenXML arbeitest? Interop ist der sehr sehr sehr sehr alte Weg, um mit Office Daten über Office-Applikationsinstanzen zu arbeiten; OpenXML braucht das alles nicht mehr.

Bei OpenXML verwendest Du für das Mergen einfach AltChunk.

27.02.2024 - 22:31 Uhr

Zitat von Stefan68

PS: Kannst Du mir Bücher empfehlen in den mehr auf den Internen Ablauf eingehen (Bevorzugt in Deutsch)

Im deutschsprachigen Raum findest Du eigentlich kaum "Under the Hood"-Bücher. Thomas Claudius Huber ist aber insbesondere für seine WPF-Bücher bekannt.

Klaus Löffelmann ist ein bekannter deutscher Entwickler, der so in den ~2012er Jahren sehr viel .NET und Windows Forms in der Community gemacht hat, aber mir ist da kein Buch bekannt. Er ist aber mittlerweile direkt bei Microsoft angestellt, entwickelt an Windows Forms und gibt immer wieder Einblicke; aktuell ist sein Windows Forms x64 Blogpost auf dem .NET Blog.

27.02.2024 - 09:55 Uhr

Generelles Feedback:

Zum Problem:

Ich vermute, dass es am BeginForm liegt - aber würde dafür meine Hand nicht ins Feuer halten. Dort ist keine Area angegeben; dafür ist die Angabe der Actions im Submit eigentlich unnötig. Aber das alles brauchst Du nicht, wenn Du es "richtigerer" machen willst.

Verwende Routes und keine Actions. Das gilt als allgemeine Best Practise und macht das Leben sehr viel einfacher. Routenamen am Besten als Konstanten pflegen, dann muss man sie nur ein mal definieren. Actions sind toll in Demos oder toll in dynamischen Tools - aber nicht für das, was Du offenbar vor hast. Davon abgesehen sind Routes ein vielfaches performanter als Action Links.

Machst Du einen Fehler bei Actions, bekommst Du keinen Error. Es geht ins Leere. Bei Routes bekommst Du eine Fehlermeldung ⇒ fail fast.


Das Forum hier basiert auch vollständig auf definierten Routes.

Weiterer Vorteil von Routes: es ist sehr viel einfacher mit Standard-HTML zu arbeiten. Du brauchst diese ganzen unnötigen Helper wie BeginForm nicht sondern machst einfach nen HTML form-Tag mit dem LinkGenerator, der um Welten besser ist als das Html-Helper zeug.

26.02.2024 - 11:31 Uhr

Bei all den Firmen, bei denen ich war und sowas verwendet haben, waren ausschließlich "echte" Redaktionssysteme im Einsatz. Waren aber auch alles Firmen mit entsprechendem Qualitätsanspruch (große Maschinenbauer etc).

21.02.2024 - 22:24 Uhr

Was soll denn AuthenticateComponent sein? Ist das was Custom-mäßiges?
Standard-Blazor kennt das nicht, da heisst das AuthorizeView, das asynchron funktioniert und sich auch automatisch aktualisiert. Und da passend dazu dann auch Authorized.

Da gibts dann auch noch Authorizing, das während der asynchronen Authorisierung angezeigt wird.

20.02.2024 - 14:54 Uhr

Zitat von Stefan7907

Kann das mit dem Garbage Collector zusammenhängen, das der meine Funktion oder wichtige Teile davon nach 40s abräumt? Oder muss ich dem DataReceivedHandler immer wieder einen Anstoß geben?

Natürlich nicht, denn so funktioniert der GC gar nicht. Der räumt nicht einfach was nach einer fixen Zeit ab.

Jedoch bricht die Kommunikation konstant nach 40 Sekunden ein.

Was heisst "bricht ein" - bekommst Du eine Exception, wenn ja welche? Wir können leider nicht hellsehen.


Ein Timeout kann auch an falschen Konfigurationen oder am Client selbst liegen. zB haben Geräte wie ein Ardurino gerne Defaults von 40 Sekunden. Der SerialPort hat keinen Default, der dieser Zeitspanne entspricht.

Ansonsten probier funktionierende Templates und such den Unterschied: https://mycsharp.de/forum/threads/43748/template-serialport

PS: hab Dein Beitrag editiert, in Zukunft selbst drauf achten. Du willst Hilfe - also machs potentiellen Helfern auch einfach.
Danke.

18.02.2024 - 12:23 Uhr

Zitat von brave_snoopy

Alternativ, wenn ich’s mit z.b. blazor mache, brauch ich den Zwischenschritt mit den APIs nicht. Sehe ich das richtig?

Ja und nein, es kommt drauf an, was Du machst.

Blazor-Kommunikation findet über eine SignalR-Verbindung statt; Du hast also unter der Haube ein Backend, das dann sicher mit der DB sprechen kann. Gibt hunderte Dokumentationen und Tutorials dazu mit Titeln wie "End to End with Blazor" etc. Aber gibt Szenarien, die durchaus eine API empfehlen. Daher ist "brauche" vielleicht das falsche Wort - "für dich reichen" ist eventuell eher der Fall.

Zum Thema .NET vs. .NET Core: Das .NET Ökosystem - .NET, .NET Core, .NET Standard, NuGet und Co
Sein Link zeigt auch nicht auf .NET Core sondern ASP.NET Core. Ja, das "Core" ist manchmal da und manchmal nicht - nur der Namensverwalter bei .NET weiß wieso.

Zwischen den Zeilen liest man, Blazor ist eigentlich wie silverlight auch schon wieder tot.

Außer bei gewissen Leuten, die vor allem auf YouTube mit Clickbait Titeln arbeiten, les ich das eigentlich nicht. Aus meiner Sicht ist Blazor in vielen Dingen einfach aktuell nicht ready, in manchen Sachen sagt das Marketing auch Dinge, die einfach in der Realität so nich wirklich funktionieren und/oder praktikabel sind - in anderen Fällen dafür ein gutes Tool.

Blazor ist auch nur eine Möglichkeit, wie man Web Anwendungen entwickelt.
Gibt auch noch andere Ansätze wie z.B. mit Razor Page.

Das sind keine konkurrierende sondern ergänzende Technologien. Blazor an für sich hat derzeit keine Konkurrenz, weil kein anderes Framework auch in keiner anderen Familie (Java, Node..) das End-to-End-Server-Client Szenario so erfüllt. Aber mit Blazor kann man ja auch andere Dinge machen wie Web auf dem Desktop (Konkurrenz hier zB Electron) oder WebAssembly, wo das anders aussieht.
Razor ist nichts anderes als eine gewisse Syntax und Razor Page ist die View Technologie, die es sowohl bei ASP.NET MVC gibt wie auch bei Blazor - und auch Stand-alone.

Ja - ASP.NET als Produktfamilie ist groß und wenn man die ersten Seiten Docs nicht liest auch erstmal unübersichtlich.

16.02.2024 - 10:02 Uhr

Zitat von trib

Die embedded Geräte mit denen ich gearbeitet habe, hatten im worst case 128MB RAM und 512MB Speicher.

Da hat ein Log(-file) schnell den Platz belegt, wenn man nicht aufgepasst hat.

Das ist aber ja nur eine Hardware-Limitierung, sofern Du direkt auf die Hardware loggst. Du kannst aber ohne Probleme auch von Embedded auf extern loggen, sofern die Hardware in einem Netz ist. Das ist aber alles dann situationsbedingt und fällt für mich nicht unter den generellen Fall "Embedded".

Hab ne Software, die im Embedded-Bereich läuft und sowohl auf ne SD-Card sowie auch gegen ein HTTP Endpunkt loggen kann.

Ist dieser null, greift eine standard implementierung.

Wo wir wieder beim Fall wären: es wird Zeug ausgeführt, das nicht sein muss. Im dümmsten Fall ist die Standard-Implementierung inkompatibel. Kostet einfach Ressourcen, das man vermeiden kann.

PS: .NET hat mittlerweile auch einen NullLogger.

15.02.2024 - 17:26 Uhr

Logging oder andere Metriken sind Dinge, die einen massiven, negativen Impact auf die Runtime-Performance ausüben kann - vor allem wenn man Best Practises wie Compile-Time Logging nicht anwendet.
Wenn Deine Logging-Dinge innerhalb Deines Providers mich 20% Runtime-Performance kostet, weil Du es erzwingst, dann fliegt die Lib halt wieder raus. Das muss niemanden aufgebürdet werden.

Daher gilt es auch als Recommendation, dass eine "neutrale" Lib kein Logging-Parameter erzwingt. Unterliegt im Endeffekt der generellen Regel: nur den Code ausführen, den man auch ausführen muss.

Weil aber es doch ab und zu Libs gibt, die das ignorieren, hab auch ich mir einen solchen Mock geschrieben: https://github.com/BenjaminAbt/ThrowAwayLogger
Nachhaltig ist es nicht. Es wird Code ausgeführt, der nicht ausgeführt werden muss.


Zitat von T-Virus

Da du auch nicht wissen kannst in welchen Umgebungen deine Lib verwendet wird, wäre es fatal wenn du dort Vorgaben mit nötigen Logging hast.

Deswegen ist es ja prinzipiell ein Interface, sodass Dir nichts aufgezwungen wird. Mit der Umgebung hat das nichts zutun.

Zitat von T-Virus

Ggf. läuft deine Lib in einer Anwendung im Embedded Bereich, dann wäre auch Logging ggf. gar nicht möglich oder nur im kleinen Bereich.

Warum nicht? Ich verwende ILogger auch im Embedded-Bereich problemlos im gleichen Maße wie in ASP.NET Core.
Was unterscheidet sich da? Ehrliche Frage: vielleicht kenn ichs nicht.

12.02.2024 - 10:45 Uhr

Auf Windows ist standardmäßig die Windows PowerShell ISE installiert, bei der auch ungeübte sehr einfach PowerShell ausführen können. Das ist aber Scripten und nicht Programmieren 😉 Direkt erster Treffer wenn Du nach powershell windows auf Google suchst.

Einführung in die Windows PowerShell ISE


Willst Du lieber sowas nutzen wie Notepad++ gibt dazu auch dutzende Anleitungen, die das alle zeigen.
zB How to Find and Replace Words in Multiple Files

11.02.2024 - 22:29 Uhr

Das ist so ein Fall, den man binnen Sekunden mit ChatGPT lösen kann; braucht man auch kein C# zu sondern zB einfach ein PowerShell Script.
Das ist dann einfacher zu pflegen und auszuführen

Create a PowerShell Script that replaces "<DefaultText>" with "<DefaultText><size=110%>" and "<FemaleText>" with "<FemaleText><size=110%>" in all files with ending ".stringtable" in a folder

# Define the folder path
$folderPath = "C:\Path\To\Your\Folder"

# Define the strings to be replaced and their replacements
$searchStrings = @("<DefaultText>", "<FemaleText>")
$replaceString = "&lt;size=110%&gt;"

# Get all files with .stringtable extension recursively
$files = Get-ChildItem -Path $folderPath -Filter "*.stringtable" -Recurse

# Loop through each file
foreach ($file in $files) {
    # Read the content of the file
    $content = Get-Content $file.FullName

    # Loop through each search string and replace it with the replace string
    foreach ($searchString in $searchStrings) {
        $content = $content -replace [regex]::Escape($searchString), "$searchString$replaceString"
    }

    # Save the changes
    Set-Content -Path $file.FullName -Value $content
}

Write-Host "Replacement completed."
08.02.2024 - 17:49 Uhr

Zitat von oehrle

Hallo Abt, danke für die Info. Aber Prizipiell wird das in die Richtung mit dem Webservice gehen? Ich meine, ist da die Berechtigungseinschränkung weniger restriktiv?

Ja - klar kannst nen "TCP/HTTP Server-Endpunkt" laufen lassen, den von Außen erreichbar machen und damit kommunizieren.
Bei den Maschinenbauern, bei denen ich war bzw. die meine Kunden waren, wurde aber sowas unterbunden.

Hat ja dann alles aber natürlich nichts mit irgendwelchen Domänenrechten zutun.

Ich würd wirklich lieber ne aktive Lösung mit der IT zusammen suchen, als jetzt irgendwelche Rechner mit TCP/HTTP-Endpunkten aufzubohren, wo dann eigentlich die nächsten Issues damit nur ne Frage der Zeit sind. Davon abgesehen kann eure IT sicherlich innerhalb Sekunden und vermutlich sogar automatisiert Dein Vorhaben erkennen und unterbinden. Üblich bei Enterprise-Grade Netzwerk-Komponenten.

08.02.2024 - 16:47 Uhr
  1. Fragen mit "Ist sowas möglich" können immer mit Ja beantwortet werden - alles eine Frage des Aufwands.
  2. Du kannst keine Domain-Impersonation auf einem Rechner durchführen, der nicht Teil der Domäne ist. Das ist eine reine Windows-Funktion.

Gibt es da schon fertige DLL's die ich in C# verwenden kann?

Nein, das hat auch mit C# nichts zutun. C# ist eine reine Sprache und auch .NET bringt Dir keine Logik-DLLs.
.NET bietet Dir Bausteine, mit denen Du eigene Logik umsetzen kannst. Natürlich nicht fertige Windows-Funktionalitäten wie hier.


Generell: es ist richtig und gut so, dass eure Maschinen sich in einem getrennten Netz befinden und nicht teil der Domäne sind. Das sind absolute Security und Netzwerk-Basics. Hab ich auch schon genug mit zutun gehabt; ich komm aus dem Maschinenbau-Umfeld.

Ja - eine solche Trennung macht viele Dinge komplex. Aber es ist deutlich komplexer, wenn eine Firma mehrere Wochen stillsteht, weil vulnerable Maschinen angegriffen wurden. Ich erinner da nur an die Stuxnet-Zeit.
Seit Stuxnet ist das sogar bei den aller meisten Machinenbauern bzw. Maschinenpark-Inhabern so, dass Maschinen generell keinerlei physikalischen Kontakt zum Unternehmensnetzwerk oder Internet haben dürfen. Gewisse Sicherheitsempfehlungen sagen hier sogar explizit den Datenaustausch per USB vor. USB: auch nicht mega toll, aber besser als die Direktanbindung.

Ich kenne Netzwerkimplementierungen in solchen Fällen, die nur eine One-Way-Schreibrichtung erlauben. So können Daten von der Maschine auf ein gewisses Laufwerk geschoben werden, und auch Daten vom Netz (zB Maschinenprogrammierer) an die Maschine kommen. Kenne aber keine einzige Lösung, die in allen Unternehmensnetzwerken mit Maschinenanbindung funktioniert, weil alle Firmen dann doch gewisse Unterschiede in Sachen Netzwerksegmentierung, Netzwerksicherheit und Domänen-Verwaltung haben.

An Deiner Stelle würde ich mich mit der IT zusammensetzen und eine Lösung suchen, die praktibel und für eure Anforderungen auch sicher ist. Alleine irgendwas erfinden ist in den aller meisten Fällen nur von kurzer Freude.

Bin jetzt echt etwas am Boden, denn diese bisherige Lösung hatte ich vor zwei Jahren mit diesen Kollegen erstellt, und jetzt das

Kann Dich trösten. Sowas war einfach vor 2 Jahren schon keine nachhaltig gute Idee, sondern nur ein Workaround. Abhaken.

02.02.2024 - 18:26 Uhr

Du wirst kein perfekt zugeschnittenes Buch finden, sondern für .NET und Angular jeweilige Bücher suchen müssen.

Wenn es Dir spezifisch um Angular und .NET geht, dann ist es wahrscheinlicher Blogartikel bzw. Tutorials zu finden. Fabian Gosebrink ist zB jemand, der sehr sppezifisch .NET und Angular gemeinsam abdeckt - aber für die Artikel sollte man die Grundlagen beider Welten beherrschen.
https://offering.solutions/blog/

01.02.2024 - 11:31 Uhr

Zumindest in früheren Versionen gar nicht; da musstest Du zwangsweise über JSInterop gehen. Drittanbieterlösungen verwenden auch hier meist JSInterop, die dann einen Custom Blazor Event werfen.

Die Idee hinter Blazor ist ja, dass Du das Objekt in der Zelle bekommst - nicht die Zelle selbst (Trennung von Daten und UI).
Ergo musst Du in Deinem Modell diese Funktionalität zB über eine Property abbilden. Und dann zB ein Html-Attribut über das Property setzen, das dann via CSS den Border bekommt - wie man das zB auch ungefähr in WPF machen würde.

29.01.2024 - 16:54 Uhr

Zitat von Fabiano

Es handelt sich einfach um einen mir bekannten Entwickler!

Dann sag einfach interner Kollege; so liest es sich zumindest wirr.

Was meinst du genau mit "noch gewisse offizielle Unterstützung für .NET Framework"? Gemäss Microsoft steht für 4.7+ noch gar kein EOL Datum fest?

Gewisse im Sinne von spezifischen Versionen; die letzten, die eben an aktuelle Windows Versionen gekoppelt sind. Aber auch hier ist NetFX generell abgekündigt; Du bekommst nur noch Sicherheitsupdates im Rahmen der Cumulative Updates, zB https://devblogs.microsoft.com/dotnet/dotnet-framework-january-2024-cumulative-update-preview/

29.01.2024 - 15:29 Uhr

Ich bin gerade über die Aussage eines Entwicklers gestolpert, wonach .NET8 nicht auf Windows IoT 10/11 verfügbar sein soll.

Quellenangabe ist immer nützlich. Ansonsten weiß niemand, ob Du irgendein Forenbeitrag meinst, oder eine Aussage eines Microsoft Entwicklers oder was der Kontext ist.

Leider finde ich keine belastbaren Infos, um die Aussage entweder zu bestätigen oder zu wiederlegen, und ein Windows IoT zum Testen hab ich auch nicht zur Hand.

Siehe .NET 8 - Supported OS versions

Windows IoT 10 bzw. 11 sind beides nur Subsysteme der jeweiligen Vollversionen, daher hast Du auch die gleichen Requirements, zumindest von der .NET Systemanforderungsseite.
Es gibt sogar für beide noch gewisse offizielle Unterstützung für .NET Framework.

Daher nein, es ist keine Einschränkung bekannt, dass die reine .NET Runtime nicht auf Windows IoT laufen würde. Selbst die .NET Desktop Runtime funktioniert auf Windows IoT mit ARM64.

26.01.2024 - 12:52 Uhr

Das hat mit Blazor nichts am Hut, das sind einfache HTML Strukturgrundlagen - und die besagen dass in einem tr kein div stecken kann.

Tabellen-Controls sind eh nicht unbedingt die modernste Art und Weise, weil sie Limits bei responsiveness haben. Musst Dir also eine andere Struktur überlegen, zB über Flexbox Tables.

26.01.2024 - 11:00 Uhr

Zitat von dannoe

Kontrollzeichen mit dem .NET Xml Serializer und auch das direkte Laden via xmlDocument.LoadXml gehen auch in .NET 8 noch nicht. (siehe https://dotnetfiddle.net/WwArTE)

Weil Du eine pessimistische Xml Implementierung verwendest.

Wenn das Xml aber mit der System.Xml API aufgebaut wird, dann wird das Zeichen automatisch mit HTML Entities (&#x1D;) kodiert.

Das ist auch der korrekte Weg.

// Create Serializer
XmlSerializer serializer = new (typeof(MyXml));

// Input to test
string input =  "ABC" + "\u001d" + "ABC";

// Print Base64 input verification
Console.WriteLine("Source Base64: " + Convert.ToBase64String(Encoding.UTF8.GetBytes(input)));

// Dummy XML object
MyXml xmlForSerialize = new () { Data = input };

// Serialize dummy object
string xmlText;
using (var stringwriter = new StringWriter())
{
    XmlWriter xmlWriter = XmlWriter.Create(stringwriter, new XmlWriterSettings{CheckCharacters = false});
    serializer.Serialize(xmlWriter, xmlForSerialize);
    xmlText = stringwriter.ToString();
}

// Deserialize XML
XmlReader xmlReader = XmlReader.Create(new StringReader(xmlText), new XmlReaderSettings { CheckCharacters = false });
MyXml xmlDeserialized = (MyXml)serializer.Deserialize(xmlReader)!;

// Print Base64 output verification
Console.WriteLine("From XML: " + Convert.ToBase64String(Encoding.UTF8.GetBytes(xmlDeserialized.Data)));

Output:

Source Base64: QUJDHUFCQw==
From XML: QUJDHUFCQw==

Aber wie gesagt - alles völlig irrelevant wenn man einfach den üblichen Weg über "Advanced Data Formatting" geht.

25.01.2024 - 20:51 Uhr

Zitat von dannoe

Wenn du kontrollieren kannst, dass dein Ersatzzeichen nicht irgendwann von einem Lieferanten im Barcode auftaucht, dann kannst du das machen.

Einfach mein Link lesen; das passiert nicht mal.

In unserem Fall hatten wir das gleiche Problem bei den mobilen Geräten (Motorola mit Windows CE und Compact Framework) unserer Kunden. Vielleicht hätten wir dort im Gerät irgendwo etwas ähnliches einstellen können. Aber diese Zeichen wurden als Trennzeichen in den Barcodes verwendet um einzelnen Daten von einander zu trennen.

Standardfall, und jeder moderne Barcode Scanner hat eine extra Einstellung dafür, weil das in vielen Szenarien nicht funktioniert; HTML Input ist nur einer davon.

Das Setting heißt in fast alle Fällen, die ich kenne, "Advanced Data Formatting".

Wird genau über diesen Weg auch bei den meisten Lieferanten-APIs von Paketen so definiert. Denke, dass das ne Branche ist, das durchaus Repräsentationsrelevanz hat.


Die Problematik bleibt: der Browser entfernt von sich aus das Zeichen beim Absenden.

Ich hab das gerade mal in ner lokalen Blazor Anwendung nachgestellt; ich bekomme das GS Zeichen (Char 29 ASCII Table), wenn ich den Form Parameter als SupplyParameterFromForm definiere; dann wird nichts raus gefiltert.


<form method="post" @formname="form" @onsubmit="Submit">
    <AntiforgeryToken />
    <div>
        <label>
            Input:
            <InputText @bind-Value="InputData" />
        </label>
        <label>
            Base64:
            <InputText @bind-Value="OutputData" />
        </label>
    </div>
    <div>
        <button type="submit">Submit</button>
    </div>
</form>

@code {
    [SupplyParameterFromForm]
    public string? InputData { get; set; } = "ABC" + "\u001d" + "ABC";

    [SupplyParameterFromForm]
    public string? OutputData { get; set; }

    private void Submit()
    {
        if (InputData is not null)
        {
            byte[] plainTextBytes = Encoding.UTF8.GetBytes(InputData);
            OutputData = Convert.ToBase64String(Encoding.UTF8.GetBytes(InputData));
        }
    }
}
25.01.2024 - 19:24 Uhr

Zitat von dannoe

Die Zeichen sind vermutlich einfach in JSON oder XML (je nachdem was du sendest) nicht erlaubt und deshalb quittiert der Server das mit einem Internal Server Error.

Wenn ungültige Daten an den Server kommen gibt es ein Bad Request Response, kein Server Error. Der Server Error kommt (vermutlich) von der weiteren Verarbeitung, dass zB der String ungültig ist, weil eben Zeichen fehlen.

Jeder Standard XML bzw. Json Serializer konvertiert non-printable chars automatisch in die UTF-16 Repräsentation.

Aber solang er nur sagt, dass er ein Fehler 500 bekommt und nicht, was die Fehlermeldung ist, kann man nur spekulieren - macht wenig sinn.

Probier mal die Eingabe zu kodieren (z.B. base64), dann zu senden und dann im Server wieder zu dekodieren.

... oder sich einfach an Standards halten. Siehe mein Post.
Aber ja: wäre ja zu einfach 😃

25.01.2024 - 11:02 Uhr

Dein GS Zeichen etc sind sogenannte no-printable chars. Und diese werden by default von Text Boxen in Browsern ignoriert.
Das heisst, dass Deine Chars hier nicht 1:1 versendet werden. Bekanntes Problem bei Barcode Scannern.

Im Prinzip hat Notepad das gleiche Problem: es kann Dir das Zeichen nicht anzeigen. Daher hat Notepad einen eigenen Platzhalter, hier zB GS für Group Separator.

Die meisten Barcode-Scanner haben eine Funktion um Tasteneingaben zu simulieren, sodass statt dem GS-Char ein ] versendet wird oder andere Optionen; hier mal erster Google Treffer zu barcode scanner gs char:
What is Gs replacement?

24.01.2024 - 19:40 Uhr

OnPropertyChanged ist der Framework-Mechanismus, wenn Du Properties hast, die einen "Dirty State" haben, der eigentlich optimalerweise zu vermeiden ist. Damit triggerst Du WPF an, dass die Referenz neu bekannt gemacht wird und die Value wird aktualisiert.

Er lässt sich bei den Typen vermeiden, die eine direkte Möglichkeit der Bindung haben; wie die ObservableCollection.

Diese Aussage verstehe ich nicht, denn ich hatte noch niemals Probleme damit so eine ObservableCollection neu zu erstellen.

Doch hattest Du, denn die Bindung in diesem Moment ist nicht mehr vorhanden, sie zeigt auf die alte Referenz.
Du wirst sicherlich eben auch OnPropertyChanged triggern, um das zu lösen.


Persönlich lösche ich aber auch immer diese Collection und fülle sie dann.

Die generelle Empfehlung ist in WPF, genau das eigentlich nicht zu tun, weil der Overhead von OnPropertyChanged,der Allocation und die Bindungsaktualisierung i.d.R. teurer ist als das Clear, das O(n) ist.

Eine Neu-Initialisiert ist nur dann empfohlen, wenn Du sehr viele Items hast und die ObservableCollection direkt mit den Items initialisierst.

Und die vielen Themen dazu in diesem Forum, aber auch zB bei SO zeigen, dass das den Leuten einfach nicht bewusst ist.

24.01.2024 - 12:02 Uhr

In einfachen Anwendungen würde man das machen wie Alf Ator es sagt, in komplexeren Anwendungen wird sowas nicht geteilt. Es werden auch keine Referenzen hin und her kopiert.

Man würde in größeren Anwendungen auf ein Messaging System setzen, zB Reactive Extensions oder ReactiveUI.
Das heisst jede View ist total unabhängig, kennt keine anderen Views und View-übergreifende Daten, Events und Informationen werden über Subscriptions bekannt gemacht und in den Views aktualisiert.

https://github.com/dotnet/reactive

24.01.2024 - 11:36 Uhr

Es wird ein Service erstellt also zB. ListViewService, der gewisse methoden hat, die eine ListView mit dem jeweiligen Inhalt befüllen. In dem Service soll nicht die observable Collection enthalten sein. Die soll jedesmal im ViewModel aus der Liste erstellt werden? Aber so klappt das irgendwie nicht, denn, wenn die View aus Bereich 1 nur mit einer observable Collection aus dem Viewmodel 1 gebunden ist und ich in Bereich 2 ListViewService aufrufe und dort lokale Variablen ändere, merkt die View das nicht.

Es ist nicht üblich, dass man sich eigene Service für UI Elemente baut. "Service" ist eine Begrifflichkeit aus der Logik-Architektur.
.NET Naming Best Practises: Services vs. Providers

Dann wäre meine Frage. Der ListviewService würde auch die Businesslogik enthalten. Aber die BusinessLogik sollte eigentlich nicht die observable Collection enthalten oder?

Nein, natürlich nicht. Dein UI Element soll und darf keine Business Logik enthalten - zumindest wenn Du eine saubere Architektur willst.
Business-Logik Bausteine sollen unabhängig von der UI sein, sodass Du diese Klassen in mehreren Projekten nutzen kannst. Wenn Du irgendeine Abhängigkeit in Deiner Logik zB zu WPF hast, dann kannst Du diese Klasse zB nicht mit Windows Forms verwenden.

[Artikel] Drei-Schichten-Architektur

Business Logik bezieht sich immer auf Business Modelle (User, Orders...) und nicht auf UI Elemente.


Technische Limitation: Deine ObservableCollection darf nicht neu erzeugt werden.

Das ViewModel erzeugt diese Liste in der Initialisierung (am besten direkt an der Property) und muss dann dauerhaft bestehen bleiben.
Du darst die Referenz nicht verändern. Willst Du Änderungen an der Liste vornehmen, dann musst Du sie leeren und neue Items hinzufügen - aber nicht neu erzeugen, sonst hast auch eine neue Referenz.

Daher ist es auch nicht sinnvoll, dass irgendeine andere Klasse eine neu erzeugte ObservableCollection zurück gibt.

22.01.2024 - 16:18 Uhr

Zitat von Caveman

Allerdings rufe ich die Methode Create1DModelData() in meinem Beispiel nur einmal auf, nämlich im Konstruktor.

Ist trotzdem quatsch. Verwende einfach

public ObservableCollection<Model> Items { get; } = new ObservableCollection<Model>();

und Du brauchst auch keinen Setter mehr, was dann eine fehlerhafte Verwendung durch Compiler Support verhindert.

22.01.2024 - 15:59 Uhr

Zitat von Caveman

Edit: Ich habe im Übrigen auch die Antwort von Abt nicht verstanden, obwohl ich mir das mindestens 10x durchgelesen habe.

   private void Create1DModelData()
    {
        ItemsModel1D = new ObservableCollection<Model>();
        for (int row = 0; row < 10; row++)
        {
            ItemsModel1D.Add(new Model() { CellValue = $"Row {row} - Col 0", UnImportantValue1 = "Blah", UnImportantValue2 = "Blubb" });
        }
    }

Du erstellt hier eine neue Instanz von  ObservableCollection<Model>(); und damit machst Du die Bindung von WPF kaputt.
Die Instanz von ObservableCollection darf nur ein einziges Mal erzeugt werden.

public ObservableCollection<Model> Items { get; } = new ObservableCollection<Model>();

Und dann muss Deine Methode aussehen wie zB

   private void Create1DModelData()
    {
        ItemsModel1D.Clear()
        for (int row = 0; row < 10; row++)
        {
            ItemsModel1D.Add(new Model() { CellValue = $"Row {row} - Col 0", UnImportantValue1 = "Blah", UnImportantValue2 = "Blubb" });
        }
    }

WPF arbeitet mit fixen Referenzen - also die Referenz, die bein Binden des Modells existiert.
Eine neue Instanz ist eine neue Referenz → kennt WPF nicht mehr, Bindung kaputt.

21.01.2024 - 22:07 Uhr

Zitat von Abt

Zitat von Peter Bucher

  1. 2 Faktor Authorisierung konnte ich mit dem Microsoft Authenticator (QR gescannt) 4, 5 Versuche nach Eingabe des Codes nicht einrichten, es kam nur "ooops ein Fehler ist aufgetreten". Liegt das an mir oder ist das bekannt?

Danke, schau ich mir an.

Hab die dazugehörigen Exceptions in App Insights gefunden und behoben.

21.01.2024 - 17:46 Uhr

Zitat von Peter Bucher

  1. 2 Faktor Authorisierung konnte ich mit dem Microsoft Authenticator (QR gescannt) 4, 5 Versuche nach Eingabe des Codes nicht einrichten, es kam nur "ooops ein Fehler ist aufgetreten". Liegt das an mir oder ist das bekannt?

Danke, schau ich mir an.

  1. Wenn man eine private Nachricht schreiben möchte - im Darkmode! - ist die Schrift weiss auf weissem Hintergrund, man sieht das geschriebene also leider nicht.

Bekannt - aber noch leider keine Lösung. Auch schon ein Ticket beim Editor-Dev aufgemacht.

21.01.2024 - 13:05 Uhr

Kleines Update zur Architektur: wir verwenden nun den Azure Communication Service, der seit Kurzem auch einen Datenstandort in Deutschland hat, für das Versenden von E-Mails. Der bisher eigene (gesicherte) SMTP-Endpunkt wurde damit ersetzt. Kam uns gelegen, da es ab und zu auch zu nicht zugestellten E-Mails kam, was nun der Vergangenheit angehören sollte.

Zudem werden unsere E-Mails nicht mehr von einer Custom ASP.NET Core Razor Engine gerendert, sondern mit der Hilfe von Handlebars.net, was uns sowohl das Rendern selbst wie auch das Testen deutlich vereinfacht.

20.01.2024 - 16:48 Uhr

Unter der Prämisse Deinen Code zu verstehen (Du zeigst hier Code mit Eigenschaften, die namentlich so nicht stimmen können):

Bindungen funktionieren nur mit fixen Referenzen; Du darfst also die Bindung von ObservableCollection<Model> Items nicht verändern.

Statt also eine neue Instanz zu erzeugen, leere die bestehende und füge dann die neuen Einträge ein.

20.01.2024 - 12:47 Uhr

Ist alles sehr gut dokumentiert, man muss nur in die Docs schauen.

Configure Windows Authentication in ASP.NET Core

16.01.2024 - 14:23 Uhr

Nein, ein SQL Query beim SqlServer muss immer auf eine Instanz gerichtet sein; kannst Du programmatisch nicht auf Server verteilen (ausser Du codest das natürlich selbst aus) - aber auf SQL Ebene geht das nicht.

Vielleicht holt ihr euch einfach Rat ins Boot?

16.01.2024 - 13:44 Uhr

Zitat von mezzo80

Dann habe ich in 1 minute nie die 10.000mm sondern immer unterschiedlich. mal 9350mm oder 8987mm aber ich komme nie auf die 10.000mm.

Das ist völlig normal auf einem Nicht-Echtzeit Betriebssystem, wie es fast alle Betriebssysteme sind.
Es gibt keine 100%tige Genauigkeit der Auflösung von Timern. Siehe Link, den ich Dir gegeben hab.

Du musst die Differenz von Start und Tick-Zeitpunkt beachten (und wenn man es ganz genau will auch die Ausführungszeit, was de facto unmöglich ist). Aber genauer gehts nicht. Statische Werte, wie Du es hast, werden immer falsche Resultate liefern, weil so Computer nicht funktionieren.

16.01.2024 - 00:30 Uhr
ObservableCollection<string> GetUsers(string name)

Auch eher nich so doll, weil Du damit Verantwortung abgibst.
Es spricht nichts gegen eine List<T> als return und das ViewModel kann sich selbst um seine ObservableCollection kümmern.

15.01.2024 - 23:07 Uhr

A circular dependency was detected bedeutet, dass zwei Abhängigkeiten sich gegenseitig kennen, was nicht sein darf.

public class Hase
{
    public Hase(Igel ..) {..}
}

public class Igel
{
    public Igel(Hase ..) {..}
}
  • Hase kann nicht erstellt werden, ohne Igel zu übergeben
  • Igel kann nicht erstellt werden, ohne Hase zu übergeben
  • => circular dependency

Und genau das passiert bei Dir:

public UserService(MainWindowViewModel mainWindowViewModel)
public MainWindowViewModel(IUserService userService)

Das ist nicht nur eine Dependency-Verletzung, sondern auch eine Schichtverletzung ⇒ [Artikel] Drei-Schichten-Architektur
Deine Logik darf niemals etwas von der UI kennen - hier übergibst Du aber ein ViewModel: das ist Käse.


Deine Implementierung vom UserService ist auch eher so suboptimal.

Die Methode heisst public void GetUsers() - aber Du gibst gar keine User zurück. Du füllst irgendeine ViewModel-Instanz.
Gib einfach die Liste von User zurück. Das ViewModel ist völlig irrelevant für die Logik.