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オブジェクトがリクエストの本文に配置され、その他のパラメータがクエリ文字列に配置されます。

null許容パラメータを単純に省略することはできないことをすでに発見しました。空の値を使用してクエリ文字列にそれらを配置する必要があります。したがって、null許容パラメータの値を指定したくない場合、クエリは次のようになります。

http://myserver/api/files?existingFileId=&linkFromExistingFile=true&previousTrackingId=

これは私のコントローラーメソッドと一致します。メソッドが実行されると、null許容パラメーターは実際にnull(予想どおり)です。

ただし、への呼び出しはをModelState.IsValid返しますfalse。エラーを調べると、null許容パラメータの両方について不平を言っています。(モデルの他のビットにはエラーがありません)。メッセージは次のとおりです。

値が必要ですが、リクエストに含まれていませんでした。

なぜ値が必要である/存在しないと考えるのですか?確かに、(a)null許容型には値は必要ありません、そして(b)値は(ある種の)存在していました-ある意味でnullっぽいのですか?

4

2 に答える 2

25

最初の答えに加えて、すべてのオプションをメソッド宣言の最後に移動し、適切な測定のために常にそれらを NULL に設定すると、URL のプレフィックスを省略できるようにコードを機能させることができるはずです。

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

しかし

良い点 re: プレフィックス付きの空の URL 値... NULL と同じですか... 文字列について考えると?q=、空の文字列ですか、それとも null ですか??

フレームワークでこれらのエラーを発生させる正確なロジックを見つけようとしましたが (引き続き調査を続けます)、実験中に、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

I solved this by moving all the parameters to a single class.

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 に答える