Laden...

Dereferenzierung von Null Werte in XML .MAUI & Blazor

Erstellt von Alesia vor einem Jahr Letzter Beitrag vor einem Jahr 504 Views
A
Alesia Themenstarter:in
15 Beiträge seit 2022
vor einem Jahr
Dereferenzierung von Null Werte in XML .MAUI & Blazor

Hallo zusammen,
ich bin auf euch gestoßen und sehe eine hohe Aktivität in eurer Community und hoffe natürlich auch etwas beisteuern zu können.
Seit längerem programmiere ich Anbindungen an ein ERP-System und kam bisher immer alleine gut klar.
Eine App auf Basis von WinForms existiert bereits und diese bin ich gerade dabei umzuschreiben.
Meine Zielplattform ist .MAUI und Blazor.

Zum starten habe ich eine einfache .MAUI App generiert um zu sehen ob mein Connector und meine Models funktionieren, dies ist der Fall und macht keine Probleme.
Da ich die App jedoch auch in einer Webanwendung bereit stellen möchte, ist der nächste Weg also .MAUI mit Blazor.

Viel Text von mir, nun mein Problem.

"Dereferenzierung eines möglichen Null-Wertes" innerhalb meiner Blazor Umgebung.

Die Basis ist ein Model und ein Service, in meinem Fall "AnschriftService".
Ich schicke XML Daten an einen Connector, der dies auf der Seite meines ERP Systems dann verarbeitet.

Wie man im Code sieht, schließe ich für den ConnectorClient mit "?" bereits die null Prüfung aus.
Jetzt hänge ich aber am XML Element das NULL enthalten darf und auch ggf. zurückgibt.
Jedoch kriege ich hier den passenden Syntax nicht raus.


public class MAnschrift
{
    public string Na1 { get; set; }
    public string Na2 { get; set; }
}


        // Es müssen noch Textfelder übergeben werden in die Funktion
        public List<MAnschrift> GetAnschriften()
        {

            // XmlDocument für Parameter erstellen
            XmlDocument XmlRequest = new XmlDocument();
            XmlRequest.LoadXml("<Root/>");
            // AdrNr
            var node = XmlRequest.CreateElement("AdrNr");
            node.InnerText = "";
            XmlRequest.DocumentElement.AppendChild(node);

            // Connector initialisieren, Standard NULL
            ConnectorClient? client = null;
            client = new ConnectorClient();


            // Xml Übergabe ausführen
            XmlElement XmlResponse = client.ExecuteComplete(GlobalConnectorConfig.serverURL, GlobalConnectorConfig.connectorScriptFileName, GlobalConnectorConfig.connectorScript, XmlRequest.DocumentElement, 30);

            /*
            XmlElement el = (XmlElement)response.SelectSingleNode("Error");
            if (el != null)
                el.ParentNode.RemoveChild(el);
            */

            XmlNodeList idNodes = XmlResponse.SelectNodes("Anschrift");
            List<MAnschrift> anschriftListe = new List<MAnschrift>();

            foreach (XmlNode node1 in idNodes)
            {
                anschriftListe.Add(new MAnschrift()
                {
                    Na1 = node1.SelectSingleNode("Na1").InnerText,
                    Na2 = node1.SelectSingleNode("Na2").InnerText,
                });
            }
            return anschriftListe;
        }

Sowohl XmlRequest.DocumentElement.AppendChild(node); wird hier mit "Dereferenzierung eines möglichen Null Verweises" deklariert als auch viele andere Elemente dieses Codes.
Ebenso wird Na1 und Na2 im Model (eigene C# Klasse) angemerkt.
Könnte ich im Model mit "string?" umgehen, im XMLElement aber nicht.

Frage 1)
Kann mir jemand verständlich machen wieso die Blazor Umgebung die null-Werte anmeckert die .MAUI Umgebung jedoch nicht?

Frage 2)
Hat jemand möglichen Lösungsansatz gegen dieses Problem?

