我目前从正文中读取输入流:
public async Task<IActionResult> Post()
{
byte[] array = new byte[Request.ContentLength.Value];
using (MemoryStream memoryStream = new MemoryStream(array))
{
await Request.Body.CopyToAsync(memoryStream);
}
return Ok();
}
由于测试和swagger的生成,我想在方法签名中指定输入参数。
是否可以以某种方式将输入参数指定为流?
public async Task<IActionResult> Post([FromBody]Stream body) ...
答案 0 :(得分:2)
您必须创建自定义属性和自定义参数绑定。
以下是FromContent
属性和ContentParameterBinding
绑定的实现:
public class ContentParameterBinding : FormatterParameterBinding
{
private struct AsyncVoid{}
public ContentParameterBinding(HttpParameterDescriptor descriptor) : base(descriptor, descriptor.Configuration.Formatters,
descriptor.Configuration.Services.GetBodyModelValidator())
{
}
public override Task ExecuteBindingAsync(ModelMetadataProvider metadataProvider,
HttpActionContext actionContext,
CancellationToken cancellationToken)
{
}
public override Task ExecuteBindingAsync(ModelMetadataProvider metadataProvider,
HttpActionContext actionContext,
CancellationToken cancellationToken)
{
var binding = actionContext.ActionDescriptor.ActionBinding;
if (binding.ParameterBindings.Length > 1 ||
actionContext.Request.Method == HttpMethod.Get)
{
var taskSource = new TaskCompletionSource<AsyncVoid>();
taskSource.SetResult(default(AsyncVoid));
return taskSource.Task as Task;
}
var type = binding.ParameterBindings[0].Descriptor.ParameterType;
if (type == typeof(HttpContent))
{
SetValue(actionContext, actionContext.Request.Content);
var tcs = new TaskCompletionSource<object>();
tcs.SetResult(actionContext.Request.Content);
return tcs.Task;
}
if (type == typeof(Stream))
{
return actionContext.Request.Content
.ReadAsStreamAsync()
.ContinueWith((task) =>
{
SetValue(actionContext, task.Result);
});
}
throw new InvalidOperationException("Only HttpContent and Stream are supported for [FromContent] parameters");
}
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)]
public sealed class FromContentAttribute : ParameterBindingAttribute
{
public override HttpParameterBinding GetBinding(HttpParameterDescriptor parameter)
{
if (parameter == null)
throw new ArgumentException("Invalid parameter");
return new ContentParameterBinding(parameter);
}
}
现在你可以
public async Task<string> Post([FromContent]Stream contentStream)
{
using (StreamReader reader = new StreamReader(contentStream, Encoding.UTF8))
{
var str = reader.ReadToEnd();
Console.WriteLine(str);
}
return "OK";
}
但它对swagger
没有帮助:(
答案 1 :(得分:0)
您必须为流创建模型绑定程序:
public class StreamBinder : IModelBinder
{
public Task BindModelAsync(ModelBindingContext bindingContext)
{
bindingContext.Result = ModelBindingResult.Success(bindingContext.HttpContext.Request.Body);
return Task.CompletedTask;
}
}
然后,您应该为其创建模型联编程序提供程序:
public class StreamBinderProvider : IModelBinderProvider
{
public IModelBinder GetBinder(ModelBinderProviderContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
if (context.Metadata.ModelType == typeof(Stream))
{
return new BinderTypeModelBinder(typeof(StreamBinder));
}
return null;
}
}
并注册:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers(options =>
{
options.ModelBinderProviders.Insert(0, new StreamBinderProvider());
});
}
用法:
public async Task<IActionResult> Post([FromBody]Stream body) ...
答案 2 :(得分:-1)
AS Web Api不要在模型绑定中绑定流,这不会起作用。相反,如果您需要参数流,则可以使用自定义模型绑定
http://10.250.216.195/insert.php
控制器
public class MyModelBinder : IModelBinder
{
public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
{
// Extract the posted data from the request
// Convert the base64string to Stream
// Extract the model from the bindingcontext
// Assign the model's property with their values accordingly
}
}