Laden...

Razor Page AJAX Call Problem mit return Page()

Erstellt von sene vor 2 Jahren Letzter Beitrag vor 2 Jahren 436 Views
S
sene Themenstarter:in
5 Beiträge seit 2014
vor 2 Jahren
Razor Page AJAX Call Problem mit return Page()

Hallo,
ich versuche mich gerade an einer Razor Webanwendung, soll eigentlich auch nur ein kleineres Projekt mit so ca. 10 Seiten werden.

In meiner ersten Seite gebe ich nun eine Liste von Daten zurück und stelle diese dar, ein kleines Suchformular was die Liste durchsucht habe ich bereits erfolgreich als POST Übergabe eingefügt und funktioniert super. die Suche schaut so aus:


<form class="form-inline" method="post" >
            <input type="text" class="form-control mb-2 mr-sm-2" asp-for="SearchString" placeholder="Suche" />
            <button type="submit" asp-page-handler="Search" class="btn btn-dark mb-2">Suche</button>
        </form>


        public IActionResult OnPostSearch()
        {
            if (!ModelState.IsValid)
                return Page();

            AllPersonGroups = DBFunctions.GetPersonGroups(cn);
            if (!string.IsNullOrEmpty(SearchString))
            {
                PersonGroups = AllPersonGroups.Where(x => x.Name.Contains(SearchString, StringComparison.OrdinalIgnoreCase)).ToList();
                if (PersonGroups.Count ==1 )
                {
                    DetailData = PersonGroups[0];
                }
            }
            else
            {
                PersonGroups = AllPersonGroups;
            }
            return Page();
        }

Nun möchte ich in der Liste auf eine Zeile klicken können und dort dann die ID die geladen werden soll zurückschicken, da ich keine ActionLinks oder Buttons benutzen wollte habe ich mich dafür entschieden das ganze als AJAX Call zu nutzen, dieser funktioniert auch und sieht so aus:


$(".clickable-row").click(function () {
            var id = $(this).data("target");
            //alert(id);
            console.log("Selected Persongroup with id" + id);
            $.ajax({
                type: "POST",
                url: "?handler=LoadById",
                headers: { "RequestVerificationToken": $('input[name="__RequestVerificationToken"]').val() },
                data: { LoadID: id },
                success: function (data) {
                    console.log("success loading persongroup");
                    console.log(data);
                },
                error: function() { alert('A error occurded .... '); }
            });
        });

Es wird bei Click auf eine Row in C# folgende Funktion ausgeführt:
LoadID ist gefüllt DetailData wird erstellt - alles super ... eigentlich 😠


public IActionResult OnPostLoadById()
        {
            if (!ModelState.IsValid)
                return Page();

            if (LoadID > 0 )
            {
                //korrekte Detaildaten laden ... 
                AllPersonGroups = DBFunctions.GetPersonGroups(cn);
                PersonGroups = AllPersonGroups;
                DetailData = AllPersonGroups.Find(x => x.ID == LoadID);
            }

            return Page();
        }

Mein Problem ist jetzt, dass ich als Antwortdaten auf meinen AJAX Call die komplette Seite zurückbekomme, eigentlich will ich die Seite ja nur neu laden und die Detaildaten neu laden. Also so wie es die Suchform auch macht. Ich habe da jetzt wohl ggf. nen falschen Denkansatz drin oder stehe irgendwie auf dem Schlauch....
Muss ich anstatt nen return Page() zu machen irgendwie nen Refresh antriggern oder wirklich jetzt per jQuery irgendwie das komplette DOM aus meinen Antwortdaten neu bauen ? Sind in den Antwortdaten eigntlich auch die Detaildaten um die es mir eigentlich geht enthalten?
Natürlich kann ich auch nur die Daten dieser einen "PersonGroup" returnen, aber habe ich dann in der cshtml noch vollen Zugriffe mit @Model.Detaildata.Name usw. oder geht das dann nimmer.
Vielleicht kann mir einer kurz helfen und mich auf den richtigen Weg zurückschubsen 😉 Ggf. reichen wahrscheinlich nur ein paar Stichwörter mit denen ich Google befeuern kann 😁

Vielen Dank schonmal!
MfG Sebastian

mfg
sebastian

16.842 Beiträge seit 2008
vor 2 Jahren

Viele Fehler zu erkennen, angefangen bei der Art und Weise, über die Architektur bis hin halt zum Code selbst.
Tipp bevor Du weiter machst: les Dir die ASP.NET Doku durch und schau Dir an, wie man so eine Anwendung strukturiert; schau Dir vielleicht auch andere Beispielanwendungen an, zB von Jeff Fritz und Steve Sanderson, die beide viele Demos Online haben.

