c# - 使用 C# ASP.NET WebAPI 2.0 在 InputModel 主体中绑定(bind) NodaTime Instant 字段

标签 c# json asp.net-web-api2 model-binding nodatime

我有一个 WebAPI 项目,它在输入模型中接收 ISO 日期字符串。我一直在使用 DateTimeOffset? 解析这些。我想从我的项目中消除 BCL 日期时间,所以我想找到一种方法将这些字符串直接绑定(bind)到 Instant

public class MyInputModel
{
    public DateTimeOffset? OldTime { get; set; }

    public Instant NewTime { get; set; }
}

示例 JSON 输入模型如下所示:

{
    "oldtime":"2016-01-01T12:00:00Z",
    "newtime":"2016-01-01T12:00:00Z"
}

我的 Controller 代码是:

[HttpPost]
public async Task<IActionResult> PostTimesAsync([FromBody]MyInputModel input)
{
    Instant myOldTime = Instant.FromDateTimeUtc(input.oldTime.Value.UtcDateTime);
    Instant myNewTime = input.newTime; // This cannot be used with ISO date strings.
}

我尝试按如下方式构建自定义模型 Binder 。 这适用于查询字符串中的模型,但不适用于 POST 请求正文中的模型。如何将 ISO 8601 字符串格式的日期输入绑定(bind)到 NodaTime Instant?

public Task BindModelAsync(ModelBindingContext bindingContext)
{
    if (!String.IsNullOrWhiteSpace(bindingContext.ModelName) && 
            bindingContext.ModelType == typeof(Instant?) && 
            bindingContext.ValueProvider.GetValue(bindingContext.ModelName) != null)
    {
        Instant? value;
        var val = bindingContext.ValueProvider
.GetValue(bindingContext.ModelName).FirstValue as string;

        if (String.IsNullOrWhiteSpace(val))
        {
            bindingContext.Result = ModelBindingResult.Failed();
            return Task.FromResult(0);
        }
        else if (InstantExtensions.TryParse(val, out value))
        {
            bindingContext.Result = ModelBindingResult.Success(value);
            return Task.FromResult(0);
        }
        else
        {
            bindingContext.ModelState.AddModelError(bindingContext.ModelName, 
"The date is invalid.");
        }
    }

    bindingContext.Result = ModelBindingResult.Failed();
    return Task.FromResult(0);
}

public static bool TryParse(string value, out Instant? result)
{
    result = null;

    // If this is date-only, add Utc Midnight to the value.
    if (value.Length.Equals(10))
    {
        value += "T00:00:00Z";
    }

    // Trim milliseconds if present
    var decimalPointIndex = value.IndexOf('.');
    if (decimalPointIndex > 0)
    {
        value = value.Substring(0, decimalPointIndex) + "Z";
    }

    // Attempt to parse
    var parseResult = InstantPattern.GeneralPattern.Parse(value);
    if (parseResult.Success)
    {
        result = parseResult.Value;
        return true;
    }

    return false;
}

最佳答案

您应该像这样添加您的模型绑定(bind)器:(在 WebApiConfig Register 方法中)

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        config.BindParameter(typeof(Instant), new InstantModelBinder())
        ...
    }
}

WebApiConfig.Register 在 Startup.cs 文件的 Configuration 函数中被调用。在大多数情况下是这样的:

var config = new HttpConfiguration();
WebApiConfig.Register(config);

如果没有被调用,你可以添加这一行:

config.BindParameter(typeof(Instant), new InstantModelBinder())

Startup.cs 中创建 HttpConfiguration 对象。

关于c# - 使用 C# ASP.NET WebAPI 2.0 在 InputModel 主体中绑定(bind) NodaTime Instant 字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38695213/

相关文章:

python - 按键值对 JSON 数据进行排序

java - 无法在类 org.apache.logging.log4j.core.layout.JsonLayout 中为元素 JsonLayout 调用工厂方法

c# - 如何在 ASP.NET ApiController 中捕获 g-recaptcha-response?

c# - ASP.Net Web API Swashbuckle 如何忽略 HttpRequestMessage

c# - 访问静态类的配置/设置 - Asp Core

c# - 我什么时候可以在 native foreach 循环上使用 List<T>.ForEach?

c# - 如何使用 View Component 按名称调用 PartialView 而不是加载 default.cshtml

php - PHP SQL 查询中的 JSON 问题

asp.net-web-api2 - SessionID 在 ASP.NET Core web api 中不断变化

c# - MVC ListBox 多项选择在发布时 Controller 中只有一个值