Main Content

Asynchronous RESTful Requests Using Protocol Buffers in .NET Client

This example shows how to make asynchronous RESTful requests using the .NET client API, MATLAB® Production Server™ RESTful API, and protocol buffers (protobuf). The example provides and explains a sample C# client, MagicAsync.cs, for evaluating a MATLAB function deployed on the server.

To use protobuf when making a request to the server, set the HTTP Content-Type request header to application/x-google-protobuf in the client code. The MathWorks.MATLAB.ProductionServer.Client.REST namespace in the .NET client library provides helper classes to internally create protobuf messages based on a proto format and returns the corresponding byte array. Use this byte array in the HTTP request body. The .NET client library provides methods and classes to deserialize the protobuf responses.

When sending a POST Asynchronous Request to the server, the client must set the HTTP request mode to async in the query parameter. The request state must be either READY or ERROR before you can retrieve the request result. For more information about asynchronous request execution on MATLAB Production Server, see Asynchronous Execution.

To use the .NET client API, you must add a reference to the MathWorks.MATLAB.ProductionServer.Client.dll file in your C# project. For more information on preparing your Microsoft® Visual Studio® environment for your project, see Prepare Your Microsoft Visual Studio Environment.

In an on-premises MATLAB Production Server installation, the client APIs are located in $MPS_INSTALL/client, where $MPS_INSTALL is the MATLAB Production Server installation location. The client APIs are also available at MATLAB Production Server Client Libraries.

Deploy MATLAB Function to Server

Write a MATLAB function mymagic that uses the magic (MATLAB) function to create a magic square, then deploy it on the server. The function mymagic takes a single int32 input and returns a magic square as a 2-D double array. The example assumes that the server instance is running at http://localhost:9910.

For information on how to deploy, see Create Deployable Archive for MATLAB Production Server.

function m = mymagic(in)

  m = magic(in);
end

Make Asynchronous Request to Server

