2013-02-28 4 views
6

У меня есть приложение MVC3, которое неожиданно вызывает у меня странное поведение. Сначала немного фона (хотя я постараюсь сделать это как можно более кратким).Request.ServerVariables throws 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 обычая результат ActionResult разработан специально для форматирования списков в формате 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(); 
     } 
    } 
} 

Теперь, кажется, что иногда NullReferenceException «s бросают на линии vm => Url.Content(...) и vm => Url.Action(...). Это не всегда происходит, но если я обновляюсь несколько раз, я могу достоверно воспроизвести его.

Update

После копаться в исходном коде на некоторое время, я считаю, что я раскрыл вредоносный код,. Проблема, похоже, связана с методом UrlRewriterHelper.WasThisRequestRewritten, который вызывает ServerVariables.Get("IIS_WasUrlRewritten"). Похоже, что метод использует частное поле с именем _request, которое в этот момент кода (0) по умолчанию является null. Мое лучшее предположение заключается в том, что некоторое время между возвратом действия и выполнением результата коллекция ServerVariables либо теряет внутреннюю ссылку на _request - ИЛИ - коллекция ServerVariables воссоздана без действительной ссылки на _request.

Я также понял, что это может быть проблемой с IIS Express. При работе под Visual Studio Development Server я не смог повторить проблему. Я обновил теги, чтобы отразить то, что думает, являются наиболее вероятными причинами.

+0

Интересный вопрос, +1. – Brian

+0

было это от отладки или просто тыкать? –

+0

Отладка. Я также понял, что '_request' установлен в значение null на' ServerVarsCollection.Dispose'. Поэтому, возможно, диспетчер получает доступ (по-прежнему не объясняет, почему я иногда получаю эту ошибку). –

ответ

3

У меня была такая же проблема с IIS Express, и я обнаружил, что это связано с тем, что я установил URL Rewrite Extension для IIS, а затем удалил его, но оставил некоторую конфигурацию в файле applicationhost.config для IIS Express. (C: \ Users \\ Documents \ IISExpress \ config \ applicationhost.config)

Я просто прокомментировал связанные строки в этом файле, убил IIS Express и повторил, и я больше не видел проблему.

Две строки, которые я прокомментировал, прокомментированы в фрагменте ниже.

<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

Спасибо. Это, похоже, устранило проблему. –

1

Проверьте визуальную студию, которую вы не проверили, чтобы показать все исключения во время отладки. Это может быть просто исключение изнутри, которое вы видите из-за настроек Debug-> exceptions.

Проверьте, не снят ли только мой код, и если теперь вы показываете две строки флажков в окнах debug-> exceptions.

+0

Я не вижу эти параметры в окне Debug -> Exceptions. Возможно, вы имеете в виду пользовательский интерфейс VS 2010 - я запускаю VS 2012. В соответствии с исключениями CLR, у меня есть исключения «Пользовательские необработанные», проверенные по всем направлениям, и все. –

+1

hmm no «Исключения» в окне 2012 года, ну, вот эта идея. Второй вариант - захватить источник MVC и отладить его. Я могу помочь вам в этом, если вам это нужно, это «справедливо» легко. Если контекст имеет значение null, генерируется исключение ArgumentNullException, а не исключение NullReferenceException. –

+0

Спасибо за предложение, это помогло пролить свет на проблему. Я обновил свой вопрос своими последними результатами. –

Смежные вопросы