Pubblicazione di moduli su 404 + HttpHandler in IIS7: perché tutti i dati POST sono scomparsi?

StackOverflow https://stackoverflow.com/questions/102846

  •  01-07-2019
  •  | 
  •  

Domanda

OK, potrebbe sembrare un po 'confuso e complicato, quindi abbi pazienza.

Abbiamo scritto un framework che ci consente di definire URL amichevoli. Se si naviga verso qualsiasi URL arbitrario, IIS tenta di visualizzare un errore 404 (o, in alcuni casi, 403; 14 o 405). Tuttavia, IIS è impostato in modo che tutto ciò che è diretto a quegli errori specifici venga inviato a un file aspx. Questo ci consente di implementare un HttpHandler per gestire la richiesta e fare cose, il che comporta la ricerca di un modello associato e quindi l'esecuzione di tutto ciò che è associato ad esso.

Ora, tutto funziona in IIS 5 e 6 e, in una certa misura, in IIS7, ma per una sola cattura, che si verifica quando si pubblica un modulo.

Vedi, quando pubblichi un modulo in un URL inesistente, IIS dice "ah, ma quell'URL non esiste" e genera un metodo 405 "non consentito" errore. Dal momento che stiamo dicendo a IIS di reindirizzare quegli errori alla nostra pagina aspx e quindi gestirli con il nostro HttpHandler, questo normalmente non è un problema. Ma a partire da IIS7, tutte le informazioni POST sono scomparse dopo essere state reindirizzate al 405. E quindi non puoi più fare le cose più banali che coinvolgono i moduli.

Per risolvere questo problema, abbiamo provato a utilizzare un HttpModule, che conserva i dati POST ma sembra non avere una sessione inizializzata al momento giusto (quando necessario). Abbiamo anche provato a utilizzare un HttpModule per tutte le richieste, non solo le richieste mancanti che colpiscono 404/403; 14/405, ma ciò significa che cose come immagini, css, js ecc. Vengono gestite dal codice .NET, il che è terribilmente inefficiente.

Il che mi porta alla vera domanda: qualcuno l'ha mai incontrato e qualcuno ha qualche consiglio o sa cosa fare per far funzionare di nuovo le cose? Finora qualcuno ha suggerito di utilizzare il modulo di riscrittura degli URL di Microsoft . Questo aiuterebbe a risolvere il nostro problema?

Grazie.

Altri suggerimenti

Poiché IIS7 utilizza .net dall'alto verso il basso, non ci sarebbe alcun sovraccarico di prestazioni nell'uso di un HttpModule, in realtà ci sono diversi Managed HttpModules che vengono sempre utilizzati su ogni richiesta. Quando viene generato l'evento BeginRequest, è possibile che SessionStateModule non sia stato aggiunto alla raccolta Moduli, quindi se si tenta di gestire la richiesta durante questo evento, non saranno disponibili informazioni sullo stato della sessione. L'impostazione della proprietà HttpContext.Handler inizializzerà lo stato della sessione se il gestore richiesto ne ha bisogno, quindi puoi semplicemente impostare il gestore sulla tua pagina di fantasia 404 che implementa IRequiresSessionState. Il codice seguente dovrebbe fare il trucco, anche se potrebbe essere necessario scrivere un'implementazione diversa per il metodo IsMissing ():

using System.Web;
using System.Web.UI;

class Smart404Module : IHttpModule
{
    public void Dispose() {}

    public void Init(HttpApplication context)
    {
        context.BeginRequest += new System.EventHandler(DoMapping);
    }

    void DoMapping(object sender, System.EventArgs e)
    {
        HttpApplication app = (HttpApplication)sender;

        if (IsMissing(app.Context))
            app.Context.Handler = PageParser.GetCompiledPageInstance(
                "~/404.aspx", app.Request.MapPath("~/404.aspx"), app.Context);
    }

    bool IsMissing(HttpContext context)
    {
        string path = context.Request.MapPath(context.Request.Url.AbsolutePath);

        if (System.IO.File.Exists(path) || (System.IO.Directory.Exists(path)
            && System.IO.File.Exists(System.IO.Path.Combine(path, "default.aspx"))))
            return true;
        return false;
    }
}

Modifica: ho aggiunto un'implementazione di IsMissing ()

Nota: su IIS7, il modulo dello stato della sessione non viene eseguito globalmente per impostazione predefinita. Esistono due opzioni: abilitare il modulo dello stato della sessione per tutte le richieste (vedere il mio commento sopra relativo all'esecuzione dei moduli gestiti per tutti i tipi di richiesta) oppure è possibile utilizzare la reflection per accedere ai membri interni all'interno di System.Web.dll.

Il problema in IIS 7 delle variabili post non passate ai gestori di errori personalizzati è stato risolto nel Service Pack 2 per Vista. Non l'ho provato su Windows Server ma sono sicuro che verrà risolto anche lì.

Solo un'ipotesi: il gestore specificato in% windir% \ system32 \ inetsrv \ config \ applicationhost.config di IIS7 che sta gestendo la tua richiesta non sta permettendo al verbo POST di passare attraverso, e sta valutando quella regola prima di determinare se l'URL non esiste.

Sì, consiglierei sicuramente la riscrittura degli URL (usando Microsoft IIS7 una o una delle tante alternative). Questo è specificamente progettato per fornire URL intuitivi, mentre i documenti di errore sono un backstop per errori, che tende a confondere i dati in arrivo, quindi potrebbe non essere quello che ti aspetti.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top