I have an MVC3 application that unexpectedly causes me strange behavior. First, a little background (although I will try to make it as concise as possible).
In my controller action, I have this code:
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);
This controller action hides complex logic because ListViewResult is a custom ActionResult result designed specifically for formatting JSON lists.
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(); } } }
Now it seems that sometimes a NullReferenceException is thrown into the string vm => Url.Content(...) and vm => Url.Action(...) . This does not always happen, but if I update several times, I can reliably reproduce it.
Update
Having rummaged in the source code for some time, I consider that I have found the broken code. The problem seems to be related to the UrlRewriterHelper.WasThisRequestRewritten method, which calls ServerVariables.Get("IIS_WasUrlRewritten") . It seems that the method uses a private field named _request , which is null at the moment of code (for some reason). It is best to assume that for some time between the return of the action and the result of the execution of the ServerVariables collection, ServerVariables either loses the internal _request - OR - the ServerVariables collection ServerVariables recreated without a valid _request .
I also realized that this could be a problem with IIS Express. When working under Visual Studio Development Server, I was not able to repeat the problem. I updated the tags to reflect what I think are the most likely reasons.