REQUEST A DEMO

Getting Started with Workday Web Services using C#

Workday Certified Partner

Dovetail is proud to be Workday Certified. To learn more about this partnership and how working with a Workday Certified Partner benefits your HR practice and your organization, click here.

request a demo

 


Connecting to Workday’s web services shouldn’t be a trivial event. At least at first one would feel this way. There are a few areas one needs to know in order to get this working correctly as well as achieving authentication on the Workday side. By now you should have been given your tenant ID from Workday, this will be needed later. To get started we need to create the web service client. Using Visual Studio there are two ways this can be done svcutil or right click the project and select Add Service Reference, I prefer to use svcutil as I felt it created a cleaner codebase than the Service Reference did.

svcutil /t:code https://community.workday.com/custom/developer/API/Human_Resources/v22.0/Human_Resources.wsdl /out:c:\PathToSource\Human_Resources.cs

Some Gotchas to cleanup

  • Open your Human_Resources.cs file, and using Ctrl + Shift + F, select Find and Replace and type in the find [][] and in the replace type []. This will fix a known bug with arrays. The util (and Service Resource) will do this, it turns Array[] into Array[][] and Array[][] into Array[][][].
  • Add a namespace to your Human_Resource.cs file, especially if you’re using Service Locators to inject the class. Don’t be shocked at the file size, its over 100K lines of code and will make Visual Studio unresponsive for a few minutes.

Now that you have a client, you’re now ready to fetch some data. This is where your tenant ID will come into play that I mentioned earlier.

We put together a wrapper class to simplify as much of this as possible and DRY up our code. This may look different in your application or you may go another route. So I’ll mainly focus on the key code points.

Create the basic connection client

public virtual Human_ResourcesPortClient CreateHumanResourcesProxy()
{
    SecurityBindingElement sb = SecurityBindingElement.CreateUserNameOverTransportBindingElement();
    sb.IncludeTimestamp = false;
    const int lim = Int32.MaxValue;
    var timeout = TimeSpan.FromMinutes(2);

    var cb = new CustomBinding(
        sb,
        new TextMessageEncodingBindingElement(MessageVersion.Soap11, Encoding.UTF8)
        {
            ReaderQuotas = new XmlDictionaryReaderQuotas
            {
                MaxDepth = lim,
                MaxStringContentLength = lim,
                MaxArrayLength = lim,
                MaxBytesPerRead = lim,
                MaxNameTableCharCount = lim
            }
        },
        new HttpsTransportBindingElement
        {
            MaxBufferPoolSize = lim,
            MaxReceivedMessageSize = lim,
            MaxBufferSize = lim,
            Realm = string.Empty
        })
    {
        SendTimeout = timeout,
        ReceiveTimeout = timeout
    };

    var proxy = new Human_ResourcesPortClient(cb, new EndpointAddress("https://wd2-impl-services1.workday.com/ccx/service/{tenantID}/Human_Resources"));

    proxy.ClientCredentials.UserName.UserName = "{username@tenantID}";
    proxy.ClientCredentials.UserName.Password = "{password}";
    return proxy;
}

Note: Did you notice the {tenantId} in the Url and the @tenantId after your user name. This is important.

Now assuming you have a similar method in your class, you could pull an employee like so: (This code was modified from our source in order to make sense and bring brevity)

public WorkdayWorkerData GetWorker(string empId)
{
    // WorkdayWorkerData is our wrapper class that makes better sense of the data (as in { FirstName, LastName, etc })
    var request = new Get_Workers_RequestType {version = "v22.0"};

    var workerId = new WorkerObjectIDType()
    {
        type = "Employee_ID",
        Value = empId
    };

    var idTypes = new List<WorkerObjectIDType> {workerId};

    request.Request_References = new Worker_Request_ReferencesType {Worker_Reference = new WorkerObjectType[1] {new WorkerObjectType()}};
    request.Request_References.Worker_Reference[0].ID = idTypes.ToArray();

    request.Request_Criteria = new Worker_Request_CriteriaType
    {
        Exclude_Inactive_Workers = true,
        Exclude_Inactive_WorkersSpecified = true
    };

    var proxy = CreateHumanResourcesProxy();

    Get_Workers_ResponseType response = null;
    try
    {
        response = proxy.Get_Workers(request);
    }
    catch (FaultException fe)
    {
        _logger.LogError("Error occurred invoking GetWorker", fe);
        return null;
    }
    return response.Response_Data.FirstOrDefault() != null ? _mapping.Map<WorkerType, WorkdayWorkerData>(response.Response_Data.FirstOrDefault()) : null;
}

This method would allow you to make a Workday request for a known Employee in the Workday database. Take notice of the Worker_Request_CriteriaType, there are several settings in this class that can be used to filter data. One gotcha with these filters is that you have to set both the IncludeX and IncludeXSpecified, same with Excludes as depicted in this code example.

Conclusion

Working with Workday’s web services will prove to be a steep learning curve on the starting line. Albeit, it gets better once you establish a base structure for data retrieval. Using helper classes and extensions will greatly cleanup your code and improve readability. And as always, make sure you have test coverage. Happy Coding!

request a demo

%d bloggers like this: