Laden...

ASP.NET MVC 4 - Aufruf einer neuen Seite mit Post Paramter

Erstellt von Sebastian1989101 vor 10 Jahren Letzter Beitrag vor 10 Jahren 5.886 Views
Sebastian1989101 Themenstarter:in
241 Beiträge seit 2010
vor 10 Jahren
ASP.NET MVC 4 - Aufruf einer neuen Seite mit Post Paramter

Hallo Community,

da ich noch relativ neu im Bereich ASP und Web Programmierung bin, ist mir gerade noch nicht so ganz klar, wie dies zu realisieren ist. Es geht hierbei um folgendes. Ich habe folgenden Controller zur Verfügung:


        public ActionResult Index()
        {
            return View();
        }

        public ActionResult Search(CustomerInfo model)
        {
            return View(model);
        }

Hierbei ist mir nicht ganz klar, wie ich aus der Index Seite heraus das ganze Aufrufen kann. Das Model hole ich mir derzeit wie folgt:


        $("#getCustomer").click(function () {            
            var model;
             
            $.ajax({
                url: "/api/customerValue/getcustomer/" + $('#search_filter').val(),
                type: "GET",
                contentType: "application/json;charset=utf-8",
                statusCode: {
                    200: function (data) {
                        model = data;
                    }
                }
            });
        });

Da die Methode "window.location" lediglich es ermöglicht GET-Werte zu übergeben und ich aufgrund der Dynamik in den Typen eigentlich nur ungern eine Form erzeugen würde über welcher ich das POST auslöse, würde ich gerne wissen wie das ganze nun aufzurufen wäre oder nach was ich suchen könnte um voran zu kommen.

Ich hatte zwar bereits folgende POST-Methode im Code allerdings ändert diese nun mal nicht die URL zur neuen Seite.


    function SaveNote() {
        var kdnr = $("#customerNumber").val();
        var note = $("#customerNotes").val();
        var noteData = { "CustomerNumber": kdnr, "Note": note };

        $.ajax({
            url: "/api/customerValue/SaveNote",
            type: "POST",
            data: JSON.stringify(noteData),
            contentType: 'application/json; charset=utf-8',
            statusCode: {
                200: function (data) {
                    viewModel.customerDetail(data);
                }
            }
        });
    }

WAGO Kontakttechnik GmbH & Co. KG / Software Notion
Softwareentwicklung

C# .NET with WPF, ASP, Xamarin and Unity
Personal Blog: Development Blog

M
402 Beiträge seit 2005
vor 10 Jahren

Hi...

Könntest Du bitte etwas genauer erklären was du eigentlich vor hast? Ich hab deinen Post jetzt 4mal durchgelesen und ich komm einfach nicht drauf was das werden soll. Deine 3 Code-Schnippsel haben genau nichts miteinander zu tun und helfen auch zum Verständnis nicht.

lg

Sebastian1989101 Themenstarter:in
241 Beiträge seit 2010
vor 10 Jahren

Ich versuche beim Wechsel einer Seite ein eigenes Model zu übergeben.

Die erste Seite ist die Index Seite, hier gibt es eine Methode welche Anhand eines Filters über einer SOAP-Methode alle möglichen Treffer an Kunden liefert. Dies ist der 2te Code Snippet im ersten Post. Und anschließend habe ich im JavaScript in der Variable "model" mein Datenmodel bzw. meine Datenmodels - ist ja ein Array.

Nun soll eine Navigation zur Seite mit der Ausgabe der Suchergebnisse stattfinden, diese Seite erwartet als Model die zuvor geladenen Datenmodels. Dies zeigt die Zeile "public ActionResult Search(CustomerInfo[] model)" im ersten Code Snippet.

Und mir ist jetzt nicht genau klar wie exakt dieser Vorgang abläuft. Wie bekomme ich nun das Array an CustomerInfo's aus dem JavaScript per POST an der neuen Seite übergeben sprich an meiner "ActionResult Search(CustomerInfo[])"-Methode.

