2012-10-02 17 views
5

テスト実行ファイルアップロード用のWeb APIは、このような単純なビューモデルを持っている:メソッドで使用さWeb APIモデルバインダーはHttpPostedFileBaseで動作しませんか?

public class TestModel { 
    public string UserId {get;set;} 
    public HttpPostedFileBase ImageFile {get;set;} 
} 

[HttpPost] 
public void Create(TestModel model) 

私はマルチパート/フォームデータのエンコード形式を投稿しようとすると、アクションに、私はこの例外を受け取る:

System.InvalidOperationException: No MediaTypeFormatter is available to read an object of type 'TestModel' from content with media type 'multipart/form-data'. 
    at System.Net.Http.HttpContentExtensions.ReadAsAsync[T](HttpContent content, Type type, IEnumerable`1 formatters, IFormatterLogger formatterLogger) 
    at System.Net.Http.HttpContentExtensions.ReadAsAsync(HttpContent content, Type type, IEnumerable`1 formatters, IFormatterLogger formatterLogger) 
    at System.Web.Http.ModelBinding.FormatterParameterBinding.ReadContentAsync(HttpRequestMessage request, Type type, IEnumerable`1 formatters, IFormatterLogger formatterLogger) 
    at System.Web.Http.ModelBinding.FormatterParameterBinding.ExecuteBindingAsync(ModelMetadataProvider metadataProvider, HttpActionContext actionContext, CancellationToken cancellationToken) 
    at System.Web.Http.Controllers.HttpActionBinding.<>c__DisplayClass1.<ExecuteBindingAsync>b__0(HttpParameterBinding parameterBinder) 
    at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext() 
    at System.Threading.Tasks.TaskHelpers.IterateImpl(IEnumerator`1 enumerator, CancellationToken cancellationToken) 

これはデフォルトのMVCモデルバインダーで動作しますが、どうやらないのWeb APIのと。ファイルをアップロードするときにビューモデルを使用することができず、データを2つの呼び出しに分けるといういくつかの言及が見つかりました。アップロードされたファイルで実際に何かを行うには、他のフィールドを投稿する必要があるので、私にとってはうまくいきません。これを達成する方法はありますか?

+0

動作させるにはカスタムの 'MediaTypeFormatter'を書く必要があります。あなたが経験したように、 "multipart/form-data"はそのままではサポートされていません。あなたは[ここ](http://lonetechie.com/2012/09/23/web-api-generic-mediatypeformatter-for-file-upload/) – nemesv

答えて

3

は、私のオリジナルの答え https://stackoverflow.com/a/12603828/1171321

は基本的に私のブログの記事で私の方法を組み合わせて、TryValidateProperty()提案モデルの検証注釈を維持するために参照してください。

編集: 私は先に進み、ブログ記事のコードにコードの機能強化を加えました。私はまもなくこの更新されたコードを投稿します。次に、各プロパティを検証し、結果の配列にアクセスする簡単な例を示します。 1つのアプローチのちょうど1つのサンプル

public class FileUpload<T> 
{ 
    private readonly string _RawValue; 

    public T Value { get; set; } 
    public string FileName { get; set; } 
    public string MediaType { get; set; } 
    public byte[] Buffer { get; set; } 

    public List<ValidationResult> ValidationResults = new List<ValidationResult>(); 

    public FileUpload(byte[] buffer, string mediaType, string fileName, string value) 
    { 
     Buffer = buffer; 
     MediaType = mediaType; 
     FileName = fileName.Replace("\"",""); 
     _RawValue = value; 

     Value = JsonConvert.DeserializeObject<T>(_RawValue); 

     foreach (PropertyInfo Property in Value.GetType().GetProperties()) 
     { 
      var Results = new List<ValidationResult>(); 
      Validator.TryValidateProperty(Property.GetValue(Value), 
              new ValidationContext(Value) {MemberName = Property.Name}, Results); 
      ValidationResults.AddRange(Results); 
     } 
    } 

    public void Save(string path, int userId) 
    { 
     if (!Directory.Exists(path)) 
     { 
      Directory.CreateDirectory(path); 
     } 
     var SafeFileName = Md5Hash.GetSaltedFileName(userId,FileName); 
     var NewPath = Path.Combine(path, SafeFileName); 
     if (File.Exists(NewPath)) 
     { 
      File.Delete(NewPath); 
     } 

     File.WriteAllBytes(NewPath, Buffer); 

     var Property = Value.GetType().GetProperty("FileName"); 
     Property.SetValue(Value, SafeFileName, null); 
    } 
} 
5

シナリオを容易にするためにMediaTypeFormatterというカスタムを書くか、MultipartFormDataStreamProvider.FormData.AllKeysコレクションを使用して手作業でデータを引き出すことができます。この方法で、ファイルと追加フィールドの両方を1回のリクエストで送信できます。

マイク・ワッソンことで良いのチュートリアルはここにあります:http://www.asp.net/web-api/overview/working-with-http/sending-html-form-data,-part-2

+7

を開始することができますので、記事を読んだ後、私はこれを行う方法を参照してください。しかし、私が誤解していない限り、モデルバインダー(とそれに伴うさまざまなデータ注釈のすべて)を使用する方法はまだありません。だから、すべての入力を手動で検証する必要がありますか?モデルバインダーでこの変更が必要な理由を偶然に知っていますか? APIプロジェクトに既存のモデルを使用できるという考え方をかなり効果的に破り、本当に奇妙な方向性があるように思えます。 – heyseuss

関連する問題