Mittwoch, 8. Februar 2012

Virtual Server und SQL Server (Express)

Gerne hosten wir auf einem externen Virtual Server mehrere Anwendungen im IIS sowie eine SQL Server Express Instanz. Eigentlich kein großes Problem, auch wenn der vServer nur 2GB Speicher hat.
Allerdings holt sich der SQL Server auch gerne mal fast den gesamten freien Speicher. Für den Fall der Fälle - man weiß ja nie. Ungünstig wenn dieser Speicher aber auch nicht rechtzeitig wieder freigegeben wird, wenn andere Anwendungen ihn benötigen. So verabschiedet sich dann der IIS regelmäßig und lieferrt höchstens noch ein "503 - Service unavailable" an seine Außenwelt.
Dieses Verhalten kann man dem SQL Server abgewöhnen, indem man ihm vorschreibt, wieviel Speicher er sich maximal holen soll. Folgende Statements sorgen dafür, das Maximum auf 512 MB zu beschränken:
sp_configure 'show advanced options', 1;
GO
RECONFIGURE;
GO
sp_configure 'max server memory', 512;
GO
RECONFIGURE;
GO
Anschließend den SQL Server (SQLEXPRESS) Dienst neu starten, und schon ist er nicht mehr so hungrig.

Dienstag, 31. Januar 2012

Error 405 bei HttpDelete Requests

Wenn in einer Web-Anwendung auf einem IIS 7.5 bei HttpDelete Requests der Fehler Code 405 auftritt ist das meist ein Indiz dafür, dass das standardmäßig beim IIS 7.5 installierte WebDav Modul dazwischen funkt.
Dieses sollte dann in der web.config wie folgt ausgesachaltet werden:
<modules runAllManagedModulesForAllRequests="true">
    <remove name="WebDAVModule" />
</modules>
Siehe auch:  http://stackoverflow.com/questions/1760607/asp-net-mvc-got-405-error-on-http-delete-request

Donnerstag, 1. Dezember 2011

Spaß mit QueryString

Einen QueryString zu ändern kann gar nicht so leicht sein. Beispielsweise ist Request.QueryString readonly. Daher kann man nicht einfach Request.QueryString.Remove("parameterDerMichStoert") aufrufen.

Eine Option ist es Request.QueryString.ToString() zu verwenden und dann dem ganzen mit regulären Ausdrücken zu Leibe zu rücken. Es gibt aber eine IMHO schönere Möglichkeit. Man kopiert sich einfach die Werte in eine NameValueCollection
var nameValueCollection = new NameValueCollection(Request.QueryString);
nameValueCollection.Remove("page");
Falls man den QueryString schon in string-Form vorliegt, kann mit HttpUtility.ParseQueryString(...) eine entsprechende NameValueCollection erstellt werden.

Bleibt allerdings noch ein Problem. Die ToString()-Methode von NameValueCollection liefert uns keinen QueryString. Im Netz finden sich viele Extension-Methods die behaupten dies zu können, allerdings waren alle die ich gefunden habe fehlerhaft. Das Problem waren immer mehrfache Werte für einen Parameter. Anstatt z.B. "customerId=1&customerId=2" haben die Methoden "customerId=1,2" ausgegeben.

Genug gelabert, hier die Extension-Method:
public static string ToQueryString(this NameValueCollection nameValueCollection)
{
 var parts = new Collection();
 foreach (string name in nameValueCollection)
 {
     var values = nameValueCollection.GetValues(name);
     if (values == null) continue;
     foreach(var value in values)
     {
         parts.Add(string.Format("{0}={1}", name, HttpUtility.UrlEncode(value)));
     }
 }
 return String.Join("&", parts);
}

Server.MapPath() mal anders

Server.MapPath(...) ist bekanntlich eine praktische Methode, um in Controllern und Views physische Pfade für Assets zu bestimmen.

Und wenn man kein Server-Objekt hat?

Sofern der Code im Rahmen eines Requests ausgeführt wird kann man einfach über den HttpContext gehen:

HttpContext.Current.Server.MapPath(...)

Was aber, wenn man z.B. in einem statischen Konstruktor oder sonst wie außerhalb eines Requests einen Pfad bestimmen muss. Auch hier gibt es eine Lösung:

HostingEnvironment.MapPath(...)

Prinzipiell könnte man wohl an allen Stellen an denen man Server.MapPath(...) verwendet auch HostingEnvironment.MapPath(...) nehmen.

Freitag, 19. August 2011

Git for Windows - libiconv-2.dll Error

Falls Git mal mit der Meldung
The program can't start because libiconv-2.dll is missing from your computer.
den Dienst verweigert (bei mir ging "push" nicht) hilft es unter Umständen, die libiconv-2.dll aus dem /bin Ordner nach /libexec/git-core zu kopieren. Es kann allerdings auch sein, dass in der Konfiguration irgendetwas nicht stimmt, und Git sich deswegen mit dieser irreführenden Meldung beschwert. Meist liegt es dann am Pfad zum Repository.

ELMAH auf x64 Server

Heutzutage ist es wirklich einfach, ELMAH in einem Projekt für das Error Logging zu benutzen. NuGet Package Manager starten -> nach ELMAH suchen -> Package mit der geünschten Konfiguration hinzufügen -> fertig.

Zuletzt hatte ich dies mit der MS Access Variante gemacht. Alles gut, bis ich die Anwendung auf dem Server laufen ließ. Folgende Fehler traten auf:
The 'Microsoft.Jet.OLEDB.4.0' provider is not registered on the local machine.
oder
The Microsoft Access database creation script failed with exit code 1
Da der 'Microsoft.Jet.OLEDB.4.0' Treiber nur 32bit ist, muss man im zuständigen Anwendungspool '32-Bit-Anwendungen aktivieren' auf True stellen. Dann sollte es mit ELMAH klappen. Gibts immer noch einen Fehler beim Erstellen der Elmah.mdb einfach mal eine vorhandene Elmah.mdb (z.B. von lokal) auf den Server legen.

http://stackoverflow.com/questions/6352904/accessproviders-working-on-webdevelopment-server-but-not-on-iis7

Montag, 1. August 2011

Project Awesome und der IE8

Bei der Verwendung des Project Awesome zur Anzeige einer PopupForm in einem MVC 3 Projekt hatte ich das Problem, dass der FormSubmit so gut wie nie im IE8 klappte. Alle anderen Browser funktionierten. Genauer gesagt klappte das Abschicken einer bestimmten Form nur das erste Mal, danach nicht mehr. Anscheinend findet es der IE8 richtig, auch POST Requests und deren Antwort zu cachen. Ich konnte das Problem letztendlich nur lösen indem ich die Actions im Controller mit
[OutputCache(Location = OutputCacheLocation.None)]
ausstattete und für jQuery diese globale Einstellung vornahm:
$.ajaxSetup({
    cache: false
});