5

ファイル アップロード用の Web API をテストするには、次のような単純なビュー モデルを用意します。

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

メソッドで使用:

[HttpPost]
public void Create(TestModel model)

multipart/form-data でエンコードされたフォームをアクションに投稿しようとすると、次の例外が発生します。

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 つの呼び出しに分離するだけであるという言及がいくつか見つかりました。アップロードされたファイルで実際に何かを行うには、他のフィールドを投稿する必要があるため、これはうまくいきません。これを達成する方法はありますか?

4

2 に答える 2

5

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

Mike Wasson による優れたチュートリアルがここにあります: http://www.asp.net/web-api/overview/working-with-http/sending-html-form-data,-part-2

于 2012-10-02T22:01:57.923 に答える
3

元の回答を参照して ください https://stackoverflow.com/a/12603828/1171321

基本的に、ブログ投稿のメソッドと TryValidateProperty() の提案を組み合わせて、モデルの検証注釈を維持します。

編集: 先に進んで、ブログ投稿で自分のコードのコード拡張を行いました。この更新されたコードをまもなく投稿します。各プロパティを検証し、結果の配列にアクセスできるようにする簡単な例を次に示します。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);
    }
}
于 2012-10-03T22:43:26.600 に答える