code it

Martins Tech Blog

HTTP-Status 400 trotz Inhalt

Der Anwendungsfall: Eine ajax-basierte Anwendung soll im Fehlerfall in den Ajax-Requests zwar einen Inhalt zurückgeben, der zu rendern ist, gleichzeitig aber auch einen von 200 abweichenden Statuscode, damit im Browser z.B. im JavaScript eine Unterscheidung stattfinden kann. Verkürzt und stark vereinfacht sieht das dann aus wie im folgenden Beispiel:

[HttpPost]
public ActionResult BuySomething(BuyProduct model)
{
    if (!ModelState.IsValid)
    {
        Response.StatusCode = (int)HttpStatusCode.BadRequest;
        return this.PartialView(model);
    }

    return this.PartialView("SuccessView", model);
}

Damit kann der Client nun im Fehlerfall zusätzliche Aktionen durchführen.

Im IIS7 funktioniert das out-of-the-box leider nicht, da hier mit Standardeinstellungen der Body-Content in der Antwort ersetzt wird. Um dieses Verhalten anzupassen, gibt es das Attribut existingResponse im Element system.webServer / httpErrors.

<system.webServer>
  <httpErrors existingResponse="PassThrough"></httpErrors>
</system.webServer>

Setzt man den Wert auf PassThrough, ersetzt der IIS den Content nicht, wenn gleichzeitig ein Statuscode >= 400 gesetzt wird.

maxRequestLength vs. maxAllowedContentLength

Wer sich mit Dateiuploads beschäftigt wird sich früher oder später Gedanken über Dateigrößenbeschränkungen machen wollen oder müssen.

Die Einstellung dafür findet sich in der web.config. Jedoch gibt es dabei gewisse Dinge zu beachten:

  1. Die MSDN ist sehr spärlich mit Informationen zu den Stellen an denen Änderungen notwendig sind und den vorhandenen Abhängigkeiten.
  2. Je nach verwendeter IIS-Version sind unterschiedliche Werte anzupassen.

Konfiguration des IIS

Relevant ist das Attribut maxAllowedContentLength im Element system.webServer / security / requestFiltering / requestLimits. Zu beachten ist hier, dass dieser Wert in Byte ist. Für Dateigrößen von 20 MB ist hier daher 20971520 einzutragen.

Konfiguration der ASP.NET Runtime

Relevant ist das Attribut maxRequestLength im Element system.web / httpRuntime. Zu beachten ist, dass dieser Wert in Kilobyte ist. Für Dateigrößen von 20 MB ist hier daher 20480 einzutragen. Wird der IIS 6 verwendet, spielt maxAllowedContentLength keine Rolle und es muss nur maxRequestLength angepasst werden.

 

Access denied due to invalid credentials - aber nur manchmal?

Heute bin ich über ein sehr seltsames Phänomen gestolpert. Gesetzt ist eine ASP.NET MVC3 Anwendung. Im Debug auf dem lokalen IISExpress läuft diese auch wunderbar, und auch auf der Testumgebung (einem Windows Server 2008) läuft die Anwendung - zumindest so lange man mit localhost darauf zugreift. Alle Zugriffe über die IP-Adresse des Servers enden mit einem 401er-Fehler - und das sowohl von anderen Rechnern aus als auch vom Server selbst.

Und das Seltsame daran: Es betrifft auch nur diese eine Anwendung - alle anderen auf diesem Server laufenden Web-Anwendungen laufen problemlos und sind auch Remote erreichbar. Nach mehreren erfolglosen Einstellungsversuchen im IIS7 - Bindings, Berechtigungen und was man sonst alles falsch machen kann, IIS-Neustarts und sogar Serverneustarts ändert sich am Problem trotzdem nichts. Der Zugriff über localhost funktioniert, aber der Zugriff über die IP-Adresse eben nicht.

Letztendlich brachte ein Blogeintrag von John Tindell die rettende Lösung - und auch wenn mir wirklich unklar ist, WARUM das funktioniert - es funktioniert.

Lösung: Fügt man in der web.config im Bereich system.webServer den folgenden Eintrag hinzu und ruft die Seite dann nochmals auf, so funktioniert der Aufruf nun auch mit der IP-Adresse:

<httpErrors errorMode="Details" />

Seltsam daran: Dieser Eintrag hat eigentlich nur etwas damit zu tun, wie das Error-Handling für die Anwendung ist und wie demzufolge Fehlermeldungen ausgegeben werden. Detailed Errors anzuschalten kann natürlich nicht die Lösung sein, da man auf extern erreichbaren Servern natürlich keine Interna des Webservers und der Applikationsstruktur preisgeben möchte. Deswegen kann das noch nicht die finale Lösung sein.