模型绑定不适用于 asp.net 核心 Web api 控制器操作方法中的 Stream 类型参数。(即使使用自定义流输入格式化程序)
Posted
技术标签:
【中文标题】模型绑定不适用于 asp.net 核心 Web api 控制器操作方法中的 Stream 类型参数。(即使使用自定义流输入格式化程序)【英文标题】:Model binding not working with Stream type parameter in asp.net core webapi controller action method.(Even with custom streaminputformatter) 【发布时间】:2016-12-27 13:29:45 【问题描述】:我想将文件上传到 asp net core web api 控制器操作方法。我将内容类型作为“应用程序/八位字节流”发送。我创建了名为 StreamInputFormatter 的自定义输入格式化程序。 streaminputformatter 被调用,但控制器中的操作方法没有被调用?并且我收到错误
“InvalidOperationException:此流不支持超时。”
StreamInputFormatter:
public class StreamInputFormatter : IInputFormatter
public bool CanRead(InputFormatterContext context)
if (context == null)
throw new ArgumentNullException(nameof(context));
var contentType = context.HttpContext.Request.ContentType;
if (contentType == "application/octet-stream")
return true;
return false;
public Task<InputFormatterResult> ReadAsync(InputFormatterContext context)
if (context == null)
throw new ArgumentNullException(nameof(context));
var memoryStream = new MemoryStream();
context.HttpContext.Request.Body.CopyTo(memoryStream);
return InputFormatterResult.SuccessAsync(memoryStream);
控制器动作方法:
[HttpPost("documentType")]
public async Task<IActionResult> CreateJob(string documentType, [FromBody]Stream template)
【问题讨论】:
您在哪里使用了 StreamInputFormatter?对于 Startup.cs 中的中间件?可以分享代码吗? 你试过字节数组吗? [FromBody]byte[] 模板 【参考方案1】:听起来您收到此错误是因为DefaultObjectValidator
迭代了您不受支持的Stream
属性(有关一些信息,请参阅此issue)。
要跳过流模型验证,您可以添加
services.AddMvc(options =>
...
options.ModelMetadataDetailsProviders.Add(new SuppressChildValidationMetadataProvider(typeof(Stream)));
);
到你的配置。
【讨论】:
当您有一个复杂的类型,验证将无法帮助您使用 SuppressChildValidationMetadataProvider 时,最好的方法是跳过它【参考方案2】:对于寻找完整示例的任何人,以下内容可能会有所帮助:
Startup.cs
services.AddMvc(options =>
options.InputFormatters.Add(new StreamInputFormatter());
options.ModelMetadataDetailsProviders.Add(new SuppressChildValidationMetadataProvider(typeof(Stream)));
);
StreamInputFormatter.cs
public class StreamInputFormatter : IInputFormatter
// enter your list here...
private readonly List<string> _allowedMimeTypes = new List<string>
"application/pdf", "image/jpg", "image/jpeg", "image/png", "image/tiff", "image/tif", "application/octet-stream" ;
public bool CanRead(InputFormatterContext context)
if (context == null)
throw new ArgumentNullException(nameof(context));
var contentType = context.HttpContext.Request.ContentType;
if (_allowedMimeTypes.Any(x => x.Contains(contentType)))
return true;
return false;
public Task<InputFormatterResult> ReadAsync(InputFormatterContext context)
if (context == null)
throw new ArgumentNullException(nameof(context));
// enable stream rewind or you won't be able to read the file in the controller
var req = context.HttpContext.Request;
req.EnableRewind();
var memoryStream = new MemoryStream();
context.HttpContext.Request.Body.CopyTo(memoryStream);
req.Body.Seek(0, SeekOrigin.Begin);
return InputFormatterResult.SuccessAsync(memoryStream);
然后是控制器:
public class FileController : BaseController
[HttpPost("customer/customerId/file", Name = "UploadFile")]
[SwaggerResponse(StatusCodes.Status201Created, typeof(UploadFileResponse))]
[Consumes("application/octet-stream", new string[] "application/pdf", "image/jpg", "image/jpeg", "image/png", "image/tiff", "image/tif")]
public async Task<IActionResult> UploadFile([FromBody] Stream file, [FromRoute] string customerId, [FromQuery] FileQueryParameters queryParameters)
// file processing here
【讨论】:
return InputFormatterResult.SuccessAsync(context.HttpContext.Request.Body);
在不复制流的情况下对我有用。以上是关于模型绑定不适用于 asp.net 核心 Web api 控制器操作方法中的 Stream 类型参数。(即使使用自定义流输入格式化程序)的主要内容,如果未能解决你的问题,请参考以下文章
模型绑定不适用于 ASP.NET Core 2 WebAPI 中的 POST 请求
RedirectToAction 不适用于 Tempdata - ASP.net 核心 MVC