Casablanca: ajax - Bad Request

0 48

ajax - Bad Request

  1. 0
    1. 0
      1. 0
        1. 0
          1. 0
            1. 0
              1. 0
                1. 0
                  1. 0
                    1. 0
                      1. 0
                        1. 0
                          1. 0
                            1. 0
                              1. 0
  2. 0
    1. 0
      1. 0
        1. 0
          1. 0
            1. 0
              1. 0
                1. 0
                  1. 0
          2. 0
        2. 0
          1. 0
            1. 0
              1. 0
                1. 0
                2. 0
          2. 0
            1. 0
            2. 0
              1. 0
                1. 0
                  1. 0
                2. 0
                  1. 0
                    1. 0
                      1. 0
                        1. 0
  3. 0
  4. 0
    1. 0
      1. 0
        1. 0

Hallo Forum,

ich habe eine Problem mit einem api-Methoden-Aufruf via ajax. Ich bekomme da die Meldung Bad Request:

    $(document).ready(function() {
        $("#form1").submit(function (e) {
            $.ajax({
                type: "GET",
                url: 'http://localhost:4627/api/MyController/Edit',
                contentType: "application/json; charset=utf-8",
                dataType: 'json',
                data: { content: $('#form1').serialize() } ,
                cache: false,
                success: function (data) {
                    alert(data);
                },
                error: function (x, status, error) {
                    alert("Error: " + error);
                }
            });
          
        });
    });
        [HttpPost]
        [ActionName("Edit")]
        public IHttpActionResult Put(FormDataCollection content)
        {
             ....
        }

Sieht da jemand etwas fehlerhaften? Danke im Voraus.

