网页API模型多部分FORMDATA绑定 [英] Web API Model Binding with Multipart formdata

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

问题描述

有没有一种办法能够得到模型绑定(或其他),以从 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表单数据

This is an outdated post: Sending HTML Form Data

所以是这样的:<一href=\"http://blogs.msdn.com/b/henrikn/archive/2012/03/01/file-upload-and-asp-net-web-api.aspx\">Asynchronous使用ASP.NET的Web API 文件上传

and so is this: Asynchronous File Upload using ASP.NET Web API

我发现这个code(和修改了一下),其中地方手动读取值:

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

这code基本上是脆弱的,未维护和进一步,不会强制模型绑定或数据注解的约束。

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?

更新:我已经看到了这个的帖子,这让我觉得 - 我必须写,我要支持每一个模型的新格式

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?

推荐答案

@马克·琼斯链接到我的博客文章的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.aspx
<一href=\"http://www.$c$cproject.com/Questions/310997/TryValidateProperty-not-work-with-generic-function\" rel=\"nofollow\">http://www.$c$cproject.com/Questions/310997/TryValidateProperty-not-work-with-generic-function

编辑:别人问这个问题,我决定code这只是为了确保它的工作。这是我更新code从我的博客与验证检查。

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

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

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