【问题标题】:Posting models with NodaTime auto-props to WebAPI将带有 NodaTime 自动道具的模型发布到 WebAPI
【发布时间】:2014-08-06 18:37:20
【问题描述】:

我们正在将 NodaTime 用于我们项目中的时间/日期模型。该项目是一个使用 WebAPI 的 Web 应用程序。当尝试发布包含 LocalTime 自动属性的模型时,我们会收到 InsufficientExecutionStackException。

为了将我们的项目与这个问题隔离开来,我创建了一个新的 WebAPI 项目。使用 NuGet,我将 NodaTime 和 NodaTime.Serialization.JsonNet 添加到项目中。在Startup.cs 中,我使用了ConfigureForNodaTime

GlobalConfiguration.Configure(x =>
{
    x.Formatters.XmlFormatter.SupportedMediaTypes.Clear();
    x.Formatters.JsonFormatter.SerializerSettings.ConfigureForNodaTime(
    DateTimeZoneProviders.Tzdb);
});

在(样板文件)ValuesController.cs 文件中,我这样劫持了Post

// POST api/values
public void Post(TestClass input)
{
    var x = input;
}

public class TestClass
{
    public LocalTime Open { get; set; }
    public LocalTime Close { get; set; }
}

在发布此输入模型时(通过邮递员),而不是接收本地时间,我在帖子末尾收到错误消息。

如果我们重写TestClass,如图所示,不会发生错误,并且我们得到正确的当地时间:

public class TestClass
{
    public LocalTime;
    public LocalTime;
}

我可以做些什么来让应用程序使用 autoprops 吗?虽然我可以(并且可能会)开始用字段替换 autoprops,但很高兴了解这里发生了什么。

这是整个错误,从中间删除了 800 行任意行:

