具有多部分表单数据的 Web API 模型绑定 [英] Web API Model Binding with Multipart formdata

查看:15
本文介绍了具有多部分表单数据的 Web API 模型绑定的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有没有办法获得模型绑定(或其他)以从 ASP.NET MVC Web API 中的多部分表单数据请求中给出模型?

Is there a way to be able to get model binding (or whatever) to give out the model from a multipart form data request in ASP.NET MVC Web API?

我看到各种博客文章,但要么在文章和实际发布之间发生了变化,要么它们没有显示模型绑定有效.

I see various blog posts but either things have changed between the post and actual release or they don't show model binding working.

这是一篇过时的帖子:发送 HTML 表单数据

所以是这样的:使用 ASP.NET Web API 的异步文件上传

我在某个地方发现了这个代码(并做了一些修改),它可以手动读取值:

I found this code (and modified a bit) somewhere which reads the values manually:

型号:

public class TestModel
{
    [Required]
    public byte[] Stream { get; set; }

    [Required]
    public string MimeType { get; set; }
}

控制器:

    public HttpResponseMessage Post()
    {
        if (!Request.Content.IsMimeMultipartContent("form-data"))
        {
            throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
        }

        IEnumerable<HttpContent> parts = Request.Content.ReadAsMultipartAsync().Result.Contents;


        string mimeType;
        if (!parts.TryGetFormFieldValue("mimeType", out mimeType))
        {
            return Request.CreateResponse(HttpStatusCode.BadRequest);
        }

        var media = parts.ToArray()[1].ReadAsByteArrayAsync().Result;

        // create the model here
        var model = new TestModel()
            {
                MimeType = mimeType,
                Stream = media
            };
        // save the model or do something with it
        // repository.Save(model)

        return Request.CreateResponse(HttpStatusCode.OK);
    }

测试:

[DeploymentItem("test_sound.aac")]
[TestMethod]
public void CanPostMultiPartData()
{
    var content = new MultipartFormDataContent { { new StringContent("audio/aac"),  "mimeType"}, new ByteArrayContent(File.ReadAllBytes("test_sound.aac")) };

    this.controller.Request = new HttpRequestMessage {Content = content};
    var response = this.controller.Post();

    Assert.AreEqual(response.StatusCode, HttpStatusCode.OK);
}

这段代码基本上是脆弱的、不可维护的,而且没有强制执行模型绑定或数据注释约束.

This code is basically fragile, un-maintainable and further, doesn't enforce the model binding or data annotation constraints.

有没有更好的方法来做到这一点?

Is there a better way to do this?

更新:我看到了这个post 这让我想到 - 我是否必须为我想要支持的每个模型编写一个新的格式化程序?

Update: I've seen this post and this makes me think - do I have to write a new formatter for every single model that I want to support?

推荐答案

@Mark Jones 链接到我的博客文章 http://lonetechie.com/2012/09/23/web-api-generic-mediatypeformatter-for-file-upload/ 其中导致我在这里.我必须考虑如何做你想做的事.

@Mark Jones linked over to my blog post http://lonetechie.com/2012/09/23/web-api-generic-mediatypeformatter-for-file-upload/ which led me here. I got to thinking about how to do what you want.

我相信如果您将我的方法与 TryValidateProperty() 结合使用,您应该能够完成您所需要的.我的方法将反序列化一个对象,但它不处理任何验证.您可能需要使用反射来遍历对象的属性,然后在每个属性上手动调用 TryValidateProperty().这种方法需要更多的动手,但我不知道该怎么做.

I believe if you combine my method along with TryValidateProperty() you should be able accomplish what you need. My method will get an object deserialized, however it does not handle any validation. You would need to possibly use reflection to loop through the properties of the object then manually call TryValidateProperty() on each one. This method it is a little more hands on but I'm not sure how else to do it.

http://msdn.microsoft.com/en-us/library/dd382181.aspxhttp://www.codeproject.com/Questions/310997/TryValidateProperty-not-work-with-generic-function

其他人问了这个问题,我决定对其进行编码以确保它可以工作.这是我更新的博客代码,带有验证检查.

Someone else asked this question and I decided to code it just to make sure it would work. Here is my updated code from my blog with validation checks.

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);
    }
}

这篇关于具有多部分表单数据的 Web API 模型绑定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