Der letzte Code Snippet zeigt wie ich dies bei einer Funktionalität gelöst habe, welche nicht die URL wechseln soll. Den das klappt nicht mit $.ajax, dass die URL gewechselt wird und dabei die Models als Parameter übergeben werden.

WAGO Kontakttechnik GmbH & Co. KG / Software Notion
Softwareentwicklung

C# .NET with WPF, ASP, Xamarin and Unity
Personal Blog: Development Blog

16.806 Beiträge seit 2008
vor 10 Jahren

Der Controller hat kein HttpPost-Attribut, dass er von HTTPPost aufgerufen wird; damit ist HttpGet der bevorzugte Aufruf.

Wie man mit HTTP Post und Get umgeht, gehört zu den Grundlagen der Webprogrammierung.
Siehe [Hinweis] Wie poste ich richtig? 1.1 und 1.1.1

Das jQuery-Gedöhns sieht nach einer ziemlich alten Variante aus; hat nichts mit jQuery 1.8 oder 1.9 mehr zutun.
Als ContentType definierst Du json; lieferst aber ein ActionResult und damit ein normalen, gerenderten Content zurück, der text/html entspricht.

Und nu wirds nochmal Zeit, dass Du Dich damit beschäftigst, wie ASP.NET MVC funktioniert und die Grundlagen erlernst.


Und natürlich kannst Du nicht einfach per jQuery ein Model an den Controller schicken und hoffen Du kriegst so Deine neue Seite. Auch das sind Grundlagen, wie Webanwendungen und HTTP funktioniert und wie Browser damit arbeiten.

Wie man korrekt mit Seiten arbeitet, die die URL nicht wechseln zeigt jQuery Mobile.
Aber das ist vollkommener Schmarn und macht zu 99% nur Probleme aufgrund der immer wieder strenger werdenen Browser-Sicherheitsfeatues wie XSS.

Wenn Du eigentlich einfach nur gewisse Teile einer Seite ersetzen willst, wie einen Status oder irgendein einzelnes Element, dann musst Du Dich etwas anders und genauer ausdrücken.
Aber auch dies ändert an der Tatsache nichts, dass Du das völlig falsch angehst, weil Du offensichtlich einfach rumprobierst anstatt nachzulesen, wie es korrekt funktioniert.

Und man kann auch nicht einfach eine Collection an einer Action empfangen, ohne, dass dies durch gewisse Tricks in HTML ermöglicht wird. Hier muss man mit einem index, numerischen Werten und den Form-Attributen name und id arbeiten.
=> Grundlagen HTML.

Sebastian1989101 Themenstarter:in
241 Beiträge seit 2010
vor 10 Jahren

Mich wundert eine solche Antwort von dir etwas Abt, da ich eigentlich von deinen vorherigen Posts den Eindruck hatte das es auch Menschen gibt die etwas Sinnvolles Posten.

Schön das es zu den Grundlagen gehört zu wissen wie GET und POST Funktionieren und die sind mir auch soweit klar. Dass die Form des jQuery nicht zu 1.8 gehören soll bin ich mir auch nicht sicher, da diese in exakt jener Dokumentation stehen.

Und dafür dass der Controller kein POST können soll: Mit den 3ten Code Snippet kann ich ohne Probleme das Model an den Controller übermitteln und ich könnte auch die View nehmen und anschließend mittels $('#content').html(content) zuweisen, nur ändert dabei nun mal nicht die URL für eine spätere Browser Navigation.

Ich versuche gerade die Navigation in einem bestehenden System einzubringen und dabei auch gleich Knockout raus zu bekommen (aktuell basiert das System im übrigen auf etwas was von dir vor einigen Monaten meinem Kollegen empfohlen wurde). Nun soll halt noch die Navigation mit einfließen und aufgrund der Untransparenz will ich gleich Knockout mit entfernen.

