2013-02-28 134 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

相关问题