Best practices for using RestSharp insode Azure Function Apps

horseatingweeds 1 Reputation point
2022-02-05T22:31:49.293+00:00

Am I using RestSharp correctly in the Function App? It works pretty well, but I'm trying to understand if/how I should reuse the RestClient. I'm also using Azure Service Bus, and I'm setting a static ServiceBusClient and ServiceBusSender.

Reusing RestClient looks tricky because I need to get an authentication token. I suppose I could use a static RestClient for making the token request (which includes a varying host name for the primary request). But how should I make the RestClient static when it needs to use a varying token and host?

This is what I have right now. I'm still on the learning curve with Azure and Function Apps, so any advice on improving this app would be appreciated.

public class Function1
{
    private readonly ILogger<Function1> _logger;

    // Static reusables 
    private static ServiceBusClient client = new ServiceBusClient(System.Environment.GetEnvironmentVariable("AzureWebJobsServiceBus"));
    private static ServiceBusSender sender = client.CreateSender("emailutilititylogger");

    public Function1(ILogger<Function1> log)
    {
        _logger = log;
    }

    [FunctionName("EmailReceipt")]
    [OpenApiOperation(operationId: "Run", tags: new[] { "name" })]
    [OpenApiSecurity("function_key", SecuritySchemeType.ApiKey, Name = "code", In = OpenApiSecurityLocationType.Query)]
    [OpenApiRequestBody("application/json", typeof(ResponsysRequest), Description = "JSON request body")]
    [OpenApiResponseWithBody(statusCode: HttpStatusCode.OK, contentType: "application/json", bodyType: typeof(Auth), Description = "The OK response")]
    public async Task<IActionResult> Run(
        [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req)
    {
        _logger.LogInformation("C# HTTP trigger function processed a request.");
        string requestBody = await new StreamReader(req.Body).ReadToEndAsync();

        //Log
        var logMessage = new LogMessage();
        logMessage.payload = requestBody;
        logMessage.timestamp = System.DateTime.Now;
        string logMessageString = JsonConvert.SerializeObject(logMessage);
        ServiceBusMessage busmsg = new ServiceBusMessage(logMessageString);
        await sender.SendMessageAsync(busmsg);

        Task<Auth> getAccessToken = GenerateAccessObject();
        Auth auth = await getAccessToken;

        EmailRequest emailRequest = JsonConvert.DeserializeObject<EmailRequest>(requestBody);
        ResponsysRequest responsysRequest = emailRequest.ToResponsys();

        var resp = await sendEmail(responsysRequest, auth, emailRequest.EmailData.Campaign);

        if (resp.IsSuccessful)
        {
            var responsysSuccess = JsonConvert.DeserializeObject<List<Response>>(resp.Content);
            return new OkObjectResult(responsysSuccess);
        }
        else
        {
            var responsysError = JsonConvert.DeserializeObject<ResponsysErrorResponse>(resp.Content);
            return new BadRequestObjectResult(responsysError);
        }       
    }

    private async Task<Auth> GenerateAccessObject()
    {
        using var client = new RestClient("https://this.com/rest/api/");
        var request = new RestRequest("auth/token");
        var response = await client.PostAsync<Auth>(request);

        return response;

    }

    private async Task<RestResponse> sendEmail(ResponsysRequest requestBody, Auth auth, string campaign)
    {
        using var client = new RestClient(auth.endPoint);
        var request = new RestRequest("/rest/campaigns/" + campaign + "/email", Method.Post);
        request.AddHeader("Authorization", auth.authToken);
        request.RequestFormat = DataFormat.Json;
        request.AddJsonBody(requestBody);
        var restResponse = await client.ExecutePostAsync(request);

        return restResponse;
    }
Azure Functions
Azure Functions
An Azure service that provides an event-driven serverless compute platform.
4,358 questions
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. MughundhanRaveendran-MSFT 12,436 Reputation points
    2022-02-09T15:23:33.29+00:00

    @horseatingweeds ,

    Thanks for reaching out to Q&A.

    I see that you are creating static clients and reusing the clients. This is a good practice in Azure functions. To avoid holding more connections than necessary, reuse client instances rather than creating new ones with each function invocation. We recommend reusing client connections for any language that you might write your function in.

    Manage connections in Azure functions : https://learn.microsoft.com/en-us/azure/azure-functions/manage-connections?tabs=csharp

    Best practices in Functions : https://learn.microsoft.com/en-us/azure/azure-functions/functions-best-practices?tabs=csharp

    I hope this helps!

    Please 'Accept as answer' and ‘Upvote’ if it helped so that it can help others in the community looking for help on similar topics.