Aber fangen wir bei Deiner Frage an:
Prinzipiell liefert man Json (über die Standard Methoden) nicht mit Page() aus, sondern mit JsonResult, siehe dazu auch die Einstiegsdoku von ASP.NET

url: "?handler=LoadById",

Damit rufst Du die aktuelle Seite auf mit einem Zusatzparameter. Gar keine gute Idee.
Jeder Endpunkt in einer ASP.NET Anwendung sollte genau eine Art von Rückgabe liefern.

Mach Dir also ne neue Action oder neue Page, in der Du das Json zurück lieferst.
Alles in eine Page zu hauen ist eine gänzlich schlechte Idee.

PS: Ajax() ist seit vielen Jahren obsolete (wie eigentlich jQuery selbst auch).

S
sene Themenstarter:in
5 Beiträge seit 2014
vor 2 Jahren

Guten Morgen,
erstmal Danke für deine Antwort.
Das was ich oben gepostet habe ist natürlich noch net so wirklich fertig, sind auch nur erstmal erste Versuche das "System zu verstehen" 😁 Danke für die Tipps mit den Dokus und Samples - schau ich mir an.

Das ich eigentlich für mein Vorhaben eine neue Page aufmachen müsste weis ich, wollte aber trotzdem dieses in einer einzigen Page lassen - weil die Daten eigentlich zusammengehören und es immer n bissl doof ist ne einzige Page mit ner Selektion von Nr - Name zu haben und die nächste Page dann die Details zeigt - wollte ich halt auf dieser Seite ne kleine Liste bauen und dann daneben die Detaildaten zum Bearbeiten 😉

Was mich nun eigentlich verwirrt hat, war halt das ich in dem Such Formular, welches ich mit nem Post an die gleiche Seite zurückschicke, dann im "Back-Code" ja nur die Daten verändere ein return Page() mache und dann die Seite neu ausgeliefert wird (mit angepassten Daten). Nun wollte ich halt das gleiche auch machen indem ich auf eine Zeile in meiner Liste klicke, die angeklickte ID zurückschicke und dann mit return Page() die Seite neu lade. Und da hängts ja nun eigentlich, weil jetzt das return Page() nur die Page als Antwort in den AJAX Call schiesst und net die Seite neu lädt.

Lange Rede kurzer Sinn, gibt es eigentlich ne Möglichkeit das so zu machen wie ich das gern hätte, oder sollte ich wirklich ne einzige Page machen mit ner Selection Liste der Daten und die nächste Page mit den Detaildaten?

Nächste Frage wenn AJAX bzw. jQuery so obsolet ist, was verwende ich dann? In meinen Fragen an Google taucht das trotzdem ständig wieder auf 😁 und irgendwie muss ich ja im Frontend immer mal n bissl was anpassen oder wieder zurückschicken und ggf. das auch ohne eine form zu haben.

Vielen Dank und mfg Sebastian

mfg
sebastian

16.842 Beiträge seit 2008
vor 2 Jahren

Lange Rede kurzer Sinn, gibt es eigentlich ne Möglichkeit das so zu machen wie ich das gern hätte

Du fragst, wie man es macht und bekommst eine Antwort. Du sagst nun quasi "mir egal wie es richtig geht, ich will es so machen wie ich es will".
Nun, was soll man Dir da antworten? Dann musst Dir halt zig Workarounds bauen, dann wirds schon gehen 😉
Ne Schraube sollte man auch eher rein drehen, aber klar; kannst auch nen Hammer nehmen und drauf klopfen. Ist dann sicherlich irgendwann drin, aber halt nicht so, wie es gedacht ist - und weißt nicht, wie lange es hält.

Das ich eigentlich für mein Vorhaben eine neue Page aufmachen müsste weis ich, wollte aber trotzdem dieses in einer einzigen Page lassen - weil die Daten eigentlich zusammengehören und es immer n bissl doof ist ne einzige Page

Keiner sagt aber, dass Du eine neue Page aufmachen musst.
Ich hab gesagt, dass Du einen Endpunkt brauchst und zB. eine Json-Antwort lieferst, die Du dann per JavaScript in Deinem Client aktualisierst.
Eine Page() ist in ASP.NET halt dafür da, dass Du auch eine vollständige Page (normalerweise mit Layout) zurück lieferst. Das Ding ist aber nicht dazu da, dass Du die komplette Seite (mit Layout) an den Client sendest und den gesamten DOM ersetzt, so ist das nicht gedacht.

Du hast halt einen Technologiebruch zwischen Server Side und Client Side. Den wirst Du auch mit Puzzle-Arbeiten nicht verhindern können, der ist halt da und damit musst umgehen.

Vielleicht solltest nochmal nen Blick in die Doku werfen, wie Razor Pages eigentlich so funktionieren und angewendet werden sollen - und wieso das nicht mit Deinem Gedankengang passt 😉

