在WebApi控制器的操作中使用body stream参数

Lie*_*ero 7 c# asp.net asp.net-web-api asp.net-core

我目前从身体读取输入流,如下所示:

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();
}
Run Code Online (Sandbox Code Playgroud)

由于测试和swagger生成,我想在方法签名中指定输入参数.

是否可以以某种方式将输入参数指定为流?

public async Task<IActionResult> Post([FromBody]Stream body) ...
Run Code Online (Sandbox Code Playgroud)

v-a*_*rew 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

现在你可以

    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";
    }
Run Code Online (Sandbox Code Playgroud)

然而它没有帮助swagger:(