为什么WebApi将空字符串标记为模型状态中的错误?

Aen*_*dhe 7 c# asp.net-web-api

我有Web API的奇怪行为,.Net 4.5.2.如果可选字符串参数为null,则ModelState没有错误.如果它不为空且不为空,则不会再出现错误.但如果它只是一个空字符串我有模型状态错误.

为什么我得到它以及如何禁用它?

假设应用程序服务localhost:82我有这些结果:

Url: http://localhost:82/
Response: "null"

Url: http://localhost:82/?q=1
Response: "1"

Url: http://localhost:82/?q=
Response: {
  "Message": "The request is invalid.",
  "ModelState": {
    "q.String": [
      "A value is required but was not present in the request."
    ]
  }
}
Run Code Online (Sandbox Code Playgroud)

测试控制器和配置如下.在VS2013中,这被简化为"WebApi"的默认"Asp.net Web应用程序".

namespace Web.Api.Test.Controllers
{
    using System.Web.Http;

    [Route]
    public class HomeController : ApiController
    {
        [Route]
        [HttpGet]
        public IHttpActionResult Search(string q = default(string))
        {
            return this.ModelState.IsValid
                ? this.Ok(q ?? "null")
                : (IHttpActionResult)this.BadRequest(this.ModelState);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Startup.cs是:

using Microsoft.Owin;

using WebApplication1;

[assembly: OwinStartup(typeof(Startup))]

namespace WebApplication1
{
    using System.Web.Http;

    using Newtonsoft.Json;

    using Owin;

    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            GlobalConfiguration.Configure(config =>
            {
                config.MapHttpAttributeRoutes();
                config.Formatters.JsonFormatter.SerializerSettings.Formatting = Formatting.Indented;

                config.Formatters.Remove(config.Formatters.XmlFormatter);
            });
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

PS:这个问题有一个解决方法,但它没有回答主要问题:为什么会出现这种情况以及这个设计决策背后的原因.

小智 5

我遇到了同样的问题,最终想出了以下内容:

public class SimpleTypeParameterBindingFactory
{
    private readonly TypeConverterModelBinder converterModelBinder = new TypeConverterModelBinder();
    private readonly IEnumerable<ValueProviderFactory> factories;

    public SimpleTypeParameterBindingFactory(HttpConfiguration configuration)
    {
        factories = configuration.Services.GetValueProviderFactories();
    }

    public HttpParameterBinding BindOrNull(HttpParameterDescriptor descriptor)
    {
        return IsSimpleType(descriptor.ParameterType)
            ? new ModelBinderParameterBinding(descriptor, converterModelBinder, factories)
            : null;
    }

    private static bool IsSimpleType(Type type)
    {
        return TypeDescriptor.GetConverter(type).CanConvertFrom(typeof (string));
    }
}

public class Startup
{
    public void Configure(IAppBuilder appBuilder)
    {
        var configuration = new HttpConfiguration();
        configuration.ParameterBindingRules.Insert(0, new SimpleTypeParameterBindingFactory(configuration).BindOrNull);
        configuration.EnsureInitialized();
    }
}
Run Code Online (Sandbox Code Playgroud)

The problem is rooted in some magic code in ModelValidationNode, which creates model errors for null models even if corresponding parameter has default value. The code above just replaces CompositeModelBinder (which calls ModelValidationNode) with TypeConverterModelBinder for simple type parameters.


stu*_*bax 1

这就是为什么:

这是一个 MVC 功能,它将空字符串绑定到 null。

我们在我们的应用程序中发现了相同的行为,并使用源代码进行了深入调试

git clone https://github.com/ASP-NET-MVC/aspnetwebstack
Run Code Online (Sandbox Code Playgroud)

朝着正确的方向进行搜索是有意义的。这里是将空白字符串设置为 null 的方法,并将错误添加到模型状态中:

if (parentNode == null && ModelMetadata.Model == null)
{
    string trueModelStateKey = ModelBindingHelper.CreatePropertyModelName(ModelStateKey, ModelMetadata.GetDisplayName());
    modelState.AddModelError(trueModelStateKey, SRResources.Validation_ValueNotFound);
    return;
}
Run Code Online (Sandbox Code Playgroud)

恕我直言,这是一个错误。但谁在乎。我们使用了这个解决方法