我有一个ApiController方法接受几个参数,像这样:
// POST api/files public HttpResponseMessage UploadFile ( FileDto fileDto,int? existingFileId,bool linkFromExistingFile,Guid? prevIoUsTrackingId ) { if (!ModelState.IsValid) return Request.CreateResponse(HttpStatusCode.BadRequest); ... }
当我POST到这个我把FileDto对象放在请求的正文中,并且查询字符串上的其他参数.
我已经发现我不能简单地省略可空参数 – 我需要把它们放在一个空值的查询字符串上.所以,当我不想为可空参数指定一个值时,我的查询看起来像这样:
http://myserver/api/files?existingFileId=&linkFromExistingFile=true&prevIoUsTrackingId=
这与我的控制器方法相符,当执行该方法时,可空参数确实为空(如您所料).
但是,对ModelState.IsValid的调用返回false,当我检查错误时,它会抱怨两个可空参数. (模型的其他位没有错误).消息是:
A value is required but was not present in the request.
为什么它认为需要/不存在价值?当然(a)一个值可以是空的,并且(b)一个值是(排序的)存在的 – 一个空的方式?
解决方法
除了第一个答案之外,如果将所有可选项移动到方法声明的末尾,您应该能够使您的代码工作,允许省略前缀的url,并且我总是将其设置为NULL以获得良好的度量值:
FileDto fileDto,Guid? prevIoUsTrackingId = null,int? existingFileId = null
但
好点re:一个带有前缀的空URL值…与NULL一样…考虑字符串,是?q =空字符串或空?
我试图找到框架中的确切逻辑(并继续看)引发了这些错误,但是在我的实验过程中,我发现直接在URL参数上指定了一个binder,似乎绕过了逻辑,并允许一个前缀后的空值没有模型绑定错误.
像这样:
public class ValuesController : ApiController { // GET api/values public IEnumerable<string> Get( [FromUri(BinderType = typeof(TypeConverterModelBinder))] string q = null,[FromUri(BinderType = typeof(TypeConverterModelBinder))] int? value = null) { if (!ModelState.IsValid) { throw new HttpResponseException(HttpStatusCode.BadRequest); } return new string[] { value.HasValue ? value.Value.ToString() : "",q }; } }