0

webapi で multipartform の投稿データを読み取るために、カスタム メディア フォーマッタを使用しています。カスタム アクション フィルター属性でシリアル化エラーと検証エラーを処理します。フォーマッタでは、入力を Type Object ImageMedia にマッピングしています。ActionContext を受け取る CustomFilterAttribute 内のエラーを処理できるように、シリアル化エラーを ModelState に追加したいと考えています。コードは次のとおりです。

public class ImageMediaFormatter : MediaTypeFormatter
{
    public ImageMediaFormatter()
    {
        SupportedMediaTypes.Add(new MediaTypeHeaderValue("image/jpeg"));
        SupportedMediaTypes.Add(new MediaTypeHeaderValue("image/jpg"));
        SupportedMediaTypes.Add(new MediaTypeHeaderValue("image/png"));
        SupportedMediaTypes.Add(new MediaTypeHeaderValue("image/gif"));
        SupportedMediaTypes.Add(new MediaTypeHeaderValue("multipart/form-data"));
    }

    public override bool CanReadType(Type type)
    {
        return type == typeof(ImageMedia);
    }

    public override bool CanWriteType(Type type)
    {
        return false;
    }

    public override Task<object> ReadFromStreamAsync(
       Type type, Stream stream, HttpContent request,
       IFormatterLogger formatterContext)
    {
        return Task.Factory.StartNew<object>(() =>
        {
            var streamProvider = new MultipartMemoryStreamProvider();
            var keys = new Dictionary<string, string>();

            var result = request.ReadAsMultipartAsync(streamProvider).Result;

            //get and remove random slashes from posted vaues
            var categoryid = 
            streamProvider.Contents.First(x => x.Headers.ContentDisposition.Name.Contains("userGeneratedCategoryId")).ReadAsStringAsync().Result.Replace("\"", string.Empty);
            keys.Add(Constants.UserGeneratedCategoryId, categoryid);

            var imageBuffer =
                streamProvider.Contents.First(x => x.Headers.ContentDisposition.Name.Contains(Constants.ImageFile)).ReadAsByteArrayAsync().Result;

            return new ImageMedia(keys, imageBuffer);
        });
    }           
}           



 public class ImageMedia 
{
    public ImageMedia(Dictionary<string, string> keys, byte[] imageBuffer)
        : this()
    {
        var keyvaluePair = new KeyValuePair<string, string>();
        foreach (var property in GetType().GetProperties())
        {
            try
            {
                keyvaluePair = keys.FirstOrDefault(pair => pair.Key.ToLower() == property.Name.ToLower());
                if (!string.IsNullOrEmpty(keyvaluePair.Key))
                {
                    property.SetValue(this, keyValuePair.Value, null);
                }
            }
            catch (Exception ex)
            {
                // Add these serialization errors to the Model State so I can handle these in a Custom Validation Action Attribute

                Errors.Add(keyvaluePair.Key, new List<string> { ex.Message });                    
                IsValid = false;                    
            }
        }
        Buffer = imageBuffer;
    }

    private ImageMedia()
    {
        Errors = new Dictionary<string, List<string>>();           
    }

    public int UserGeneratedCategoryId { get; set; }
    public byte[] Buffer { get;set;}
}
4

1 に答える 1

1

メソッドIFormatterLoggerに渡される提供されたコンテキストにエラーを追加できます。ReadFromStreamAsync

public override Task<object> ReadFromStreamAsync(Type type, Stream stream, HttpContent request,
   IFormatterLogger formatterContext)

例:

formatterLogger.LogError(errorPath: "OrderedDate", errorMessage: "Not a valid date");
于 2013-07-25T14:52:19.197 に答える