In the C# client code, use the POST Asynchronous Request to make the initial request to the server. For more information about asynchronous request execution in MATLAB Production Server, see Asynchronous Execution.

  1. Create an HTTP request body containing the protocol buffer message.

    Use the Create(arg1, arg2, arg3) method defined in the MATLABParams class of the MATLAB Production Server .NET client API to build the protocol buffer message. The Create method takes as input the expected number of output arguments for the deployed function, the expected output type, and an array of objects representing the inputs to the deployed function. Since the deployed mymagic function returns a single 2-D array, set arg1 to 1 and arg2 to new List<Type> { typeof(double[,]) }. Specify an integer value for arg3, which is the input to the mymagic function.

    Create a POST Asynchronous Request using the .NET WebRequest.Create method. For more information on the .NET WebRequest class, see Microsoft documentation.

    MATLABParams mlParams = MATLABParams.Create(1, new List<Type> { typeof(double[,]) }, 2);
  2. Send the request to the server.

    Send a POST Asynchronous Request to the server where the request body consists of the protobuf message (mlParams). The request URL comprises the address of the server instance (http://localhost:9910), the name of the deployed archive (mymagic), and the name of the MATLAB function to evaluate (mymagic). Set the HTTP request mode to async in the query parameter. Set the HTTP Content-Type request header to application/x-google-protobuf, as the API returns a byte array of protocol buffer messages.

    Send the request to the server using the .NET WebRequest.getResponse method. For more information on the .NET WebRequest class, see Microsoft documentation.

    String mpsBaseUrl = "http://localhost:9910";
    var response = MakeHTTPRequest(mpsBaseUrl + "/mymagic/mymagic?mode=async", "POST", mlParams);
    Console.WriteLine("The HTTP status code of the request is " + response.StatusCode + ".\n\n");

    The example uses a helper method MakeHTTPRequest to send the protobuf message to the server. This method takes as input an HTTP URL, an HTTP method (GET or POST), and a MATLABParams object, and returns the server response.

    static HttpWebResponse MakeHTTPRequest(String url, String requestType, MATLABParams mlParams)
    {
        var httpRequest = (HttpWebRequest)WebRequest.Create(url);
        httpRequest.Method = requestType;
        httpRequest.ContentType = "application/x-google-protobuf";
        if (requestType.Equals("POST"))
        {
            mlParams.WriteTo(httpRequest.GetRequestStream());
        }
        return (HttpWebResponse)httpRequest.GetResponse();
    }
  3. Receive and interpret the server response.

    On successful execution of the HTTP requests, the server responds with a protocol buffer message. Parse the protocol buffer message using methods from the MATLABRequestHandle class to get details such as the state of the request, the request URL, and the last modified sequence value of the request.

    MATLABRequestHandle matlabRequestHandle = MATLABRequestHandle.Create(response.GetResponseStream());
    Console.WriteLine("The response body of the initial POST request contains the following values after deserialization using MATLABRequestHandle class: ");
    Console.WriteLine(matlabRequestHandle.ToString() + ".\n\n");

Get State Information of Request

  1. Make a request to get the request state information.

    Make a request to the GET State Information RESTful API. In the request URL, set the query parameter format to protobuf so that the server returns the output in protocol buffer format. You can get the result of an asynchronous request only after the state of the request has changed to READY or ERROR.

  2. Parse the response.

    Parse the response using methods defined in the MATLABRequest class to get the state of the request.

The example code makes a request to the GET State Information API every second to look for a request state change to either READY_STATE or ERROR_STATE.

 MATLABRequest mlRequestStatus;
 do
 {
    var statusRequestResponse = MakeHTTPRequest(mpsBaseUrl + matlabRequestHandle.RequestURL + "/info?format=protobuf", "GET", null);
    mlRequestStatus = MATLABRequest.Create(statusRequestResponse.GetResponseStream());
    Console.WriteLine("State: " + mlRequestStatus.State);
    Thread.Sleep(1000);
}while (mlRequestStatus.State < MATLABRequestState.READY_STATE);

In asynchronous mode, a client is able to post multiple requests to the server. To get the state information of each POST request, you must make a corresponding request to the GET State Information RESTful API.

Retrieve Results of Request

  1. Make a request to fetch the response.

    Use the GET Result of Request RESTful API to fetch the request results after the request state has changed to READY or ERROR. In the request URL, set the query parameter format to protobuf, so that the server returns the output in protocol buffer format.

    response = MakeHTTPRequest(mpsBaseUrl + matlabRequestHandle.RequestURL + "/result?format=protobuf", "GET", null);

  2. Parse the response.

    If the request state is READY, use the methods defined in the MATLABResult class to parse the response. To create a MATLABResult object, use the Create method, and pass as inputs the MATLABParams mlParams object and the response body of the request to GET Result of Request API.

    If an error occurs when the deployed MATLAB function executes, the call to the Result method throws a MATLABException that contains the error message from MATLAB.

    If the request state is ERROR, use the HTTPErrorInfo class instead of the MATLABResult class to parse the response. Use the methods defined in the HTTPErrorInfo class to get information about the error.

    if (mlRequestStatus.State == MATLABRequestState.READY_STATE)
    {
        MATLABResult mlResult;
        try
        {
             mlResult = MATLABResult.Create(mlParams, response.GetResponseStream());
             double[,] result = mlResult.Result<double[,]>();
             Console.WriteLine("Printing the 2-D array...\n");
             PrintMagic(result);
        }
        catch (MATLABException e)
        {
            Console.WriteLine(e.Message);
        }
    }
    else if (mlRequestStatus.State == MATLABRequestState.ERROR_STATE)
    {    
        HTTPErrorInfo httpErrorInfo = HTTPErrorInfo.Create(response.GetResponseStream());
        Console.WriteLine("Error:");
        Console.WriteLine(httpErrorInfo.HttpErrorCode);
        Console.WriteLine(httpErrorInfo.HttpErrorMessage);
    }
  3. Display the results.

    The example uses a helper method PrintMagic that takes as input the result that is parsed from the response body of the GET Result of Request API call and prints the corresponding 2-D magic square array.

    static void PrintMagic(double[,] magic)
    {
        int numDims = magic.Rank;
        int[] dims = new int[numDims];
    
        for (int i = 0; i < numDims; i++)
        {
            dims[i] = magic.GetLength(i);
        }
        
        for (int j = 0; j < dims[0]; j++)
        {    
            for (int k = 0; k < dims[1]; k++)
            {
                Console.Write(magic[j, k]);
                if (k < dims[1] - 1)
                {
                    Console.Write(",");
                }
            }
            Console.WriteLine();
        }
    }

Running the C# application generates the following output.

Printing the 2-D array...

1,3
4,2

Sample code for the MagicAsync.cs C# client follows.

Code:

 MagicAsync.cs

See Also

| |

Related Topics