Mrc*_*ief 24 asp.net-mvc c#-4.0 asp.net-mvc-3 asp.net-web-api
有没有办法能够从ASP.NET MVC Web API中的多部分表单数据请求中获取模型绑定(或其他)?
我看到各种博客帖子,但是在帖子和实际版本之间发生了变化,或者它们没有显示模型绑定工作.
这是一篇过时的帖子:发送HTML表单数据
这是这样的:使用ASP.NET Web API进行异步文件上载
我发现这个代码(并修改了一下)在某处手动读取值:
模型:
public class TestModel
{
[Required]
public byte[] Stream { get; set; }
[Required]
public string MimeType { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
控制器:
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);
}
Run Code Online (Sandbox Code Playgroud)
测试:
[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);
}
Run Code Online (Sandbox Code Playgroud)
此代码基本上是脆弱的,不可维护的,并且不会强制执行模型绑定或数据注释约束.
有一个更好的方法吗?
更新:我看过这篇文章,这让我觉得 - 我是否必须为每一个我想支持的模型编写一个新的格式化程序?
这里有一个用于文件上传的通用格式化程序的好例子http://lonetechie.com/2012/09/23/web-api-generic-mediatypeformatter-for-file-upload/.如果我要让多个控制器接受文件上传,那么这将是我采取的方法.
PS环顾四周似乎是您在控制器中上传的更好示例http://www.strathweb.com/2012/08/a-guide-to-asynchronous-file-uploads-in-asp-net-web- API-RTM /
更新
回复:多部分方法的实用性,这是盖在这里 ,但实际上,这归结为多途径幸福建立显著大小的二进制有效载荷等..
DEFAULT模型绑定是否有效?
WebApi的标准/默认模型绑定器不是为了应对您指定的模型而构建的,即混合简单类型和Streams和字节数组的模型(不是那么简单)......这是引用lonetechie的文章的引用:
"简单类型"使用模型绑定.复杂类型使用格式化程序."简单类型"包括:基元,TimeSpan,DateTime,Guid,Decimal,String或具有从字符串转换的TypeConverter的东西
您在模型上使用字节数组以及从请求的流/内容创建该数组的需要将指导您使用格式化程序.
分别发送模型和文件?
就个人而言,我希望将文件上传与模型分开...也许不是你的选择...这样你就可以在使用MultiPart数据内容类型时POST到同一个Controller和路由,这将调用文件上传格式化程序当你使用application/json或x-www-form-urlencoded然后它会做简单的类型模型绑定...两个POST对你来说可能是不可能的,但它是一个选项......
定制型号粘合剂?
我在自定义模型绑定器上取得了一些小小的成功,你可以用这个做点什么......这可以做成通用的(有一些适度的努力),并且可以在绑定器提供程序中全局注册以便重用...
这可能值得玩吗?
public class Foo
{
public byte[] Stream { get; set; }
public string Bar { get; set; }
}
public class FoosController : ApiController
{
public void Post([ModelBinder(typeof(FileModelBinder))] Foo foo)
{
//
}
}
Run Code Online (Sandbox Code Playgroud)
定制模型粘合剂:
public class FileModelBinder : System.Web.Http.ModelBinding.IModelBinder
{
public FileModelBinder()
{
}
public bool BindModel(
System.Web.Http.Controllers.HttpActionContext actionContext,
System.Web.Http.ModelBinding.ModelBindingContext bindingContext)
{
if (actionContext.Request.Content.IsMimeMultipartContent())
{
var inputModel = new Foo();
inputModel.Bar = ""; //From the actionContext.Request etc
inputModel.Stream = actionContext.Request.Content.ReadAsByteArrayAsync()
.Result;
bindingContext.Model = inputModel;
return true;
}
else
{
throw new HttpResponseException(actionContext.Request.CreateResponse(
HttpStatusCode.NotAcceptable, "This request is not properly formatted"));
}
}
}
Run Code Online (Sandbox Code Playgroud)
@Mark Jones链接到我的博客文章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);
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
30181 次 |
最近记录: |