2013-02-28 9 views
6

Possiedo un'applicazione MVC3, che improvvisamente mi dà un comportamento strano. Prima un po 'di background (anche se cercherò di renderlo il più breve possibile).Request.ServerVariables genera NullReferenceException

Nella mia azione di controllo, ho questo codice:

public ActionResult Grid(ApplicationViewModel search = null) 
{ 
    return this.ListView(
     this.Find<Entity>(), 
     this.CreateViewModel, 
     mixins: new Dictionary<string, Func<EntityViewModel, object>>() 
     { 
      { "Icon", vm => Url.Content("~\Images\entityType.png") }, 
      { "Link", vm => Url.Action("Details", vm.ControllerId) } 
     }); 
} 

EntityViewModel CreateViewModel(Entity entity); 

// Inherited base class methods 
protected IQueryable<T> Find<T>(); // Find T entities in DB 

protected ListViewResult<TModel, TViewModel> ListView<TModel, TViewModel>(
    IQueriable<TModel> entityQuery, 
    Func<TModel, TViewModel> materializeViewModel, 
    IDictionary<string, Func<TViewModel, object>> mixins); 

Questa azione di controllo nasconde una buona dose di logica complessa, perché ListViewResult è un risultato personalizzato ActionResult progettato specificamente per la formattazione degli elenchi JSON.

public class ListViewResult<TModel, TViewModel> : 
    ActionResult 
{ 
    public IQueryable<TModel> ViewData { get; set; } 
    public Func<TModel, TViewModel> Materialize { get; set; } 
    public Dictionary<string, Func<TViewModel, object>> Mixins { get; private set; } 

    ... 

    public override void ExecuteResult(ControllerContext context) 
    { 
     // Perform sorting/paging/formatting on IQueryable 

     ... 

     var viewModels = this.ViewData.Select(this.Materialize); 
     try 
     { 
      // another custom ActionResult for formatting JSON responses 
      new JsonNetResult() 
      { 
       Data = viewModels.ToArray(), 
       SerializerSettings = new JsonSerializerSettings() 
       { 
        ContractResolver = new MixinContractResolver() 
        { 
         Mixins = this.Mixins 
        } 
       } 
      }.ExecuteResult(context); 
     } 
     catch (Exception e) 
     { 
      context.HttpContext.Response.StatusCode = 500; 
      context.HttpContext.Response.StatusDescription = e.Message; 
     } 
    } 

    private class MixinContractResolver : 
     CamelCasePropertyNamesContractResolver 
    { 
     public Dictionary<string, Func<TViewModel, object>> Mixins { get; set; } 

     private List<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization) 
     { 
      List<JsonProperty> props = // get base properties 
      foreach (var pair in this.Mixins) 
      { 
       props.Add(new JsonProperty() 
       { 
        Ignored = false, 
        NullValueHandling = NullValueHandling.Include, 
        Readable = true, 
        PropertyName = Inflector.Camelize(pair.Key), 
        PropertyType = typeof(object), 
        ValueProvider = new DelegateValueProvider<TViewModel, object>(pair.Value), 
        Writable = false, 
       }); 
      } 
     } 
    } 

    private class DelegateValueProvider<T, R> : 
     Newtonsoft.Json.Serialization.IValueProvider 
    { 
     private readonly Func<T, R> func; 

     public DelegateValueProvider(Func<T, R> func) 
     { 
      this.func = func; 
     } 

     public object GetValue(object target) 
     { 
      return (R)this.func((T)target); 
     } 

     public void SetValue(object target, object value) 
     { 
      throw new NotSupportedException(); 
     } 
    } 
} 

Ora, sembra che ogni tanto un NullReferenceException 's gettati alla linea vm => Url.Content(...) e vm => Url.Action(...). Questo non avviene sempre, ma se si aggiorna alcune volte, posso riprodurlo in modo affidabile.

Aggiornamento

Dopo aver scavato intorno nel codice sorgente per un po ', credo di aver scoperto il codice incriminato. Il problema sembra essere con il metodo UrlRewriterHelper.WasThisRequestRewritten che chiama ServerVariables.Get("IIS_WasUrlRewritten"). Sembra che il metodo utilizzi un campo privato denominato _request che è null a questo punto nel codice (per qualche motivo). La mia ipotesi migliore è che un po 'di tempo tra il ritorno dell'azione e il risultato dell'esecuzione, la collezione ServerVariables o perde il riferimento interno a _request - O - la raccolta ServerVariables viene ricreata senza un riferimento valido a _request.

Ho anche capito che questo potrebbe essere un problema con IIS Express. Durante l'esecuzione in Visual Studio Development Server, non sono stato in grado di duplicare il problema. Ho aggiornato i tag per riflettere su quali sono le cause più probabili.

+0

Interessante domanda, +1. – Brian

+0

era questo dal debug o semplicemente spunta? –

+0

Debug. Mi sono anche reso conto che '_request' è impostato su null da' ServerVarsCollection.Dispose'. Quindi, forse il controller si sta disperdendo (ancora non spiega perché ricevo questo errore solo occasionalmente). –

risposta

3

Ho appena avuto lo stesso problema con IIS Express e ho scoperto che era perché avevo installato l'URL Rewrite Extension su IIS e poi lo ho disinstallato, ma aveva lasciato alcune configurazioni nel file applicationhost.config per IIS Express. (C: \ Users \\ Documents \ IISExpress \ config \ applicationhost.config)

Ho appena commentato le righe correlate in quel file, ucciso IIS Express e reran e non ho visto di nuovo il problema.

Le due righe che ho commentato sono commentate nello snippet seguente.

<configuration> 
    ... 
    <system.webServer> 
     ... 
     <globalModules> 

      <!--<add name="RewriteModule" image="%IIS_BIN%\rewrite.dll" />--> 
      ... 
     </globalModules> 
    </system.webServer> 
    <location path="" overrideMode="Allow"> 
     <system.webServer> 
      <modules> 
       <!--<add name="RewriteModule" />--> 
       ... 
      </modules> 
     </system.webServer> 
    </location> 
</configuration> 
+0

Grazie. Questo sembra aver risolto il problema. –

1

Controllare in studio visivo che non è stato spuntato per mostrare tutte le eccezioni durante il debug. Questa potrebbe essere solo un'eccezione gestita internamente che stai vedendo a causa delle tue impostazioni Debug-> eccezioni.

Controllare se Solo il mio codice è deselezionato e se ora si visualizzano due righe di checkbox nelle finestre di debug-> eccezioni.

+0

Non vedo queste opzioni nella finestra Debug -> Eccezioni. Forse ti stai riferendo all'interfaccia utente di VS 2010 - Sto utilizzando VS 2012. In Eccezioni CLR, ho verificato le eccezioni 'Utente non gestito' su tutta la linea e il gioco è fatto. –

+1

hmm no 'Eccezioni' nella finestra 2012 eh, beh ... ecco che arriva l'idea. La seconda opzione è quella di prendere l'origine MVC e debuggarlo. Posso aiutarti con quello se ne hai bisogno, è 'abbastanza' facile. Se il contesto è nullo, viene generata un'eccezione ArgumentNullException anziché una NullReferenceException. –

+0

Grazie per il suggerimento, questo ha aiutato a far luce sul problema. Ho aggiornato la mia domanda con le mie ultime scoperte. –

Problemi correlati