Was mich nun eigentlich verwirrt hat, war halt das ich in dem Such Formular, welches ich mit nem Post an die gleiche Seite zurückschicke, dann im "Back-Code" ja nur die Daten verändere ein return Page() mache und dann die Seite neu ausgeliefert wird (mit angepassten Daten).

Im "Back Code" veränderst gar nichts, weil wir mit HTTP überhaupt keine Verbindung zwischen Server und Client haben. HTTP ist ein verbindungsloses Protokoll.
Webanwendungen funktionieren vollkommen anders als Desktopanwendungen; hier gibt es auf dem Server keine Zustandsinfo, was der Client gerade so macht.

Was Du im Endeffekt machst ist ein bisschen zu programmieren, wie man es mit WebForms 2003 gemacht hat (und nen bisschen was von ner PHP Denkweise zeigt): Formular-Daten an einen Endpunkt schicken und HTML Elemente zurück bekommen und den DOM ersetzen.
Willst Du das mit Razor Pages immer noch so machen, dann darfst Du keine Page zurück geben (weil die eben das gesamte HTML zurück liefert, und nicht nur Teilausschnitte), sondern Partial Pages.
Bei Partial Pages pflegst um ungünstigsten Fall das HTML auf der Serverseite halt an mehreren Stellen; außer Du hast eben ne gute Struktur an Razor-Templates, womit man das verhindern kann.
Das Forum hier verwendet auch viele solcher Razor Templates, um Redundanz der Struktur / des Stylings zu vermeiden.

Besser wäre es aber so das Ding umzusetzen, wie es gedacht ist und das Framework vorsieht 🙂
Ne Page() ist die gesamte Ansicht einer Seite. Willst Du Teilausschnitte verändern, dann hast Du einen Json-Endpunkt, klassisches REST zB.
Zur Not eben ne Partial Page ausliefern.

In meinen Fragen an Google taucht das trotzdem ständig wieder auf 😁 und irgendwie muss ich ja im Frontend immer mal n bissl was anpassen oder wieder zurückschicken und ggf. das auch ohne eine form zu haben.

Ich kenne Deine Google Begriffe nicht, aber prinzipiell geht der Trend zu SPAs bzw PWA, also ohne Server Side Anteile (außer API). Hier gibts in der .NET Welt Blazor dazu.
Für Server Side gibts natürlich immernoch berechtigte Szenarien, den dynamischen Anteil würde man dann aber eher mit schlanken progressive Frameworks wie vuejs umsetzen.
Hier hast Du aber wie gesagt immer den Technologiebruch, den Du halt korrekt umsetzen musst.
Aber ganze HTML Blöcke (DOM Replacing), wie Du es angehst, ersetzt man eigentlich seit vielen Jahren in keiner Technologie mehr; u.a. auch weil es anfällig für Browser / Content Angriffe ist (XSRF).

S
sene Themenstarter:in
5 Beiträge seit 2014
vor 2 Jahren

Du fragst, wie man es macht und bekommst eine Antwort. Du sagst nun quasi "mir egal wie es richtig geht, ich will es so machen wie ich es will".

OK 😁 So sollte das net rüberkommen - sorry!

Im "Back Code" veränderst gar nichts, weil wir mit HTTP überhaupt keine Verbindung zwischen Server und Client haben. HTTP ist ein verbindungsloses Protokoll.

War doof ausgedrückt, meinte natürlich das ich die Seite mit angepassten Daten aufgrund der übermittelten Werte neu sende 😁

Aber um das Thema abzuschliessen:
Ich halte mich jetzt erstmal relativ weit an die Doku und baue das Projekt mal fertig, auch wenn dann einige Handlings noch nicht ganz wie gewünscht implementiert sind - dadurch lerne ich glaub erstmal noch relativ viel dazu. Und wenn das ganze dann fertig ist, kann ich mir immer noch Gedanken dazu machen ob und wie ich nochmal einzelne "Features" umsetze und die "Technologiebrüche" implementiere.

Vielen Dank schonmal für das zurechtrücken auf den richtigen Weg 😉 und die Zeit mir zu antworten!

mfg
sebastian

16.842 Beiträge seit 2008
vor 2 Jahren

War doof ausgedrückt, meinte natürlich das ich die Seite mit angepassten Daten aufgrund der übermittelten Werte neu sende 😁

Wenn Du nur Teile der Seite aktualisieren willst, dann mach das über nen JavaScript Request, antworte mit Json und ersetze die entsprechenden Platzhalter im DOM.
Willst Du die gesamte Seite neu laden, dann lass den JavaScript-Teil weg und mach es über einen Server-Request.

Aber lade nicht über JavaScript die gesamte Seite neu und ersetze den kompletten DOM; das ist Käse (unabhängig, welche Technologien verwendet werden).