web-dev-qa-db-ja.com

POSTによってAzure関数にパラメーターを渡す方法は?

私はそれについて学ぶために単純なAzure関数を実行しようとしています。 3つの機能があります。

  • データベースのテーブルに行を挿入する1つの関数。このテーブルには、現在の日付と、ユーザーによって入力され、GETによって渡された文字列パラメーターが含まれます。
  • 1つは前のものと同様に機能しますが、POSTによってパラメーターを渡します。
  • 表を読み取ってその内容を表示する1つの関数。

私は最初と3番目のものを行うことができました。しかし、POSTでパラメーターを渡すことはできません。例を探しましたが、うまく実行できませんでした。クライアントアプリはWindowsフォームのアプリです。

POSTによってパラメータを関数に渡す方法とそれらを読み取る方法についての例を誰かに教えてもらえますか?

前もって感謝します

編集:

GETでパラメーターを渡すコードは次のとおりです(これは正常に機能しています)。

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

    }
}

そして、これはそれを受け取って挿入を行うためのコードです(これも機能しています)。

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

私が探しているのは、これをPOSTすることです

30
davidrgh

System.Text.Jsonを使用している場合は、POSTデータを1行で読み取ることができます。

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

Newtonsoft.Jsonを使用している場合は、 Allen Zhangによる回答 を参照してください。

0
sveinungf

[FromBody]属性を使用するWebApiアプローチが好きなので、IBindingを使用して独自に作成しました。これで、オブジェクトを渡すことができます。

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

次に、Startup.csファイル内にバインディングを追加します。

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

    }
}

これで、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

Azure Function AppでPOSTリクエストを使用してデータを取得する非常に簡単な例を実行しました。次の例を見つけてください。

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