2017-06-02 1 views
1

Je souhaite avoir un attribut personnalisé pour analyser les données en tant que flux et être testable avec Swagger.Swagger ne reconnaît pas le paramètre du contrôleur WebAPI avec l'attribut personnalisé [FromContent]

Je créé contrôleur qui lit du corps POST:

[SwaggerOperation("Create")] 
[SwaggerResponse(HttpStatusCode.Created)] 
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"; 
} 

Comment définir flux de sorte qu'il est visible dans l'interface utilisateur Swagger?

Voici mon implémentation de FromContent attribut et ContentParameterBinding de liaison:

public class ContentParameterBinding : HttpParameterBinding 
{ 
    private struct AsyncVoid{} 
    public ContentParameterBinding(HttpParameterDescriptor descriptor) : base(descriptor) 
    { 

    } 

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

Mise à jour

Lorsque je crée Stream à l'aide [FromBody] est montre correctement Swagger, mais Stream n'est pas initié et ==null

[SwaggerOperation("Create")] 
[SwaggerResponse(HttpStatusCode.Created)] 
public async Task<string> Post([FromBody]Stream contentStream) 
{ 
    using (StreamReader reader = new StreamReader(contentStream, Encoding.UTF8)) 
    { 
     var str = reader.ReadToEnd(); 
     Console.WriteLine(str); 
    } 
    return "OK"; 
} 

Good Post

Je veux avoir la même interface utilisateur, mais avec mon attribut personnalisé qui me laisse ai Stream du contenu.

Avec mon attribut personnalisé, il montre sans TextArea pour le paramètre, mais pourrait être testé à l'aide Postman et fonctionner correctement et Stream est disponible Bad Post

+0

Comment avez-vous vouloir le montrer? Où est le problème? vous devez préciser quelle sortie vous attendez – Marusyk

+0

@MegaTron J'essaie d'ajouter Test pour poste, où le flux a été créé à partir du corps du contenu, je vais ajouter des exemples et des images –

+0

Ce paramètre de liaison entière semble beaucoup de travail pour éviter de faire 'var stream = attendre this.Request.Content.ReadAsStreamAsync()' dans la méthode du contrôleur. –

Répondre

1

Hérite votre fixation de FormatterParameterBinding classe:

public class ContentParameterBinding : FormatterParameterBinding 
{ 
    public ContentParameterBinding(HttpParameterDescriptor descriptor) 
      : base(descriptor, 
        descriptor.Configuration.Formatters, 
        descriptor.Configuration.Services.GetBodyModelValidator()) 
    { 
    } 

    //your code 
} 
+0

Merci pour votre aide! –