有没有办法能够从ASP.NET MVC Web API中的多部分表单数据请求中获取模型绑定(或任何)来发布模型?
我看到各种博客文章,但事情发生在实际版本和实际版本之间,或者它们不显示模型绑定工作。
这是一个过时的帖子:Sending HTML Form Data
这也是这样的:Asynchronous File Upload using ASP.NET Web API
模型:
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); }
这个代码基本上是脆弱的,不可维护的,进一步的,不强制模型绑定或数据注释约束。
有没有更好的方法来做到这一点?
解决方法
@Mark琼斯链接到我的博客文章
http://lonetechie.com/2012/09/23/web-api-generic-mediatypeformatter-for-file-upload/,带领我来到这里。我必须考虑如何做你想做的事情。
我相信如果你将我的方法与TryValidateProperty()结合起来,你应该可以完成你所需要的。我的方法会得到反序列化的对象,但是它不会处理任何验证。您需要使用反射来循环遍历对象的属性,然后在每个对象上手动调用TryValidateProperty()。这种方法是多一点手,但我不知道如何做到这一点。
http://msdn.microsoft.com/en-us/library/dd382181.aspx
http://www.codeproject.com/Questions/310997/TryValidateProperty-not-work-with-generic-function
编辑:有人问这个问题,我决定编写代码,以确保它的工作。这是我的博客中更新的验证检查代码。
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); } }