2013-02-28 141 views
6

我有一個MVC3應用程序,它突然給我一些奇怪的行爲。首先是一些背景(儘管我會盡量使其儘可能簡短)。Request.ServerVariables拋出NullReferenceException

在我的控制器動作,我有這樣的代碼:

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); 

該控制器動作隱藏複雜的邏輯相當數量的,因爲ListViewResult是專門爲JSON格式列表設計定製的結果ActionResult。現在

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(); 
     } 
    } 
} 

,似乎偶爾NullReferenceException的在該行vm => Url.Content(...)vm => Url.Action(...)被拋出。這不是總是發生,但如果我刷新幾次,我可以可靠地重現它。

更新

在一會兒的源代碼周圍挖掘後,我相信我已經發現有問題的代碼。這個問題似乎與UrlRewriterHelper.WasThisRequestRewritten方法,它調用ServerVariables.Get("IIS_WasUrlRewritten")。看來這種方法使用了一個名爲_request的專用字段,它是null(在某些情況下)。我最好的猜測是,在返回的動作和執行結果之間的某個時間段,ServerVariables集合要麼丟失了它的內部參照_request - - 正在重新創建集合ServerVariables,而沒有對_request的有效參考。

我也意識到這可能是IIS Express的問題。在Visual Studio Development Server下運行時,我無法重現該問題。我更新了標籤以反映最可能的原因。

+0

有趣的問題,+1。 – Brian 2013-02-28 23:09:44

+0

這是從調試還是隻是在探討? – 2013-03-02 03:25:01

+0

調試。我也意識到'_request'被'ServerVarsCollection.Dispose'設置爲null。所以也許控制器被處置掉(仍然不能解釋爲什麼我偶爾會遇到這個錯誤)。 – 2013-03-02 13:28:05

回答

3

我剛剛遇到了與IIS Express相同的問題,並且發現這是因爲我已經將URL重寫擴展安裝到IIS,然後將其卸載,但它已經在IIS Express的applicationhost.config文件中留下了一些配置。 (C:\ Users \\ Documents \ IISExpress \ config \ applicationhost.config)

我剛剛註釋掉了該文件中的相關行,殺死了IIS Express和reran,但我沒有再次看到該問題。

我註釋掉的兩行代碼在下面的代碼片段中進行了註釋。

<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

謝謝。這似乎解決了問題。 – 2013-03-28 15:24:22

1

檢查視覺工作室,你還沒有檢查過在調試時顯示所有異常。這可能只是一個內部處理的異常,因爲您的調試 - >異常設置,您會看到。

檢查是否只是我的代碼未選中,如果您現在在debug-> exceptions窗口中顯示兩行復選框。

+0

我在調試 - >例外窗口中看不到這些選項。也許你指的是VS 2010的用戶界面 - 我正在運行VS 2012.在CLR Exceptions下,我在全局檢查了「用戶未處理」異常,就是這樣。 – 2013-02-28 23:43:23

+1

嗯在2012年的窗口中沒有'例外'呃,好吧 - 那裏有這個想法。第二個選擇是獲取MVC源代碼並進行調試。如果你需要的話,我可以幫助你,這'相當'容易。如果上下文爲空,則引發ArgumentNullException而不是NullReferenceException。 – 2013-03-01 01:24:07

+0

感謝您的建議,這確實有助於澄清問題。我用我的最新發現更新了我的問題。 – 2013-03-01 23:14:34

相關問題