19

我有一个接受多个参数的 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=

这确实与我的控制器方法匹配,并且当执行该方法时,可以为空的参数确实是null(如您所料)。

但是ModelState.IsValid,对返回的调用false,当我检查错误时,它抱怨两个可为空的参数。(模型的其他位没有错误)。消息是:

需要一个值,但请求中不存在该值。

为什么它认为一个值是必需的/不存在的?当然(a)可空值不需要一个值,并且(b)一个值(某种)存在 - 以某种方式为空?

4

2 回答 2

25

除了第一个答案之外,如果您将所有可选项移动到方法声明的末尾,您应该能够让您的代码工作允许省略 url 上的前缀,并且我总是将它们设置为 NULL 以进行良好的衡量:

FileDto fileDto,
bool linkFromExistingFile,
Guid? previousTrackingId = null,
int? existingFileId = null

好点re:带有前缀的空URL值......它与NULL相同......考虑字符串,是?q=空字符串还是空字符串?

我试图在引发这些错误的框架中找到确切的逻辑(并继续寻找),但在我的实验过程中,我确实发现直接在 URL 参数上指定活页夹似乎绕过了逻辑并允许在前缀后使用空值没有模型绑定错误。

像这样:

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 };
    }     
}
于 2012-09-27T13:08:15.173 回答
9

我通过将所有参数移动到一个类来解决这个问题。

public class UploadFileModel {
   public FileDto FileDto { get; set; }
   public int? ExistingFileId { get; set; }
   public bool LinkFromExistingFile { get; set; }
   public Guid? PreviousTrackingId { get; set; }
}

public HttpResponseMessage UploadFile([FromUri]UploadFileModel model)
{
   // ...
}
于 2012-10-26T09:07:47.767 回答