web-dev-qa-db-fra.com

Comment passer des paramètres par POST à une fonction Azure?

J'essaie de faire une simple fonction Azure pour en savoir plus. Il y aura 3 fonctions:

  • 1 fonction pour insérer une ligne dans une table d'une base de données. Ce tableau contiendra la date actuelle et une chaîne de paramètres saisis par l'utilisateur et transmis par GET.
  • 1 fonction similaire à la précédente, mais passant le paramètre par POST.
  • 1 fonction pour lire le tableau et afficher son contenu.

J'ai pu faire le premier et le troisième. Mais je ne peux pas passer le paramètre par POST. J'ai cherché des exemples mais je n'ai pas pu les exécuter avec succès. L'application client est une application Windows Forms.

Quelqu'un pourrait-il me montrer un exemple et comment passer des paramètres par POST à la fonction et comment les lire?

Merci d'avance

ÉDITER:

Voici le code pour passer les paramètres par GET (cela fonctionne bien):

private void button2_Click(object sender, EventArgs e)
{
    string cadena = lsql1.Text + "?notas=" + tNotas.Text;

    try
    {
        HttpWebRequest req = (HttpWebRequest)WebRequest.Create(cadena);
        HttpWebResponse res = (HttpWebResponse)req.GetResponse();

        if (res.StatusCode == HttpStatusCode.OK)
        {
            MessageBox.Show("Grabado");
        }
        else
        {
            MessageBox.Show(res.StatusDescription);
        }
    }catch (WebException ex)
    {
        using (Stream s = ex.Response.GetResponseStream())
        {
            StreamReader sr = new StreamReader(s);
            string text = sr.ReadToEnd();
            text = text.Substring(1, text.Length - 2);
            sr.Close();
            text = text.Replace("\\", "");
            text = "{" + text + "}";
            Error mensajeError = JsonConvert.DeserializeObject<Error>(text);

            MessageBox.Show(mensajeError.ExceptionMessage);
        }

    }
}

Et voici le code pour le recevoir et faire l'insertion (cela fonctionne aussi):

[FunctionName("sql1")]
public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log)
{
    try
    {
        log.Info("C# HTTP trigger function processed a request.");

        var cnnString = "Server=SERVIDOR;Database=base_prueba;User ID =Azure;Password=0000;Trusted_Connection=False;Encrypt=False;";

        using (SqlConnection connection = new SqlConnection(cnnString))
        {
            connection.Open();
            SqlCommand cmd = connection.CreateCommand();

            DateTime fecha = DateTime.Today;

            string notas = req.GetQueryNameValuePairs()
            .FirstOrDefault(q => string.Compare(q.Key, "notas", true) == 0)
            .Value;

            // insert a log to the database
            cmd.CommandText = "INSERT INTO Prueba_Azure (fecha, notas) VALUES ('" + fecha.ToString() + "', '" + notas + "')";
            cmd.ExecuteNonQuery();
        }

        // Get request body
        dynamic data = await req.Content.ReadAsAsync<object>();

        return name == req.CreateResponse(HttpStatusCode.OK, "Done");
    }
    catch (Exception ex)
    {
        HttpResponseMessage res = req.CreateErrorResponse(HttpStatusCode.InternalServerError, ex);
        return res;
    }
}

Ce que je cherche c'est de le faire par POST

30
davidrgh

Si vous utilisez System.Text.Json, vous pouvez lire les données POST sur une seule ligne:

public static async Task Run(
    [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)]
    HttpRequest req,
    ILogger log)
{
    MyClass myClass = await JsonSerializer.DeserializeAsync<MyClass>(req.Body);
}

Si vous utilisez Newtonsoft.Json, voir la réponse d'Allen Zhang .

0
sveinungf

J'aime l'approche WebApi consistant à utiliser [FromBody] attribut, donc en utilisant IBinding j'ai créé le mien. Maintenant, je peux simplement passer l'objet.

[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.ReturnValue)]
[Binding]
public sealed class FromBodyAttribute : Attribute
{
}