BTT: Solange nicht die URL geändert werden soll gelingt es mir schon das Model zu übergeben und zu nutzen, aber die Navigation soll nun mal mit rein. Im Ablauf soll am ende das ganze wie folgt aussehen: Auslesen der Daten vom Service -> Wenn OK Navigation zur neuen Seite mit Übergabe der Daten als Model.

Edit:
Hier wäre noch jemand der es so gelöst hat wie es auch bei mir Funktionieren würde (nur fehlt dort eben das wechseln der URL zu einer neuen Seite):
http://stackoverflow.com/questions/14878151/mvc-4-partialviewresult-caching-on-jquery-post

WAGO Kontakttechnik GmbH & Co. KG / Software Notion
Softwareentwicklung

C# .NET with WPF, ASP, Xamarin and Unity
Personal Blog: Development Blog

16.806 Beiträge seit 2008
vor 10 Jahren

Mich wundert eine solche Antwort von dir etwas Abt, da ich eigentlich von deinen vorherigen Posts den Eindruck hatte das es auch Menschen gibt die etwas Sinnvolles Posten.

Weil das hier ein typischer Thread für "ich probier einfach mal was aus, sch* auf die Doku. Irgendjemand wird schon helfen." ist.

Schön das es zu den Grundlagen gehört zu wissen wie GET und POST Funktionieren und die sind mir auch soweit klar. Dass die Form des jQuery nicht zu 1.8 gehören soll bin ich mir auch nicht sicher, da diese in exakt jener Dokumentation stehen.

jQuery Ajax sollte seit 1.8 immer über die events done(), .always() oder .fail() bedient werden. Du arbeitest hier nach dem Status-Code, was man unter 1.5 noch gemacht hat. In der Doku dazu steht folgendes:

// Assign handlers immediately after making the request,

// and remember the jqxhr object for this request

var jqxhr = $.ajax( "example.php" )

    .done(function() { alert("success"); })
    .fail(function() { alert("error"); })
    .always(function() { alert("complete"); });
 
// perform other work here ...

// Set another completion function for the request above
jqxhr.always(function() { alert("second complete"); });


Für POST gibts sogar das vorgeferigte $.post();

Und dafür dass der Controller kein POST können soll: Mit den 3ten Code Snippet kann ich ohne Probleme das Model an den Controller übermitteln und ich könnte auch die View nehmen und anschließend mittels $('#content').html(content) zuweisen, nur ändert dabei nun mal nicht die URL für eine spätere Browser Navigation.

Er kann es; ich habe von bevorzugt geredet. Hinzu kommt aber, dass bei POST mehr Daten verschickt werden können, als bei GET. Und gerade das passiert oft bei Ajax-Anfragen; GET Anfragen mit zu langen Query-Inhalten würden einfach unter den Tisch fallen oder einen Fehler auslösen.

Und natürlich ändern Ajax-Anfragen NICHT die URL des Browsers - genau das ist das Ziel von Ajax-Anfragen.
Wenn Du Dir anschaust, was Ajax überhaupt ist, dann wird Dir dessen Prinzip auch klar.

Ich versuche gerade die Navigation in einem bestehenden System einzubringen und dabei auch gleich Knockout raus zu bekommen (aktuell basiert das System im übrigen auf etwas was von dir vor einigen Monaten meinem Kollegen empfohlen wurde). Nun soll halt noch die Navigation mit einfließen und aufgrund der Untransparenz will ich gleich Knockout mit entfernen.

Eigentlich verschiebt sich das Web in Richtung Knockout. Für MVC gibts sogar KnockoutMVC das den Aufwand des Entwicklers unfassbar (in Zusammenhang mit HTML5) erleichtert bzw. minimiert.

BTT: Solange nicht die URL geändert werden soll gelingt es mir schon das Model zu übergeben und zu nutzen, aber die Navigation soll nun mal mit rein. Im Ablauf soll am ende das ganze wie folgt aussehen: Auslesen der Daten vom Service -> Wenn OK Navigation zur neuen Seite mit Übergabe der Daten als Model.

