« Voltar
em Web API web c#

Passando uma string simples para a WEB API.

Estou escrevendo esse post somente para documentar algo que precisei fazer hoje e parecia simples e no final não era tão trivial como eu imaginava.
Teve uma vez que precisei hostear uma Web API fora do IIS também e documentei aqui.

Mas vamos lá!

Por uma razão X, preciso que um método em minha Web API receba uma simples string, desse jeito:

[HttpPost]
public HttpResponseMessage Metodo([FromBody] string texto)  
{
    //faz alguma coisa
}

Deveria ser tranquilo né? Mas não é :/
Tentei de várias formas, mas o valor sempre vinha nulo!

Pesquisei então e encontrei esse post.
Eu não vou explicar todos os detalhes técnicos porque estou na correria hoje :/
Talvez num próximo post.

Enfim, primeiro vamos criar a classe NakedBodyParameterBinding:

public class NakedBodyParameterBinding : HttpParameterBinding  
{
    public NakedBodyParameterBinding(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)
            return EmptyTask.Start();

        var type = binding
                    .ParameterBindings[0]
                    .Descriptor.ParameterType;

        if (type == typeof(string))
        {
            return actionContext.Request.Content
                    .ReadAsStringAsync()
                    .ContinueWith((task) =>
                    {
                        var stringResult = task.Result;
                        SetValue(actionContext, stringResult);
                    });
        }
        else if (type == typeof(byte[]))
        {
            return actionContext.Request.Content
                .ReadAsByteArrayAsync()
                .ContinueWith((task) =>
                {
                    byte[] result = task.Result;
                    SetValue(actionContext, result);
                });
        }

        throw new InvalidOperationException("Only string and byte[] are supported for [NakedBody] parameters");
    }

    public override bool WillReadBody
    {
        get
        {
            return true;
        }
    }
}

Depois, a classe EmptyTask:

public class EmptyTask  
{
    public static Task Start()
    {
        var taskSource = new TaskCompletionSource<AsyncVoid>();
        taskSource.SetResult(default(AsyncVoid));
        return taskSource.Task as Task;
    }

    private struct AsyncVoid
    {
    }
}

E por último, a classe NakedBodyAttribute:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)]
public sealed class NakedBodyAttribute : ParameterBindingAttribute  
{
    public override HttpParameterBinding GetBinding(HttpParameterDescriptor parameter)
    {
        if (parameter == null)
            throw new ArgumentException("Invalid parameter");

        return new NakedBodyParameterBinding(parameter);
    }
}

Aí, no método em que você quiser receber um valor "limpo", é só marcar o parâmetro com o atributo que criamos:

[HttpPost]
public HttpResponseMessage Metodo([NakedBody] string texto)  
{
    //faz alguma coisa
}

Desse jeito, dá pra fazer a requisição assim:

POST http://meusite.com/api/Metodo HTTP/1.1  
Content-Type: text/plain; charset=utf-8  
Host: meusite.com

Texto puro  

Pronto!

A Web API facilita muita coisa, mas essa situação poderia ser mais fácil né?
Você já fez de alguma forma diferente? Mais fácil, talvez? Compartilha aí (:

Mais uma vez, eu peguei esse código desse post e todos os detalhes do que fizemos aqui estão publicados lá.

Você pode baixar as classes sem ter que ficar copiando e colando direto do meu Github.
Só clicar no "Download ZIP" do lado direito inferior.


Já que você leu até aqui, porque não curte minha página lá no Face pra ficar em dia com as minhas postagens e outras coisas legais?
O endereço é https://www.facebook.com/devgabsferreira (:

comments powered by Disqus