Thursday, 9 March 2017

Azure Function: Call a web service and return the result as a class

My current project is using Azure Functions as action triggers. Thanks to some nifty work from the Visual Studio team, we now have a local development environment.

The following POC function will call a Web API (configured through API Management) and convert the resultant JSON into a class object.

1. Create a 'Model' solution that stores the class to be used. I called my MyModel. My class is called ApiResult.

namespace MyModel
{
    public class ApiResult
    {
        public string Message { get; set; }
    }
}

2. Create an API to invoke

using MyModel;
using System.Web.Http;

namespace MyControllers
{
    public class MyController : ApiController
    {
        [System.Web.Http.HttpGet]
        [System.Web.Http.Route("api/myapiendpoint")]
        public ApiResult ValidateFile()
        {
            return new ApiResult()
            {
                Message = "Success!"
            };
        }
    }
}

3. Copy the MyModel.dll to a folder in my Azure Function folder (I called in References)

4. Here is the code to call the endpoint and return the result object

// add the dll references
#r "..\References\MyModel.dll"
#r "..\References\System.Runtime.Serialization.dll"

// add the namespaces
using System.Net;
using System.IO;
using System.Text;
using System.Runtime.Serialization.Json;
using MyModel;

// I used an HttpTrigger action for simplicity
public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log)
{
    // create a few constants to make things easier
    const string WEBSERVICE_URL = @"http://myapimanagement.azure-api.net/api/myapiendpoint";
    const string SUBSCRIPTION_KEY = @"123456";
 
    try
    {
        // Call a method to do the work
        ExecuteWebRequest(WEBSERVICE_URL, SUBSCRIPTION_KEY);
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.ToString());
    }

    return req.CreateResponse(HttpStatusCode.OK);
}

private static void ExecuteWebRequest(string url, string key)
{
    WebRequest webRequest = WebRequest.Create(url);
    if (webRequest != null)
    {
        webRequest.Method = "GET";
        webRequest.Timeout = 20000;
        webRequest.ContentType = "application/json";
        webRequest.ContentLength = 0;

        // Add the subscription key to the header so the call will authenticate
        webRequest.Headers.Add("Ocp-Apim-Subscription-Key", key);
        using (System.IO.Stream s = webRequest.GetResponse().GetResponseStream())
        {
            using (System.IO.StreamReader sr = new System.IO.StreamReader(s))
            {
                // convert the Json to the base object
                var jsonResponse = ReadApiResultToObject(sr.ReadToEnd());
            }
        }
    }
}

private static ApiResult ReadApiResultToObject(string json)
{
    ApiResult deserializedUser = new ApiResult();
    using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(json)))
    {
        DataContractJsonSerializer ser = new DataContractJsonSerializer(deserializedUser.GetType());
        deserializedUser = ser.ReadObject(ms) as ApiResult;
    }
    return deserializedUser;
}

My biggest learning from this exercise is that the compilation is late bound, so any errors will be at runtime. So, make small changes and test often.

No comments:

Post a comment