Hruß

  1. Tach!

    ich habe eine Problem mit einem api-Methoden-Aufruf via ajax. Ich bekomme da die Meldung Bad Request:

    Schau in die Console des Browser und auch in den Netzwerktab nach der genaueren Meldung. Unter Umständen auch mal einen anderen Browser verwenden, um eine anders formulierte und damit vielleicht verständlichere Meldung zu bekommen. Ich vermute ein CORS-Problem. Kann aber auch alles mögliche andere sein.

    dedlfix.

    1. Hallo,

      da ist nichts besonderes zu sehen. Wie kann da das Cors-Problem beheben. Das Ganze lief auf einem anderen Rechner problemlos und ich habe morgen eine Präsentation.

      Gruß Error

      Folgende Beiträge verweisen auf diesen Beitrag:

      1. Tach!

        da ist nichts besonderes zu sehen.

        Bitte auch im Console-Tab schauen. Und hier im Netzwerktab mal die Zeile mit dem Request anklicken und prüfen, ob da was besonderes zu sehen ist.

        Wie kann da das Cors-Problem beheben.

        Erstmal ermitteln, was die genaue Ursache ist. Ich vermute lediglich, weil ich in ähnlicher Situation 40Xer bekam. GET und POST ging, aber PUT und DELETE fehlerten. Ob das Bad Request oder eine andere Meldung war, weiß ich nicht mehr.

        Wenn es allerdings wegen CORS nicht geht, erstmal informieren, was CORS ist und dann suchen, wie man die Sendung der notwendigen Header veranlasst. Das ist ein Standard-Verfahren und es gibt Lösungswege auch für ASP.NET MVC.

        Das Ganze lief auf einem anderen Rechner problemlos und ich habe morgen eine Präsentation.

        Wenn dort kein hostüberschreitender Verkehr (inklcusive gleicher Port) stattfand, dann schlägt CORS auch nicht zu.

        dedlfix.

        1. Danke. Da es eigentlich um eine Post-Methode geht, habe ich GET durch POST ersetzt und bekomme nun einen Internal Server error:

          Error

          1. Tach!

            Danke. Da es eigentlich um eine Post-Methode geht, habe ich GET durch POST ersetzt und bekomme nun einen Internal Server error:

            Wie immer bei 500ern, Ursache finden. Diese Information wird ungern zum Browser geschickt und stattdessen nur allgmeiner Bla, der dir als Entwickler nicht hilft. Beim Apachen gibts ein error.log. Der IIS hat das nicht, und besonders nicht der Entwicklungs-Webserver. Vielleicht hat der Event-Viewer was zu erzählen. Aber vorher ...

            "You can try adding:

            GlobalConfiguration.Configuration.IncludeErrorDetailPolicy = 
            IncludeErrorDetailPolicy.Always;
            

            to your Application_Start() in the Global.asax."

            ... zitiere ich mal eine Stackoverflow-Fundstelle. Aber nach dem Fehlerfinden wieder rausnehmen! Vielleicht ist es auch in der Web.config einstellbar, dass du eine vollständige Meldung bekommst. Also, da gibts auf alle Fälle Einträge, die die Geschwätzigkeit von Fehlermeldungen beeinflusst, ich hab die nur nicht im Kopf und weiß nicht, ob sie im speziellen Fall helfen.

            dedlfix.

            1. Vielen Dank. Das ist wie verhext. Ich komme da überhaupt nicht weiter. Vor allem, weil ich bezüglich der Ursache total blind vorgehen muss.

              1. Tach!

                Vielen Dank. Das ist wie verhext. Ich komme da überhaupt nicht weiter. Vor allem, weil ich bezüglich der Ursache total blind vorgehen muss.

                Ja, das muss man meistens, solange man sie noch nicht kennt. Es gibt aber - neben den schon genannten - noch ein paar Dinge, die man tun kann, bevor man aufgibt.

                Breakpoint in die Controller-Action setzen und schauen, ob die Ausführung dort überhaupt landet oder schon vom Framework abgefangen wird.

                In der Global.asax lassen sich Methoden definieren, die zum Beispiel globale Errorhandler sind. Wie die konkret heißen musst du googeln. Auch da kannst du einen Breakpoint setzen und die Exception und ggf. deren InnerExceptions-Kette auswerten, ob du da erkenntnisgewinnende Texte findest.

                Den Unterschied zwischen der funktionierenden Maschine und der nicht funktionierenden finden. Oder die Situation exakt nachzustellen versuchen.

                dedlfix.

                1. Die Methoden In dem api-Controller werden überhaupt nicht aufgerufen. Man kommt da überhaupt nicht hin. Der Fehler passiert anscheinend im ajax selber. Ich habe eine Globale error handling definiert/programmiert (mit Log4net). Aber wie gesagt, man kommt überhaupt nicht so weit.

                  1. Tach!

                    Die Methoden In dem api-Controller werden überhaupt nicht aufgerufen. Man kommt da überhaupt nicht hin. Der Fehler passiert anscheinend im ajax selber. Ich habe eine Globale error handling definiert/programmiert (mit Log4net). Aber wie gesagt, man kommt überhaupt nicht so weit.

                    Also, es ist wohl eher anzunehmen, dass der Request auf die Reise geht und am Server ankommt. Zur Not mit dem Fiddler nachweisen/nachschauen.

                    Log4net ist nicht das Tool, das alle Fehler abfängt, solange du es nicht an einer Stelle eingebunden hast, an der alle Exceptions vorbeikommen, die nicht individuell gefangen wurden, eben wie in der Global.asax.

                    Neben dem globalen Errorhandler gibt es dort weitere Methoden, die im Lifecycle eines Requests angesprungen werden, wenn sie dort vorhanden sind. Auch solche vor dem Einleiten des Requests in die MVC-Verarbeitung und auch nach Abschluss dessen. Die eignen sich auch zum Einklinken und Testen, ob da was angesprungen wird und zur Auswertung der Daten.

                    dedlfix.

                    1. Das ist ja der Fall. Es gibt bei mir eine Zentralle Stelle, wo alle Fehler hinkommen. Abgesehen davon, ich habe gerade das Projekt auf einem anderen Rechner ausprobiert. Da läuft das Projekt auch nicht. Das funktionierende Projekt läuft staunlicherweise auch auf dem neuen Laptop nicht. Daher musste ich heute Morgen ein Neues Projekt auf dem Laptop anlegen und alles neu machen. Der Server startet, die MVC-Webseite wird als "Diese Website ist nicht erreichbar" abgebrochen. Ich habe auch mit anderen Portnummern versucht, vergeblich. Der Entwicklungsrechner ist 32bit, der Laptop 64. VS2015 ist aber auf beiden 32bit.

                      1. Tach!

                        Das ist ja der Fall. Es gibt bei mir eine Zentralle Stelle, wo alle Fehler hinkommen.

                        Und? Wird sdie angesprugen und liefert Erkenntnisse?

                        Abgesehen davon, ich habe gerade das Projekt auf einem anderen Rechner ausprobiert. Da läuft das Projekt auch nicht. Das funktionierende Projekt läuft staunlicherweise auch auf dem neuen Laptop nicht. Daher musste ich heute Morgen ein Neues Projekt auf dem Laptop anlegen und alles neu machen. Der Server startet, die MVC-Webseite wird als "Diese Website ist nicht erreichbar" abgebrochen. Ich habe auch mit anderen Portnummern versucht, vergeblich. Der Entwicklungsrechner ist 32bit, der Laptop 64. VS2015 ist aber auf beiden 32bit.

                        Was sagt die Analyse mit dem Fiddler (der von Telerik)? Siehst du damit Netzwerkverkehr? (Der Browser darf für den Fiddler nicht auf "nutze keinen Proxy" gestellt sein.)

                        Ist das alles auf demselben Recher oder auf verschiedenen mit aktivierter Firewall?

                        dedlfix.

                        1. Ja ja. Wenn das Programm läuft und egal wo ein Fehler passiert, wird es protokolliert. etwas stimmt da nicht. Während der Fiddler auf dem Entwicklungsrechner nur dann zuckt, wenn auf irgendeinen Button geklickt wird, auf dem Laptop ist der Hölle los. Da werden andauernd irgendetwas protokolliert.

                          1. Tach!

                            Ja ja. Wenn das Programm läuft und egal wo ein Fehler passiert, wird es protokolliert. etwas stimmt da nicht. Während der Fiddler auf dem Entwicklungsrechner nur dann zuckt, wenn auf irgendeinen Button geklickt wird, auf dem Laptop ist der Hölle los. Da werden andauernd irgendetwas protokolliert.

                            Irgendwas passt da nicht. Der Browser zeigt in seinem Netzwerktab eine Aktivität an. Hast du dir die mal genauer angeschaut? Welchen Grund sollte der Browser haben, dort etwas anzuzeigen, wenn er gar keinen echten Request absetzt? Außer dass er die Antwort aus dem Cache nimmt und nur pro forma dort einen Eintrag hinterlässt, was er aber bei POST, PUT und DELETE nicht kann. Der Request geht doch garantiert auf die Reise. Und du kannst diesen anklicken und die verwendeten Header sehen. Besonders anhand der vorhandenen Response sollte hervorgehen, dass der Request auf Reisen ging und beantwortet wurde. Auch dass es einen HTTP-Statuscode gibt, deutet darauf hin, dass eine HTTP-Verbindung zustande kam. Schick mal einen Request in die Botanik, dann bekommst du nach einer Weile auch einen Fehler, aber keine Response und keinen HTTP-Statuscode, weil aufgrund des nicht erfolgreichen TCP/IP-Verbindungsaufbaus das HTTP gar nicht zum Zuge kam. Dein 500er deutet draufhin, dass dein Server den zurückgeschickt hat, weil ihm irgendwas nicht passte. Wenn du aber all das in den Wind schlägst, was ich versuchen würde und in der Vergangenheit bereits versucht habe (am Ende immer erfolgreich), dann weiß ich auch nicht weiter, wie du der Ursache auf den Grund gehen kannst. Irgendetwas an dem Request gefällt dem Server nicht. Das kann durchaus auch sein, dass du den falschen Content-Type zu den Daten mitschickst und es deshalb nicht geht. ASP.NET MVC wertet den Content-Type aus, um die Daten gemäß diesem Format zu dekodieren. Es kann sein, dass du durch rumprobieren zur Lösung kommst. Aber nachschauen nach dem Fehlermeldungstext halte ich für zielführender. Dass du einen ausführlicheren Meldungstext gar nicht zu fassen bekommst, halte ich für ausgeschlossen, wenn du die üblichen Verdächtigen richtig konfigurierst.

                            dedlfix.

                            1. Ich habe unten was gefunden und gepostet.

                              1. Tach!

                                Ich habe unten was gefunden und gepostet.

                                Ja, grad gesehen und beantwortet.

                                dedlfix.

  2. Sieht da jemand etwas fehlerhaften? Danke im Voraus.

    Sieht auf jeden Fall ziemlich nach Konzeptlosigkeit aus. Wenn die Formulardaten ohnehin per jQuery serialisiert sind, lautet der hierzu passende Content-Type: application/x-www-form-urlencoded; das passt schonmal nicht zu application/json was Du sendest und serverseitig lese ich da was von FormData, das passt auch nicht.

    Wenn also serverseitig eine bestimmte Aktion laufen soll, muss 1. der entsprechende Parameter, 2. die Request-Method und 3. der gesendete Content-Type schon zusammenpassen.

    MfG

    PS: bring den Serverprozess dazu dass er Execptions abfängt und mit text/plain an den Browser schickt und nicht einfach einen 500er rauswürgt.

    1. Hallo,

      danke. Da gibt es keinen Serverprozess. Alles wird schon beim ajax-Methode beendet. Was du als Konzeptlosigkeit bezeichnest, ist leider ein Blindflug, weil mir da keine andere Möglichkeit bleibt, als nur alles auszuprobieren.

      Der Content-Type: application/x-www-form-urlencoded; kommt in den ajax-Teil? Funktioniert nicht. Wo hast du den die FormData gesehn. Das sollte eingentlich richtig sein, weil ich den Inhalt eines Formulrs an die api-Methode übergebe. Es ist zu erwähnen, dass der gleiche ajax-Methode mit einem MVC-Controller korrekt funktioniert, mit einem api-Controller aber nciht.

      Gruß

      1. Der Content-Type: application/x-www-form-urlencoded; kommt in den ajax-Teil?

        Muss nicht, weil es der Default-Content-Type ist. Und den sollte eigentlich jeder Cotroller verstehen, egal ob die Daten mit GET oder POST gesendet werden.

        Welcher Parameter wird eigentlich hier 'http://localhost:4627/api/MyController/Edit' erwartet? Da gibt es doch bestimmt eine RewriteRule wo das auf Parameter umgeschrieben wird. Normalisiert sieht das möglicherweise so aus http://localhost:4627/api?Edit=1&name=usw, einen solchen Request kannst Du mit jedem Browser machen, also einfach mal ein paar Schlüssel-Werte-Paare anhängen und natürlich den Parameter für die beabsichtigte Aktion wo ich mal annehme dass der den Namen Edit hat.

        Das wären die Grundlagen und die sind überall gleich; das Verständnis fürs c#Framework hingegen musst Du natürlich selbst aufbringen.

        MfG

        1. Also die eigentliche ajax Methode sieht so aus:

                  var result = $.post('http://localhost:4627/api/MyShop/Edit', $('#form1').serialize())
                      .success(function (data) {
                          if (data.success == true) {
                              window.location = host;
                          }
                      })
                      .error(function (error) {
                          alert("Error for edit: " + error.responseJSON.ExceptionMessage);
                      });
          

          Die Edit-Methode bekommt den editierten Inhalt eines Formulars als Übergabeparameter. Diese ajax-Version reagiert überhaupt nicht mehr, obwohl auf dem Entwicklungsrechner tadellos funktioniert. Nicht mal wirft sie eine Fehlermeldung. Sie funktioniert einfach nicht.

          Gruß

          1. Hello,

            gaht denn überhaupt ein JavaScript-Code auf dem betroffenen Host?

            Liebe Grüße
            Tom S.

            --
            Es gibt nichts Gutes, außer man tut es
            Andersdenkende waren noch nie beliebt, aber meistens diejenigen, die die Freiheit vorangebracht haben.
            1. Hallo,

              ja. Zu Anfang und beim Start des Projekt wird ein ajax-Code ausgeführt, um die anfängliche Liste auf zubauen. Diese ruft eine api-Get-Methode und holt sich die Daten aus der Datenbank und sagt sie dann an. Das Hauptproblem liegt bei api-PUT-Post und Delete-Methoden.

              Gruß

              1. Hello,

                da fällt mir noch ne ganz blöde Idee ein dazu:
                Läuft da eine Application Firewall?

                Liebe Grüße
                Tom S.

                --
                Es gibt nichts Gutes, außer man tut es
                Andersdenkende waren noch nie beliebt, aber meistens diejenigen, die die Freiheit vorangebracht haben.
                1. Hallo,

                  ich weiß es nicht. Meinst du auf dem Rechner selbst oder innerhalb von VS?

                  Gruß

                  1. Hello,

                    auf dem Rechner selbst.

                    Die Requests sollten doch ganz normal über den Netzwerkstack abgearbeitet werden, also raus aus VS ins Betriebssystem und wieder rein. Darum fragte ich ja auch schon, ob der Port überhaupt offen ist.

                    Liebe Grüße
                    Tom S.

                    --
                    Es gibt nichts Gutes, außer man tut es
                    Andersdenkende waren noch nie beliebt, aber meistens diejenigen, die die Freiheit vorangebracht haben.
          2. Sind Deine js und jsquery ressourcen alle da? Hier sind ein paar 404er Not Found zu sehen, guck mal ob der richtigen Schreibweise, da fehlt vielleicht nur die Endung .js

            jquery hat die unangenehme Eigenschaft, Fehlermeldungen zu unterdrücken.

            --
            Lieber ne lange Geschichte als ne lange Leitung!
        2. Tach!

          Welcher Parameter wird eigentlich hier 'http://localhost:4627/api/MyController/Edit' erwartet? Da gibt es doch bestimmt eine RewriteRule wo das auf Parameter umgeschrieben wird. Normalisiert sieht das möglicherweise so aus http://localhost:4627/api?Edit=1&name=usw,

          Nein. Das ist nicht Apache und PHP oder Perl, das ist IIS mit ASP.NET MVC. Da wird der Request direkt aus dem Webserver durchgereicht und die URL wird vom Framework analysiert, ohne umgeformt worden zu sein.

          einen solchen Request kannst Du mit jedem Browser machen, also einfach mal ein paar Schlüssel-Werte-Paare anhängen und natürlich den Parameter für die beabsichtigte Aktion wo ich mal annehme dass der den Namen Edit hat.

          Das wäre kontraproduktiv, weil für einen derartigen Request der Router gleich gar kein Ziel mehr findet und nur 404 antworten kann.

          Das wären die Grundlagen und die sind überall gleich;

          Nö, es gibt durchaus auch Unterschiede. Die Grundlagen sind hier lediglich HTTP. Das Umschreiben von URLs sind eine Spezialität anderenorts. Und selbst da wird solch ein Umschreiben nicht zwingend benötigt.

          dedlfix.

          1. Ich glaube ich habe etwas gefunden:

            {"Message":"Fehler","ExceptionMessage":"Es wurden mehrere Aktionen gefunden, die mit der Anforderung übereinstimmen: \r\nCreate für den Typ Client.Controllers.CarShopController\r\nEdit für den Typ Client.Controllers.CarShopController\r\nDelete für den Typ Client.Controllers.CarShopController\r\nTest für den Typ Client.Controllers.CarShopController","ExceptionType":"System.InvalidOperationException","StackTrace":" bei System.Web.Http.Controllers.ApiControllerActionSelector.ActionSelectorCacheItem.SelectAction(HttpControllerContext controllerContext)\r\n bei System.Web.Http.Controllers.ApiControllerActionSelector.SelectAction(HttpControllerContext controllerContext)\r\n bei System.Web.Http.ApiController.ExecuteAsync(HttpControllerContext controllerContext, CancellationToken cancellationToken)\r\n bei System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__1.MoveNext()"}

            Ich habe die anderen Methoden auskommentiert und nun springt die die Edit Methode an. Die Frage ist nun, wie ich die Prameterliste der Methoden ändern muss, wenn alle den gleichen Prameter erhalten.

            Gruß

            1. Tach!

              {"Message":"Fehler","ExceptionMessage":"Es wurden mehrere Aktionen gefunden, die mit der Anforderung übereinstimmen:

              Ich habe die anderen Methoden auskommentiert und nun springt die die Edit Methode an. Die Frage ist nun, wie ich die Prameterliste der Methoden ändern muss, wenn alle den gleichen Prameter erhalten.

              Na siehst du, geht doch. Das Problem ist also, dass der Request nicht eindeutig zu einer Action geroutet werden kann.

              [HttpPost]
              [ActionName("Edit")]
              public IHttpActionResult Put(FormDataCollection content)
              

              Um hierhin zu kommen, muss es ein Request mit der Methode POST sein, festgelegt durch das Attribut HttpPost. Und der Name der Action war eigentlich Put, wurde aber durch das ActionName-Attribut mit Edit überschrieben. Wenn du eine solche Kombination noch bei anderen Actions hast, ist das nicht mehr eindeutig. Du musst da entweder die Methode ändern oder den Namen der Action.

              dedlfix.

              Folgende Beiträge verweisen auf diesen Beitrag:

              1. Ich habe das nicht ganz verstanden. Die Methoden sind ja wie folgt:

                [HttpPost]
                [ActionName("Create")]
                public IHttpActionResult Post(CarModel currentCar)
                
                [HttpPost]
                [ActionName("Edit")]
                public IHttpActionResult Put(CarModel content)
                
                [HttpPost]
                [ActionName("Delete")]
                public IHttpActionResult Delete(CarModel car)
                

                Anhand der ActionName sind die ja eindeutig. Was meinst du dann mit:

                Wenn du eine solche Kombination noch bei anderen Actions hast, ist das nicht mehr eindeutig. Du musst da entweder die Methode ändern oder den Namen der Action.

                Wie müssen die Namen der Methoden geändert werden. Gib mir bitte ein Beispiel:

                1. Tach!

                  Anhand der ActionName sind die ja eindeutig. Was meinst du dann mit:

                  Wenn du eine solche Kombination noch bei anderen Actions hast, ist das nicht mehr eindeutig. Du musst da entweder die Methode ändern oder den Namen der Action.

                  Ich wusste ja nicht, wie die benannt sind, ich habe vermutet, dass es eine Gleichbenamsung sein könnte.

                  Wie müssen die Namen der Methoden geändert werden.

                  Wie sieht denn die Routing-Konfiguration aus? Anders als der Default?

                  Web API hat eine Routing- und Namens-Konvention. Wenn ich das richtig sehe, sollte man es wohl auch überschreiben können, was wohl in deinem Fall so nicht geht. Da fehlt mir die Erfahrung.

                  Mal eine andere Frage, warum möchtest du alle Änderungen mit POST erledigen? Die Verwendung von PUT und DELETE neben POST ist genauso einfach, der Request wird dadurch aber auch schon damit eindeutiger.

                  Gib mir bitte ein Beispiel

                  Funktionierende Beispiele bekommst du, wenn du dir einen Controller scaffolden lässt (wie man so schon auf Neudeutsch sagt), also einen hinzufügst, der für die CRUD-Funktionalität zumindest nackige Methoden hat. Und in der Dokumentation zur Web API.

                  dedlfix.

                2. Dir werden VIER Methodentreffer angezeigt, und die Kandidaten sehen eigentlich unverdächtig aus. Allerdings meckert er auch noch über eine Methode "Test" - die hast Du uns verheimlicht.

                  Ggf. sind deine Routen seltsam definiert, so dass er die gleiche Methode über mehrere Routen findet?

                  Was auch noch sein kann, aber unwahrscheinlich ist: Du verwendest das falsche ActionName Attribut. Es gibt zwei - eins für MVC (im System.Web.Mvc) und eins für WebAPI (in System.Web.Http). Prüfe deine using Angaben, wenn du das falsche verwendest dann gibt es keine Fehlermeldung, es wird einfach ignoriert.

                  Dass Du mit partial classes hantierst und in einer anderen Source-Datei weitere Methoden hast, will ich mal ausschließen.

                  Rolf

          2. Das Umschreiben von URLs sind eine Spezialität anderenorts.

            Stimmt, andere Frameworks machen das auch, in Magento gibt es da sog. Pseudoklassen. Es läuft aber aus dasselbe hinaus, nämlich den Schlüssel- bzw. Aktionparameter samt Wert im URL abzubilden und den Namen des Controllers bzw. der Controllerklasse dazu.

            Ich hatte diese Idee auch schon, aber bereits nach kurzer Zeit verworfen, weil das mit einer ganzen Reihe von Nachteilen verbunden ist, den dynamischen Teil einer Route in einer statischen Routingtabelle unterzubringen. Unter Anderem erschwert es die Fehlersuche (was wir ja hier mitkriegen), es vergrößert die Routingtable und es bedingt mehr Code der kompiliert im Speicher vorzuhalten ist. Im legacy/native CGI-Modus sind da die Grenzen schnell erreicht wenn bei jedem Request die Routingtable neu in den Speicher geladen wird und jedesmal Unmengen Code zu kompilieren sind, auch Code von Klassen die am eigentlichen Request gar nicht beteiligt sind.

            Von der allgemeinen 'Klassenflut' ganz zu schweigen und warum sollte sich der URL ändern nur wenn sich die Requestmethode ändert, das Modell und oft auch das View jedoch dasselbe bleibt... über all diese und weitere Nachteile werde ich mal einen ausführlichen Artikel schreiben wenn die Tage wieder kürzer werden.

            Gruß vom Baggersee 😉

            1. Tach!

              Ich hatte diese Idee auch schon, aber bereits nach kurzer Zeit verworfen, weil das mit einer ganzen Reihe von Nachteilen verbunden ist, den dynamischen Teil einer Route in einer statischen Routingtabelle unterzubringen. Unter Anderem erschwert es die Fehlersuche (was wir ja hier mitkriegen), es vergrößert die Routingtable und es bedingt mehr Code der kompiliert im Speicher vorzuhalten ist.

              Die Default-Routing-Tabelle bei ASP.NET MVC besteht aus genau einem Eintrag. Das Muster ist {controller}/{action}/{id}, alle drei Parameter sind optional, es gibt Default-Werte für controller (=Home) und action (=Index). Für den API-Teil gibt es eine zweite Regel bei dem das gleiche Muster mit einem api/ am Anfang verwendet wird. Wenn man sich an diese Konvention hält, also keine abweichende URL-Gestaltung benötigt, wächst da gar nichts.

              Für die erschwerte Fehlersuche sehe ich eher ausbaufähiges Wissen um die Debugmöglichkeiten und der Arbeitsweise sowie Verwendung der eingesetzten Teile des Frameworks als das Problem an, zuzüglich der Stolperstellen, wie die von Rolf b genannte, und die kleinen Inkonsistenzen zwischen den Controllern für die HTML-Webseiten und denen für die Web-API. Die sind aber auch teilweise dessen geschuldet, dass die allgemeinen Anforderungen etwas unterschiedlich sind. Für das "normale" Web braucht es eindeutige URLs, API-Zugriffe für CRUD-Operationen hingegen können sich eine URL (pro Thema/Model) teilen und unterschiedliche Requestmethoden verwenden.

              Im legacy/native CGI-Modus sind da die Grenzen schnell erreicht wenn bei jedem Request die Routingtable neu in den Speicher geladen wird und jedesmal Unmengen Code zu kompilieren sind, auch Code von Klassen die am eigentlichen Request gar nicht beteiligt sind.

              ASP.NET-Anwendungen laufen in so etwas ähnlichem wie dem FastCGI-Modus. Die Anwendung läuft in einem Application-Pool, und wird nur gelegentlich komplett neu gestartet.

              Von der allgemeinen 'Klassenflut' ganz zu schweigen und warum sollte sich der URL ändern nur wenn sich die Requestmethode ändert, das Modell und oft auch das View jedoch dasselbe bleibt...

              Das ist ja hier auch nicht der Fall. Er hatte, aus welchem Grund auch immer, dieselbe Requestmethode für alle datenändernden CRUD-Aktionen verwendet, und da braucht es eine anderweitige Unterscheidung, wie anders benannte URLs. Ansonsten ist es im Web-API-Teil Usus, dieselbe URL mit unterschiedlichen Requestmethoden zu verwenden. Es entstand dadurch auch keine Klassenflut, es spielte sich für dieses Model alles in derselben Controller-Klasse ab.

              dedlfix.

            2. ...in einer statischen Routingtabelle...

              Die ASP.NET MVC Designer verwenden das Prinzip "Convention before Configuration", d.h. wenn Du eine URL verwendest, die auf das von dedlfix genannte allgemeine Muster passt, dann sucht die MVC Runtime nach einer Klasse mit passendem Namen, instanziiert sie und ruft darin dann eine entsprechende Action Methode auf. Bei Web-API baut er ggf. noch das HTTP-Verb mit ein, um den Methodennamen abzuleiten.

              Solange man die Convention kennt, und sie auch zum Problem passt, ist das alles schnuckelig und kompakt abbildbar. Was die MVC Runtime im Hintergrund treibt, ist eine andere Frage, er wird z.B. nicht jedesmal alle geladenen Assemblies nach Controllern durchflöhen, sondern das nur einmal tun und in einem Dictionary cachen.

              ...es vergrößert die Routingtable und es bedingt mehr Code der kompiliert im Speicher vorzuhalten ist.

              Das ist letztlich richtig; das Routing, das ich konfiguriere, ist nur die Spitze des Vanilleeisberges und die eigentliche Routingtable baut MVC im Cache auf. Aber eben nur einmal. ASP.NET läuft im IIS als Application bzw. unter Apache und Mono als Apache-Modul, d.h. da wird einmal der Code geladen und verarbeitet dann die einlaufenden Requeste. Das muss man natürlich beim Programmieren beachten, man kann nicht einfach so mit static-Variablen herummachen. Die werden von allen parallel laufenden Requests geteilt. Ein Reload der Application (bzw. Recycle des Application Pool) findet statt, wenn ASP.NET eine Änderung der web.config oder der zur Application gehörigen Ressourcen erkennt, oder nach einer gewissen Zeitdauer (Reboot tut gut). Das merkt man genau - der erste Aufruf eines ASP.NET Service dauert sehr lange, der Rest geht fix.

              Von der allgemeinen 'Klassenflut' ganz zu schweigen

              Das kann man so und so sehen. Klassen sollen im Sinne von SRP eh nicht groß sein, von daher entstehen bei Beachtung der Clean Code Prinzipien ohnehin eine Menge davon.

              Gruß vom Baggersee 😉

              Das ist ein GUTER Plan. Verbrenne Dich nicht!

              Rolf

              1. Hello,

                bitte schlagt mich nicht gleich, aber so wie ich das aus den ganzen Beschreibungen verstanden habe, ist doch gar kein Request abgesetzt worden.

                Ich vermute, dass gar kein Socket gebildet werden konnte. Das würde auch zu "bad Request" passen. Wenn der Request an den "Server" gelangt wäre, hätte es mMn einen HTTP-Status gegeben. Oder habe ich hier nun irgendwas ganz falsch verstanden?

                Liebe Grüße
                Tom S.

                --
                Es gibt nichts Gutes, außer man tut es
                Andersdenkende waren noch nie beliebt, aber meistens diejenigen, die die Freiheit vorangebracht haben.
                1. Ich vermute, dass gar kein Socket gebildet werden konnte. Das würde auch zu "bad Request" passen. Wenn der Request an den "Server" gelangt wäre, hätte es mMn einen HTTP-Status gegeben. Oder habe ich hier nun irgendwas ganz falsch verstanden?

                  HTTP Status 400 vulgo „Bad Request“

                  1. Hello,

                    da hast DU jetzt eventuell etwas falsch verstanden.
                    Es kam ja, soweit ich das gelesen habe, gar kein HTTP-Status zurück.

                    Liebe Grüße
                    Tom S.

                    --
                    Es gibt nichts Gutes, außer man tut es
                    Andersdenkende waren noch nie beliebt, aber meistens diejenigen, die die Freiheit vorangebracht haben.
                2. Tach!

                  bitte schlagt mich nicht gleich, aber so wie ich das aus den ganzen Beschreibungen verstanden habe, ist doch gar kein Request abgesetzt worden.

                  Das war nur die Vermutung von Casablanca, und sie war garantiert nicht richtig.

                  Ich vermute, dass gar kein Socket gebildet werden konnte. Das würde auch zu "bad Request" passen.

                  Nein, ohne HTTP-Verbindung kein HTTP-Status sondern allgemeiner Netzwerkfehler.

                  Wenn der Request an den "Server" gelangt wäre, hätte es mMn einen HTTP-Status gegeben. Oder habe ich hier nun irgendwas ganz falsch verstanden?

                  Bad Request ist HTTP-Status 400, mithin fand eine HTTP-Verbindung statt. Hat sich ja dann auch eine Fehlermeldung im Server angefunden, die besagte, dass der Request im Server ankam und nur nicht zum Ziel geroutet werden konnte, weil mehrere gefunden wurden. Die Ziele waren nicht eindeutig gekennzeichnet, vermutlich weil die Zuweisung des Name-Attributes zu den Actions aufgrund eines Formfehlers ignoriert wurde.

                  dedlfix.

                  1. Hello,

                    kannst Du garantieren, dass die IDE nicht für einen nicht ausführbaren AJAX-Request "bad request" antwortet ohne einen HTTP-Status zu liefern?

                    In der Konsole sah das doch so aus.

                    Aber warten wir es mal ab, was schlussendlich die Lösung des Rätsels gewesen sein wird.

                    Liebe Grüße
                    Tom S.

                    --
                    Es gibt nichts Gutes, außer man tut es
                    Andersdenkende waren noch nie beliebt, aber meistens diejenigen, die die Freiheit vorangebracht haben.
                    1. Tach!

                      kannst Du garantieren, dass die IDE nicht für einen nicht ausführbaren AJAX-Request "bad request" antwortet ohne einen HTTP-Status zu liefern?

                      Wenn ich einen Request an ein nicht erreichbares Ziel stelle, sehe ich nach dem Timeout im Netzwerk-Tab keinen Statuscode, sondern eine andere Meldung. Was man konkret im Ajax-Objekt sieht, hab ich nicht getestet. Der Browser müsste eine Antwort faken und ich sehe in der List der Statuscodes auch keinen, der für generelle Netzwerkprobleme geeignet wäre.

                      Bad Request wäre auch die falsche Meldung für Netzwerkprobleme, denn ein solcher Request wäre prinzipiell zustellbar, nur hat man da Formfehler drin, die den Server vom Antworten abhalten.

                      dedlfix.

                      1. Hello,

                        das XHR-Objekt sollte Statuscode 0 liefern, wenn z. B. keine Namensauflösung möglich war.

                        Liebe Grüße
                        Tom S.

                        --
                        Es gibt nichts Gutes, außer man tut es
                        Andersdenkende waren noch nie beliebt, aber meistens diejenigen, die die Freiheit vorangebracht haben.
                        1. Tach!

                          das XHR-Objekt sollte Statuscode 0 liefern, wenn z. B. keine Namensauflösung möglich war.

                          0 ist kein HTTP-Statuscode. Da wird wohl bei allen Fehlern, die unterhalb der HTTP-Schicht auftreten, ersatzweise so eine 0 geliefert werden.

                          dedlfix.

  3. Hello,

    was saht denn netstat zu 4627?

    Liebe Grüße
    Tom S.

    --
    Es gibt nichts Gutes, außer man tut es
    Andersdenkende waren noch nie beliebt, aber meistens diejenigen, die die Freiheit vorangebracht haben.
  4. Hallo zusammen,

    ich möchte mich gerne für eure Hilfe bedanken. Obwohl ich gestern nicht den Fehler beheben konnte, habe ich heute knapp vor der Zeit das alte, lauffähige Projekt auf meinem Laptop zum Laufen bringen konnte. Ich verstehe immer noch nicht, was im neu angelegten Projekt, das den gleichen Code hatte wie das alte, den Fehler verursachte, das Ganze ist aber jetzt vorbei. Ich werde mich aber später mit dem Problem weiter befassen.

    Gruß

    1. Hello,

      hast Du vielleicht auf den Hosts unterschiedliche Versionen von VS drauf gehabt?

      Ich wage mich zu erinnern, dass die unterschiedlichen Versionen unterschiedliche Ports benutzten für ihre Aufgaben. Beim Remote Degugger ist es jedenfalls so gewesen. Wenn Du dann also nur das Projekt übertragen hast, stimmt der Port nicht mehr, auch wenn das Projekt als solches noch läuft.

      Ich entmehme deinen Zeilen, dass Du nun das gesamte VS inclusive Projekt neu installiert hast. Das würde zu der Theorie passen. :-O

      Liebe Grüße
      Tom S.

      --
      Es gibt nichts Gutes, außer man tut es
      Andersdenkende waren noch nie beliebt, aber meistens diejenigen, die die Freiheit vorangebracht haben.
      1. Hi,

        neine, wie bereits erwähnt, ich habe das Projekt ursprünglich auf dem Entwicklungsrechner entwicklet, wo es tedellos lief. Nach dem ich es auf meinem Präsentationslaptop kopiert habe, lief gar nichts mehr und die Seiten wurden nicht gefunden und IIS wurde auch nicht gestartet. Daher habe ich auf dem Laptop ein neues Project angelegt und die bereits geschriebenen Codes in das Projekt importiert und alles an das neue Projekt angepasst. Trotzdem habe ich die bereits besprochenen Probleme gehabt.

        Heute habe ich beim googeln ganz zufällig gesehen, woran es liegen könnte, und zwar an dem Ordner .vs des aleten Projektes, den man bei so einem Fall wie mir löschen sollte. Das habe ich auch gemacht und oh wunder, nach einem verlorenen Tag lieft auf einmal das alte Projekt einwandfrei nach fünf Minuten. Der .vs Ordner wird von VS automatisch nochmal angelegt und anscheinend werden alle Einstellungen neu an das System angepasst.

        Gruß

        1. Tach!

          Heute habe ich beim googeln ganz zufällig gesehen, woran es liegen könnte, und zwar an dem Ordner .vs des aleten Projektes, den man bei so einem Fall wie mir löschen sollte. Das habe ich auch gemacht und oh wunder, nach einem verlorenen Tag lieft auf einmal das alte Projekt einwandfrei nach fünf Minuten. Der .vs Ordner wird von VS automatisch nochmal angelegt und anscheinend werden alle Einstellungen neu an das System angepasst.

          Na, wenn du das so sagst, hast du vielleicht unterschiedliche Versionsstände von VS oder dem .NET Framework auf den Rechnern?

          dedlfix.