4.931 Beiträge seit 2008
vor einem Jahr

Hallo und willkommen,

vergleiche mal in den Projekteinstellungen unter "Build / General" den Eintrag für "Nullable", s.a. Nullable-Kontexte.

A
Alesia Themenstarter:in
15 Beiträge seit 2022
vor einem Jahr

Hallo Th69,

Erstmal danke ich dir für den Tipp.
ich werd verrückt.
Suche da ewig nach einer Antwort und Lösungen und Sie kann so einfach sein.
Im Model und im Service habe ich #nullable disable ergänzt und siehe da es funktioniert.

Gibt es generell auch eine Lösung ohne diesen Parameter, ist der Code dann so "konform" oder würde ein anderer Entwickler hier den Kopf schütteln wenn ich überall das nullable deaktiviere.
Ich würde gerne daraus lernen und es optimieren für die Zukunft.

4.931 Beiträge seit 2008
vor einem Jahr

Ich kann dir da keine Empfehlung aussprechen, da ich es bisher noch nicht aktiv genutzt habe.
Ich denke nur, zumindestens in einem Team-Projekt sollte man es einheitlich nutzen (also möglichst keine gemischten Kontexte).

16.806 Beiträge seit 2008
vor einem Jahr

oder würde ein anderer Entwickler hier den Kopf schütteln wenn ich überall das nullable deaktiviere.

Ja. Die Warnung und daraus folgende Behebung von potentiellen Null-Reference issues ist absolut zu empfehlen.
Aktuell ist es sogar so, dass es nur eine Warnung ist (um kompatibel zu bestehendem Code zu sein), aber empfohlen ist treat warn as errors.


 <WarningsAsErrors>CS8600;CS8602;CS8603</WarningsAsErrors>

Wie man im Code sieht, schließe ich für den ConnectorClient mit "?" bereits die null Prüfung aus.

Nein, das tust Du nicht. Hier wird nichts ausgeschalten oder geprüft. Der Code ist so sogar sinnfrei.

Mach es einfach zu


   ConnectorClient client = new ConnectorClient();

weil der Compiler hier auch erkennt, dass es potentiell nicht null sein kann.