Eine Webseite funktioniert nicht wie Windows Forms oder WPF.
Man muss als Web-Entwickler ganz anders denken.

Der Ablauf sollte wie folgt sein:
-> Request auf seite X
-> Auslesen der Daten

  • Wenn Daten korrekt, dann View dieser Daten
  • Wenn Daten nicht korrekt dann return auf die Index-Seite mit Fehlermeldung (TempData-Array und nicht ViewData des aktuellen Controllers verwenden!) weiterleiten

Aber Dein stukturellese Vorhaben ist so bei Webanwendungen nicht möglich.
Zum einen aufgrund des Aufbaus an für sich und zum anderen die Sicherheitsrichtilien von Browsern im Umgang mit XSS bzw. Javascript.

Sebastian1989101 Themenstarter:in
241 Beiträge seit 2010
vor 10 Jahren

Was bietet den Knockout für Vorteile? Bisher konnte ich nur Nachteile Feststellen was aber evtl. auch daran liegt das ich eigentlich kein Web Entwickler bin wie du ja bereits sagtest.

Klar könnte ich erst die Navigation machen und anschließend dort das Loading triggern (würde sogar Funktionieren so hatte ich es zuerst). Allerdings Funktionieren in diesem Fall die ganze Load-Animationen nicht da der Browser ja nur Synchron ist und die Anfrage das fester mehr oder weniger freezt.

Und zu deinen ersten Satz: Ja Web-Entwicklung ist für mich fast immer Try&Error. Wenn ich wissen würde nach was ich in der Doku suchen müsste würde ich dort gucken aber ich habe nicht mal ein Ansatz unter was so eine Thematik zu finden wäre.

Edit: Was mir gerade noch auffällt und was diene Aussage schon etwas arg wieder spricht: Warum kann ich einer View den ein Model als Parameter übergeben? Klar könnte ich ihn an der Stelle Statisch ein Model übergeben was Funktionen und Daten bereitstellt. Aber normalerweise ist doch alles dynamisch im .NET, warum sollte dies die Ausnahme bilden.

WAGO Kontakttechnik GmbH & Co. KG / Software Notion
Softwareentwicklung

C# .NET with WPF, ASP, Xamarin and Unity
Personal Blog: Development Blog

16.806 Beiträge seit 2008
vor 10 Jahren

Was bietet den Knockout für Vorteile? Bisher konnte ich nur Nachteile Feststellen was aber evtl. auch daran liegt das ich eigentlich kein Web Entwickler bin wie du ja bereits sagtest.

Welche Nachteile meinst Du? Vielleicht ein Umsetzungsfehler.
Vorteil ist, dass es unheimlich einfach ist modelle zu füllen, um diese zB via Ajax an eine Action zu schieben. Es bringt die Bindung von WPF quasi ins Web.

Zudem kann es problemlos mit anderen Bibliotheken verwendet werde.

Allerdings Funktionieren in diesem Fall die ganze Load-Animationen nicht da der Browser ja nur Synchron ist und die Anfrage das fester mehr oder weniger freezt.

Es kann sich ja hier eh nur um eine Animation handeln, dass derzeit etwas geladen wird; und das geht auch bei einem normalen Request.
Problem ist nur, dass sie nicht weg geht, wenn das Resultat in einem neuen Fenster geöffnet wird.
Aber ja: ein Tod musst sterben.

Edit: Was mir gerade noch auffällt und was diene Aussage schon etwas arg wieder spricht: Warum kann ich einer View den ein Model als Parameter übergeben? Klar könnte ich ihn an der Stelle Statisch ein Model übergeben was Funktionen und Daten bereitstellt. Aber normalerweise ist doch alles dynamisch im .NET, warum sollte dies die Ausnahme bilden.

Ähm.. man kann jeder View ein Model übergeben. Das ist normal.
Untypisiert Daten an eine View zu übergeben stinkt zum Himmel. Oder was meinst Du?

