2017-03-29 52 views
4

我目前從身體讀取輸入流是這樣的:用身體流參數

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(); 
} 

我想指定的方法簽名的輸入參數,由於測試和招搖的產生。

是否有可能以某種方式將輸入參數指定爲流?

public async Task<IActionResult> Post([FromBody]Stream body) ... 
+0

幫你試試我的回答?https://stackoverflow.com/questions/43086909/use-body-stream-parameter-in-webapi-controllers-action/44334250#44334250 –

回答

1

您必須創建自定義屬性和自定義參數綁定。

這是我實現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 :(

0

因爲Web API不綁定流在模型綁定這不會工作。相反,如果你需要的參數流,你可以使用自定義模型綁定

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 
    } 
} 

控制器

public ApiActionResult SaveDocument([ModelBinder(typeof(MyModelBinder))]DocumentVM contentDTO)