Sowohl XmlRequest.DocumentElement.AppendChild(node); wird hier mit "Dereferenzierung eines möglichen Null Verweises" deklariert als auch viele andere Elemente dieses Codes.
Ebenso wird Na1 und Na2 im Model (eigene C# Klasse) angemerkt.
Könnte ich im Model mit "string?" umgehen, im XMLElement aber nicht.

Das ist ein absolut korrektes Verhalten, weil potentiell XmlRequest.DocumentElement null sein könnte.
Im Endeffekt musst Du das abfangen, um sicher zu sein. Potentiell schließt Du das durch XmlRequest.LoadXml("<Root/>"); aus - kann aber der Compiler nicht sehen.

Ebenso wird Na1 und Na2 im Model (eigene C# Klasse) angemerkt.

Absolut gleiches spiel: es sind und bleiben potentielle Null issues.
Wenn die Node Na1 nicht existiert (weil zB die Response sich geändert hat), fliegt Dir der Code um die Ohren.

Alles Situationen weswegen nullable eingeführt wurde, damit Code stabiler ist: Du musst diese Situationen prüfen.

Siehe auch meine Antworten in Mögliche Nullverweiszuweisung bzw. Dereferenzierung eines möglichen Nullverweises

A
Alesia Themenstarter:in
15 Beiträge seit 2022
vor einem Jahr

Hallo Abt,

danke für die Ausführliche Info zu dem ganzen.
Man merkt ich befinde mich in der Lernphase des ganzen und bin nicht so bewandert mit Null Prüfungen.

Ein einfacher Gedanke von mir war nun, okay mach ich das halt.
Gepackt in eine If geprüft auf is not null oder != null geht.
Aber bei den SingleNodes und einer NodeList geht es nicht, zumindest nicht so.

Ich hatte ja im Vorfeld bereits viel Zeit investiert das Problem zu finden bzw. zu er-googlen.
In den meisten Beispielen wird eben kein Null geprüft oder es kommen um es mit deinen Worten zu fassen unsinniger Code dabei rum (? oder string.emtpy z.B.)


            if(XmlRequest.DocumentElement is not null)
            { 

Ich würde gerne daraus lernen und es auch dann richtig machen.
Gibt es von dir / jemanden ein Beispiel wie ich ein eine XmlNodeList und ein SelectSingleNote auf Null prüfe?

16.806 Beiträge seit 2008
vor einem Jahr

Deswegen hab ich Mögliche Nullverweiszuweisung bzw. Dereferenzierung eines möglichen Nullverweises verlinkt. Da hab ich die Problematik erklärt, die auch hier passt.
Du hast exakt den gleichen Folgefehler, den so viele (leider aus Faulheit?) machen.


XmlElement? root = XmlRequest.DocumentElement;
if(root is not null)
{
    // AdrNr
    XmlElement node = XmlRequest.CreateElement("AdrNr");
    node.InnerText = "";
    root.AppendChild(node);
}

Nullable zwingt Dich hier nicht nur Code zu schreiben, der stabilerer ist; sondern in diesem Fall auch sauberer sowie effizienter.

A
Alesia Themenstarter:in
15 Beiträge seit 2022
vor einem Jahr

Hallo Abt,

verstanden, irgendwie habe ich im ersten durchlesen deinen Link nicht bemerkt.
Tatsächlich beschreibst du da ja auch die Vorgehensweise die passt.
Habe es kurz nach meinem Post dann auch herausgefunden.

Wenn ich deinen Post richtig verstanden habe, prüfst du, speicherst zwischen und verwendest die geprüfte Variable, macht auch Sinn.
Wie läuft das dann in einer Schleife in der die Node in meinem Beispiel erst generiert wird?


            if(idNodes is not null)
            {
                foreach (XmlNode node1 in idNodes)
                {}
}

Die idNodes werden geprüft und als geprüft erkannt, aber die node1 die erzeugt wird, kann ja potenziell InnerTexte enthalten die Null sind.
Ebenso kann es sein, dass der Node nicht vorhanden ist.
Eine Prüfung auf das vorhanden sein von der jeweiligen Node, funktioniert schon nicht, zumindest so wie ich es nun versucht habe.


XmlElement el = (XmlElement)XmlResponse.SelectSingleNode("Na2");
if (el != null)

16.806 Beiträge seit 2008
vor einem Jahr

XmlElement el = (XmlElement)XmlResponse.SelectSingleNode("Na2");
if (el != null)

ist Käse, der potentiell knall. Verhindert auch keine Warnings.

Korrekt:


XmlElement? el = XmlResponse.SelectSingleNode("Na2");
if (el is not null)

Die idNodes werden geprüft und als geprüft erkannt, aber die node1 die erzeugt wird, kann ja potenziell InnerTexte enthalten die Null sind.
Ebenso kann es sein, dass der Node nicht vorhanden ist.

Korrekt. Muss man alles prüfen.

A
Alesia Themenstarter:in
15 Beiträge seit 2022
vor einem Jahr

Die Prüfung runter bis auf den foreach Schleife, habe ich nun soweit implementiert, dank deiner Hilfestellung.
Innerhalb der Schleife muss wie du schon bestätigt hast, die Prüfung der Node und die Prüfung des Inhaltes stattfinden.


                    XmlNode? nodeCheck = node1.SelectSingleNode("Na1");
                    if (nodeCheck is not null)
                    {
                        Na1 = nodeCheck.InnerText;
                    }

                    nodeCheck = node1.SelectSingleNode("Na2");
                    if (nodeCheck is not null)
                    {
                        Na2 = nodeCheck.InnerText;
                    }

Ist das der richtige Weg aus deiner Sicht?