Sebastian1989101 Themenstarter:in
241 Beiträge seit 2010
vor 10 Jahren

Ohne Knockout:


<div id="content" align="center">
    <div class="datagrid">
        @foreach (var customer in Model)
        {
            <table>
                <tbody>
                    <tr>
                        <td rowspan="2" style="padding: 0px 10px">
                            <button id="KNDbutton" class="customerButton">@customer.CustomerNumber</button>
                        </td>
                        <td style="font-weight: bold; padding: 10px 5px 2px;">
                            @if  (!string.IsNullOrEmpty(customer.Title) || !string.IsNullOrEmpty(customer.FirstName) || !string.IsNullOrEmpty(customer.LastName)) {
                                <label>@customer.Title @customer.FirstName @customer.LastName</label>
                            }
                        </td>
                    </tr>
                    <tr>
                        <td style="width: 300px; padding: 0px 5px 10px; border-right: 1px solid #006699">
                            <label>@customer.Street @customer.HouseNumber</label><br />
                            <label>@customer.PLZ @customer.City</label><br />
                            
                            @if (!string.IsNullOrEmpty(customer.Mail)) {
                                <a href="mailto:@customer.Mail">@customer.Mail</a><br />
                            }
                            
                            @if (!string.IsNullOrEmpty(customer.Tel1)) {
                                <a href="tel:@customer.Tel1">@customer.Tel1</a><br />
                            }
                        </td>
                        <td style="width: 170px; padding: 0px 5px 0px 16px;">
                            <b><label>MyNexiu Account: </label></b><br />
                            Login: <label>@customer.CustomerNumber</label><br />
                            Passwort: <label>@customer.Password</label><br />
                        </td>
                    </tr>
                </tbody>
            </table>    
        }
    </div>
</div>

Mit Knockout:


<div id="content" align="center">
    <div class="datagrid">
        <span data-bind="template: {name: 'customerTemplate', foreach: customer}" />
        <script id="customerTemplate" type="text/html">
            <table>
                <tbody>
                    <tr>
                        <td rowspan="2" style="padding: 0px 10px">
                            <a class="KNDid" data-bind="attr: { 'data-customer-id': CustomerNumber }"><button id="KNDbutton" data-bind="text: CustomerNumber" class="customerbutton"/></a>
                        </td>
                        <td style="font-weight: bold; padding: 10px 5px 2px;">
                            <div data-bind="if: Title || FirstName || LastName">
                                <label data-bind="text: Title" /> <label data-bind="text: FirstName" /> <label data-bind="text: LastName" />
                            </div>
                        </td>
                    </tr>
                    <tr>
                        <td style="width: 300px; padding: 0px 5px 10px; border-right: 1px solid #006699">
                            <label data-bind="text: Street" /> <label data-bind="text: HouseNumber" /><br />
                            <label data-bind="text: PLZ" /> <label data-bind="text: City" /><br />
                            <div data-bind="if: Mail">
                                <a data-bind="attr: {href: 'mailto:' + Mail }">                                
                                    <label data-bind="text: Mail" />
                                </a><br />
                            </div>
                            <div data-bind="if: Tel1">
                                <a data-bind="attr: {href: 'tel:' + Tel1 }">                                
                                    <label data-bind="text: Tel1" />
                                </a>
                            </div>
                        </td>
                        <td style="width: 170px; padding: 0px 5px 0px 16px;">
                            <b><label>mynexiu account:</label></b><br />
                            <div data-bind="if: CustomerNumber">Login: <label data-bind="text: CustomerNumber" /><br /></div>
                            <div data-bind="if: Password">Passwort: <label data-bind="text: Password" /></div>
                        </td>
                    </tr>
                </tbody>
            </table>
        </script>
    </div>
</div>

