ASP.NET 5 MVC 6 RC1 API 中的自定义模型绑定异常
Exception with custom model binding in ASP.NET 5 MVC 6 RC1 API
当尝试在 ASP.NET 5 RC1 中使用自定义模型联编程序进行解析时,我在调用操作时在 Microsoft.AspNet.Mvc.ModelBinding.CompositeModelBinder
中抛出 NullReferenceException
。
启动中的模型绑定:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(options =>
{
options.ModelBinders.Insert(0, new MyCustomModelBinder());
}
自定义模型活页夹:
public class MyCustomModelBinder : IModelBinder
{
public Task<ModelBindingResult> BindModelAsync(ModelBindingContext bindingContext)
{
if (bindingContext.ModelType == typeof(MyCustomClass) && bindingContext.ValueProvider.GetValue(bindingContext.ModelName) != null)
{
MyCustomClass model;
var val = bindingContext.ValueProvider.GetValue(bindingContext.ModelName).FirstValue as string;
if (MyCustomClass.TryParse(val, out model))
{
return Task.FromResult(ModelBindingResult.Success(bindingContext.ModelName, model));
}
}
return null;
}
}
控制器动作:
[HttpGet]
public IActionResult GetSomething([ModelBinder(BinderType = typeof(MyCustomModelBinder))]MyCustomClass key)
{
return Json("Success!");
}
异常:
System.NullReferenceException: Object reference not set to an instance
of an object. at
Microsoft.AspNet.Mvc.ModelBinding.CompositeModelBinder.d__5.MoveNext()
--- End of stack trace from previous location where exception was thrown --- at
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task
task) at
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task
task) at
Microsoft.AspNet.Mvc.Controllers.DefaultControllerActionArgumentBinder.d__6.MoveNext()
--- End of stack trace from previous location where exception was thrown --- at
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task
task) at
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task
task) at
Microsoft.AspNet.Mvc.Controllers.DefaultControllerActionArgumentBinder.d__9.MoveNext()
--- End of stack trace from previous location where exception was thrown --- at
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task
task) at
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task
task) at
Microsoft.AspNet.Mvc.Controllers.DefaultControllerActionArgumentBinder.d__5.MoveNext()
--- End of stack trace from previous location where exception was thrown --- at
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task
task) at
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task
task) at
Microsoft.AspNet.Mvc.Controllers.FilterActionInvoker.d__52.MoveNext()
--- End of stack trace from previous location where exception was thrown --- at
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task
task) at
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task
task) at
Microsoft.AspNet.Mvc.Controllers.FilterActionInvoker.d__51.MoveNext()
--- End of stack trace from previous location where exception was thrown --- at
Microsoft.AspNet.Mvc.Controllers.FilterActionInvoker.d__44.MoveNext()
--- End of stack trace from previous location where exception was thrown --- at
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task
task) at
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task
task) at
Microsoft.AspNet.Mvc.Infrastructure.MvcRouteHandler.d__6.MoveNext()
--- End of stack trace from previous location where exception was thrown --- at
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task
task) at
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task
task) at
Microsoft.AspNet.Mvc.Routing.InnerAttributeRoute.d__10.MoveNext()
--- End of stack trace from previous location where exception was thrown --- at
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task
task) at
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task
task) at
Microsoft.AspNet.Routing.RouteCollection.d__9.MoveNext()
--- End of stack trace from previous location where exception was thrown --- at
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task
task) at
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task
task) at
Microsoft.AspNet.Builder.RouterMiddleware.d__4.MoveNext()
--- End of stack trace from previous location where exception was thrown --- at
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task
task) at
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task
task) at
Microsoft.AspNet.Hosting.Internal.RequestServicesContainerMiddleware.d__3.MoveNext()
--- End of stack trace from previous location where exception was thrown --- at
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task
task) at
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task
task) at
Microsoft.AspNet.Hosting.Internal.HostingEngine.<>c__DisplayClass32_0.<b__0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown --- at
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task
task) at
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task
task) at
Microsoft.AspNet.Server.Kestrel.Http.Frame.d__79.MoveNext()
请在 BindModelAsync
方法调用中将 return null
更改为 return Task.FromResult(ModelBindingResult.NoResult);
。
在 CompositeModelBinder.cs 的 64 行 var result = await binder.BindModelAsync(bindingContext);
中,当框架等待 Task
为 null
时发生错误
当尝试在 ASP.NET 5 RC1 中使用自定义模型联编程序进行解析时,我在调用操作时在 Microsoft.AspNet.Mvc.ModelBinding.CompositeModelBinder
中抛出 NullReferenceException
。
启动中的模型绑定:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(options =>
{
options.ModelBinders.Insert(0, new MyCustomModelBinder());
}
自定义模型活页夹:
public class MyCustomModelBinder : IModelBinder
{
public Task<ModelBindingResult> BindModelAsync(ModelBindingContext bindingContext)
{
if (bindingContext.ModelType == typeof(MyCustomClass) && bindingContext.ValueProvider.GetValue(bindingContext.ModelName) != null)
{
MyCustomClass model;
var val = bindingContext.ValueProvider.GetValue(bindingContext.ModelName).FirstValue as string;
if (MyCustomClass.TryParse(val, out model))
{
return Task.FromResult(ModelBindingResult.Success(bindingContext.ModelName, model));
}
}
return null;
}
}
控制器动作:
[HttpGet]
public IActionResult GetSomething([ModelBinder(BinderType = typeof(MyCustomModelBinder))]MyCustomClass key)
{
return Json("Success!");
}
异常:
System.NullReferenceException: Object reference not set to an instance of an object. at Microsoft.AspNet.Mvc.ModelBinding.CompositeModelBinder.d__5.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.AspNet.Mvc.Controllers.DefaultControllerActionArgumentBinder.d__6.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.AspNet.Mvc.Controllers.DefaultControllerActionArgumentBinder.d__9.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.AspNet.Mvc.Controllers.DefaultControllerActionArgumentBinder.d__5.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.AspNet.Mvc.Controllers.FilterActionInvoker.d__52.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.AspNet.Mvc.Controllers.FilterActionInvoker.d__51.MoveNext() --- End of stack trace from previous location where exception was thrown --- at Microsoft.AspNet.Mvc.Controllers.FilterActionInvoker.d__44.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.AspNet.Mvc.Infrastructure.MvcRouteHandler.d__6.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.AspNet.Mvc.Routing.InnerAttributeRoute.d__10.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.AspNet.Routing.RouteCollection.d__9.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.AspNet.Builder.RouterMiddleware.d__4.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.AspNet.Hosting.Internal.RequestServicesContainerMiddleware.d__3.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.AspNet.Hosting.Internal.HostingEngine.<>c__DisplayClass32_0.<b__0>d.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.AspNet.Server.Kestrel.Http.Frame.d__79.MoveNext()
请在 BindModelAsync
方法调用中将 return null
更改为 return Task.FromResult(ModelBindingResult.NoResult);
。
在 CompositeModelBinder.cs 的 64 行 var result = await binder.BindModelAsync(bindingContext);
中,当框架等待 Task
为 null