{
"message":"An error has occurred.",
"exceptionMessage":"Insufficient stack to continue executing the program safely. This can happen from having too many functions on the call stack or function on the stack using too much stack space.",
"exceptionType":"System.InsufficientExecutionStackException",
"stackTrace":"   at System.Runtime.CompilerServices.RuntimeHelpers.EnsureSufficientExecutionStack()
    at System.Web.Http.Validation.DefaultBodyModelValidator.ValidateNodeAndChildren(ModelMetadata metadata, ValidationContext validationContext, Object container, IEnumerable`1 validators)
    at System.Web.Http.Validation.DefaultBodyModelValidator.ValidateProperties(ModelMetadata metadata, ValidationContext validationContext)
    at System.Web.Http.Validation.DefaultBodyModelValidator.ValidateNodeAndChildren(ModelMetadata metadata, ValidationContext validationContext, Object container, IEnumerable`1 validators)
    at System.Web.Http.Validation.DefaultBodyModelValidator.ValidateElements(IEnumerable model, ValidationContext validationContext)
    at System.Web.Http.Validation.DefaultBodyModelValidator.ValidateNodeAndChildren(ModelMetadata metadata, ValidationContext validationContext, Object container, IEnumerable`1 validators)
    at System.Web.Http.Validation.DefaultBodyModelValidator.ValidateProperties(ModelMetadata metadata, ValidationContext validationContext)
    at System.Web.Http.Validation.DefaultBodyModelValidator.ValidateNodeAndChildren(ModelMetadata metadata, ValidationContext validationContext, Object container, IEnumerable`1 validators)
    at System.Web.Http.Validation.DefaultBodyModelValidator.ValidateProperties(ModelMetadata metadata, ValidationContext validationContext)
    at System.Web.Http.Validation.DefaultBodyModelValidator.ValidateNodeAndChildren(ModelMetadata metadata, ValidationContext validationContext, Object container, IEnumerable`1 validators)
    at System.Web.Http.Validation.DefaultBodyModelValidator.ValidateProperties(ModelMetadata metadata, ValidationContext validationContext)
    at System.Web.Http.Validation.DefaultBodyModelValidator.ValidateNodeAndChildren(ModelMetadata metadata, ValidationContext validationContext, Object container, IEnumerable`1 validators)
    at System.Web.Http.Validation.DefaultBodyModelValidator.ValidateProperties(ModelMetadata metadata, ValidationContext validationContext)
    at System.Web.Http.Validation.DefaultBodyModelValidator.ValidateNodeAndChildren(ModelMetadata metadata, ValidationContext validationContext, Object container, IEnumerable`1 validators)
    at System.Web.Http.Validation.DefaultBodyModelValidator.ValidateProperties(ModelMetadata metadata, ValidationContext validationContext)
    at System.Web.Http.Validation.DefaultBodyModelValidator.ValidateNodeAndChildren(ModelMetadata metadata, ValidationContext validationContext, Object container, IEnumerable`1 validators)
    at System.Web.Http.Validation.DefaultBodyModelValidator.ValidateProperties(ModelMetadata metadata, ValidationContext validationContext)
    at System.Web.Http.Validation.DefaultBodyModelValidator.ValidateNodeAndChildren(ModelMetadata metadata, ValidationContext validationContext, Object container, IEnumerable`1 validators)
    at System.Web.Http.Validation.DefaultBodyModelValidator.ValidateProperties(ModelMetadata metadata, ValidationContext validationContext)
    at System.Web.Http.Validation.DefaultBodyModelValidator.ValidateNodeAndChildren(ModelMetadata metadata, ValidationContext validationContext, Object container, IEnumerable`1 validators)
    at System.Web.Http.Validation.DefaultBodyModelValidator.ValidateProperties(ModelMetadata metadata, ValidationContext validationContext)
    at System.Web.Http.Validation.DefaultBodyModelValidator.ValidateNodeAndChildren(ModelMetadata metadata, ValidationContext validationContext, Object container, IEnumerable`1 validators)
    at System.Web.Http.Validation.DefaultBodyModelValidator.Validate(Object model, Type type, ModelMetadataProvider metadataProvider, HttpActionContext actionContext, String keyPrefix)
    at System.Web.Http.ModelBinding.FormatterParameterBinding.<ExecuteBindingAsyncCore>d__0.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 System.Runtime.CompilerServices.TaskAwaiter.GetResult()
    at System.Web.Http.Controllers.HttpActionBinding.<ExecuteBindingAsyncCore>d__0.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 System.Runtime.CompilerServices.TaskAwaiter.GetResult()
    at System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__2.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 System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
    at System.Web.Http.Filters.AuthorizationFilterAttribute.<ExecuteAuthorizationFilterAsyncCore>d__2.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 System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
    at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__0.MoveNext()"
}

【问题讨论】:

  • 你能试试 Noda Time 2.0 吗?如果有帮助的话,我可以制作一个预发布的 Nuget 版本...... 2.0 中有很多重大更改,所以这只是暂时的 - 但很高兴知道它是否能解决问题。跨度>
  • 我很乐意用 Noda Time 2.0 测试它,但我不知道如何获得它。
  • 您可以只获取源代码并自己构建它,或者我可以构建并发布一个预发布的 Nuget 包。您目前正在使用 Nuget 包吗?
  • 我目前正在使用 Nuget 包。我不介意自己检查项目,但必须等到今天晚些时候。
  • 好的 - 无论如何,出于其他原因构建预发布版本对我来说很有用;我今晚会继续,完成后在这里ping。非常感谢!

标签: c# asp.net-web-api nodatime


【解决方案1】:

这似乎是一个 WebAPI 问题,但我不完全了解根本原因,也不是特别喜欢这个解决方案。但是,基于the code in this answer,我想出了一个解决方法:

public class CustomBodyModelValidator : DefaultBodyModelValidator
{
    public override bool ShouldValidateType(Type type)
    {
        return type.Namespace != "NodaTime" && base.ShouldValidateType(type);
    }
}

在您的配置 lambda 中(或您访问全局 WebAPI 配置的任何位置:

x.Services.Replace(typeof(IBodyModelValidator), new CustomBodyModelValidator());

在我(或其他人)找到更好的解决方案之前,请考虑这是一种变通方法。谢谢。

更新:经过进一步研究,这似乎已经以issue #249 的身份发布到 Noda Time 问题跟踪器,并提出了类似的解决方案。

【讨论】:

猜你喜欢
  • 2016-07-22
  • 2013-01-17
  • 1970-01-01
  • 2021-03-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多