Also da finde ich das erste doch schon arg Übersichtlicher und Strukturierter. Zusätzlich fliegen Exception im Fehlerfall direkt im Browser Fenster und werden nicht einfach durch nichts tun überdeckt (gerade dies macht besonders Spaß bei der Fehlersuche).

Bzgl. der Load-Animation: Wie soll die den bitte Ihre tat Fortsetzen wenn, das Browser Fenster durch das Laden einer neuen Seiten im freeze Zustand ist? Selbst GIF-Grafiken bleiben in diesem Falle stumpf stehen.


        $("#getCustomer").click(function () {
            $("#loading").css({ 'display': 'block' });
            window.location = '/Customer/Search/' + $("#filter").val();
        });

Führt dazu, dass die Grafik im "loading"-Div einfriert solange die neue Seite am Daten laden ist. Hier die Methode zum laden:


        public async Task<ActionResult> Search(string filter)
        {
            CustomerInfoDto[] data = await ApplicationManager.ServiceManager.GetCustomerListAsync(filter);
            return View(data);
        }

Oder ist das auch das falsche Vorgehen? Ist doch jetzt genauso wie du sagtest, Seite wechseln und beim wechseln die Daten laden.

WAGO Kontakttechnik GmbH & Co. KG / Software Notion
Softwareentwicklung

C# .NET with WPF, ASP, Xamarin and Unity
Personal Blog: Development Blog

16.806 Beiträge seit 2008
vor 10 Jahren

Ja gut - genau so macht mans eben mit MVC und Knockout nicht 😉
Das ist Plain Knockout in einer nicht wirklich gut umgesetzten Variante.

Beispiele, von sauberen Umsetzungen, gibts zB unter
http://knockoutmvc.com/ClickCounter
Ich würde aber nicht alles über Knockout lösen; gerade wenns eigentlich nur Daten innerhalb des Browsers betrifft. Da sind die Requests ja dann unnötig.

Ich verwende Wartefenster, wenn der Request mal länger dauern würde. Bei einer Suche verwende ich folgendes Prinzip:

  1. Request von Index auf die Suchseite (Volltextsuche) auf SearchResults
  2. Die Action SearchResults bekommt den Query, startet einen Hintergrund-Thread mit einer ID.
    Anschließend wird die View an den Client zurück geschickt, die eine Animation enthält, dass derzeit das Suchresultat ermittelt wird.

Sobald die Suche des Hintergrund-Threads fertig ist pusht die ASP.NET MVC Anwendung via WebSocket (SignalR) das Ergebnis zum Client.
Die SignalR Instanz des Browser nimmt das Ergenis entgegen und zeigt dieses dann an.

Bei schnellen Suchen kann es passieren, dass der Client noch gar nicht bereit ist und das Resultat dann ins Leere geschickt wird.
Hier muss man entweder ein Idle einbauen oder auf das Verbinden des Browsers warten.

Das async bringt Dir hier nicht viel, weil es was anderes tut als Du gern hättest. Das könntest Du eigentlich genauso gut weglassen und es geht trotzdem. So ticken Webanwendungen halt nicht.
Es ermöglicht Dir eigentlich nur Hintergrundanfragen und viel Compiler Magic. Ich verwende async/await zB gar nicht, weil ichs einfach unübersichlich und schlecht zu warten finde.
Wenn ich sowas brauch mach ich das noch brav mit Threads und alles so, dass ich das auch handhaben und warten kann.

Sebastian1989101 Themenstarter:in
241 Beiträge seit 2010
vor 10 Jahren

Gut... das sieht ja schon ganz anders aus als es der Kollege umgesetzt hat mit Knockout. Allerdings ist das auch noch mehr das, was vom Studio als MVC 4 ASP angelegt wird. Den demnach wäre es eher so: http://knockoutjs.com/examples/clickCounter.html

WAGO Kontakttechnik GmbH & Co. KG / Software Notion
Softwareentwicklung

C# .NET with WPF, ASP, Xamarin and Unity
Personal Blog: Development Blog