public class FromBodyBinding : IBinding
{
    private readonly ILogger logger;
    public FromBodyBinding(ILogger logger)
    {
        this.logger = logger;
    }
    public Task<IValueProvider> BindAsync(BindingContext context)
    {
        // Get the HTTP request
        var request = context.BindingData["req"] as DefaultHttpRequest;

        return Task.FromResult<IValueProvider>(new FromBodyValueProvider(request, logger));
    }

    public bool FromAttribute => true;


    public Task<IValueProvider> BindAsync(object value, ValueBindingContext context)
    {
        return null;
    }

    public ParameterDescriptor ToParameterDescriptor() => new ParameterDescriptor();
}

public class FromBodyBindingProvider : IBindingProvider
{
    private readonly ILogger logger;
    public FromBodyBindingProvider(ILogger logger)
    {
        this.logger = logger;
    }

    public Task<IBinding> TryCreateAsync(BindingProviderContext context)
    {
        IBinding binding = new FromBodyBinding(this.logger);
        return Task.FromResult(binding);
    }
}

public class FromBodyValueProvider : IValueProvider
{
    private HttpRequest request;
    private ILogger logger;

    public FromBodyValueProvider(HttpRequest request, ILogger logger)
    {
        this.request = request;
        this.logger = logger;
    }

    public async Task<object> GetValueAsync()
    {
        try
        {
            string requestBody = await new StreamReader(this.request.Body).ReadToEndAsync();
            object result = JsonConvert.DeserializeObject(requestBody);
            return result;
        }
        catch (System.Exception ex)
        {
            this.logger.LogCritical(ex, "Error deserializing object from body");

            throw ex;
        }
    }

    public Type Type => typeof(object);

    public string ToInvokeString() => string.Empty;
}

public class BindingExtensionProvider : IExtensionConfigProvider
{
    private readonly ILogger logger;
    public BindingExtensionProvider(ILogger<Startup> logger)
    {
        this.logger = logger;
    }

    public void Initialize(ExtensionConfigContext context)
    {
        // Creates a rule that links the attribute to the binding
        context.AddBindingRule<FromBodyAttribute>().Bind(new FromBodyBindingProvider(this.logger));
    }
}

Ensuite, dans votre fichier Startup.cs, ajoutez la liaison.

public class Startup : IWebJobsStartup
{
    public void Configure(IWebJobsBuilder builder)
    {
        JsonConvert.DefaultSettings = () =>
        {
            return new JsonSerializerSettings()
            {
                ContractResolver = new DefaultContractResolver
                {
                    NamingStrategy = new CamelCaseNamingStrategy()
                },
                Formatting = Formatting.Indented
            };
        };

        builder.Services.AddLogging();
        builder.AddExtension<BindingExtensionProvider>();

    }
}

Maintenant, vous pouvez simplement avoir une ancienne classe régulière, tout comme WebApi!

[FunctionName("MyFunction")]
public async Task<IActionResult> Run(
    [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = null)] HttpRequest req,
    [Binding.FromBody] dynamic data) // or you can change 'dynamic' to some class
{
    string username = data?.username;
    ...
}
0
Matt

J'ai fait un exemple très simple pour obtenir des données en utilisant POST dans Azure Function App. Veuillez trouver l'exemple suivant.

using System;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Azure.WebJobs.Host;

namespace MyFunctions
{
    public static class MyFunctionsOperations
    {
        [FunctionName("MyFunctionsOperations")]
        public static async Task<HttpResponseMessage> Run([HttpTrigger(AuthorizationLevel.Function, "post", Route = null)]HttpRequestMessage req, TraceWriter log)
        {
            log.Info("C# HTTP trigger function processed a request.");
            var headers = req.Headers;
            string collection = headers.GetValues("collection").First();   //getting parameter from header

            CosmosdbOperation obj = new CosmosdbOperation();
            dynamic data = await req.Content.ReadAsAsync<object>();  //getting body content
            Boolean response = await obj.MyFunctionExecution(data.ToString(), collection);

            return (response)
                ? req.CreateResponse(HttpStatusCode.BadRequest, "Please pass a proper argument in the request body")
                : req.CreateResponse(HttpStatusCode.OK, "Operation successfully executed..");
        }
    }
}
0
Sapnandu