cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
885
Views
0
Helpful
2
Replies

Async Support for REST .NET SDK

stephan.steiner
Spotlight
Spotlight

Hi

I've been building the framework for making adding async support for the .NET SDK. Given that we're talking remote IO operations, async should be the preferable way of doing things.

Any interest in adding this to the mainline lib? If so I'd sit down another day or two to actually test what I came up with. It's just the groundwork and an implementation for a handful of objects.. full async support would obviously require async methods for every object, but they should be easy enough to add.

2 Replies 2

lindborg
Cisco Employee
Cisco Employee

yeah, I've thought of this but it is a reasonable amount of work - unfortunately I'm flying mostly solo on all the tools including the SDK these days (everything is about cloud any more) - so carving off enough cycles to hit this top to bottom might be a challenge, but I'd be more than happy to look at what you had in mind.

Alright.. give me a couple of days to get a few more samples ready.

Basically I wrote duplicates for the whole code that perform a cupi operations in async, but that's the easy part. Then since there's no out variables with async, I created a generic WebCallResult that can hold the result for an operation. So for instance, vm server extraction looks like this

        public static async Task<WebCallResult<List<VmsServer>>> GetVmServersAsync(ConnectionServerRest pConnectionServer)

        {

            WebCallResult<List<VmsServer>> result = new WebCallResult<List<VmsServer>>();

            result.Success = false;

            List<VmsServer> pServers = null;

            if (pConnectionServer == null)

            {

                result.ErrorText = "Null Connection server object passed to GetVmsServers";

                return result;

            }

            string strUrl = ConnectionServerRest.AddClausesToUri(pConnectionServer.BaseUrl + "vmsservers");

            //issue the command to the CUPI interface

            WebCallResult res = await pConnectionServer.GetCupiResponseAsync(strUrl, MethodType.GET, "").ConfigureAwait(false);

            if (res.Success == false)

            {

                return res.ToGenericResult<List<VmsServer>>();

            }

            result = res.ToGenericResult<List<VmsServer>>();

            //if the call was successful the JSON dictionary should always be populated with something, but just in case do a check here.

            //if this is empty that's an error - a zero count is also not valid since there must always be one.

            if (string.IsNullOrEmpty(result.ResponseText) || result.TotalObjectCount == 0)

            {

                pServers = new List<VmsServer>();

                result.Success = false;

                return result;

            }

            pServers = pConnectionServer.GetObjectsFromJson<VmsServer>(result.ResponseText);

            if (pServers == null)

            {

                pServers = new List<VmsServer>();

                result.ErrorText = "Could not parse JSON into VmsServers:" + result.ResponseText;

                result.Success = false;

                return result;

            }

            result.ResultObject = pServers;

            //the ConnectionServer property is not filled in in the default class constructor used by the Json parser -

            //run through here and assign it for all instances.

            foreach (var oObject in pServers)

            {

                oObject.HomeServer = pConnectionServer;

            }

            return result;

        }

And then I had to separate constructor from the first login because the standard constructor I've been using would automatically log in and extract the server version. But given there's constructors that take an IConnectionRestCalls, there's probably a more sensible way to go about this. Either way, I'm flexible this way if it means we could integrate this into the main line.

From that point on, it's all just duplicating the extraction methods to run the async code. Not very elegant, but it gets the job done.

The only other thing I could think of would be doing the object parsing a bit more generic. I have my own AXL lib that I started way before there was async.. and it was rather easy to turn this into sync because my object extraction is generic. So basically I can call axlServer.Get<ObjectType>(IGetOperation op), and ObjectType implements IGetOperation and defines the url for the request and how to parse the result back to an ObjectType It increases your amount of plumbing code (every ObjectType needs to implement interfaces with methods for Get/Add/Update/Delete) slightly, on the other hand, sync or async then basically doesn't matter and there's just a few duplicate methods.