Sunday, June 26, 2016

Custom approval workflow causes 'Access Denied' error

Recently I was setting up a MIM environment that does the most basic approval workflows.  Have a user create a contractor in the MIM Portal that requires manager approval.  After setting everything up I was getting Access Denied error with the following error - 'Object reference not set to an instance of the object'..  This worked in past FIM deployments so I wasn't sure what the deal was.

Thanks to Dan Malloy for pointing out this blog which fixed the problem.

FYI if you change an OOB approval workflow, now it becomes custom and it will also change the .NET reference from 3.5 to 4.0 which may cause issues.  Switching it back to 3.5 should resolve the issue.

Saturday, March 19, 2016

Outlook 2016 and MIM2016 client extension resolved

My last post I was frustrated I could install the client extensions for MIM2016 on Outlook 2016.  Now there's a fix:
Thanks to Brian Desmond for pointing this out.

Friday, March 18, 2016

Outlook 2016 and MIM 2016 client extensions.

Was recently at a client site working on group management.  I discovered that the Outlook plug-in for MIM client extension is not supported on Outlook 2016. 

This is not noted anywhere on the MS web site, so now you know.  This is a bit disappointing, I'm hoping MS will do something about this soon.  I'm going to report it on the MS FIM forum shortly.

Update: There's a hotfix see next post.

Wednesday, December 23, 2015

Security for all is good

It's been discovered that Juniper Networks has been using a flawed encryption for years.  Possibly a result of NSA and/or a bug.  When it becomes easy for good guys to decrypt information for the sake of national security, it makes it just as easy for bad guys to decrypt.  Engineering secure systems without backdoors works for everybody.

Juniper backdoor

Monday, December 14, 2015

MIM 2016 and Exchange 2010: no-start-ma during AD export

I've recently been playing around with MIM 2016 and stood up an Exchange 2010 server within the environment.  Trying to provision to AD with Exchange functionality has proven difficult.  I would get no-start-ma in the MIM Sync console after the AD export.

When I removed the removed the exchange provisioning functionality in the MA extensions section, the export worked as expected. I was able to prove that I could connect to remote powershell so that didn't seem to be the issue yet I continue having the problem.  After googling around I ran across Thomas' blog in setspn.blogspot and found the same thing.

On the MIM sync server, install .Net 4.6.  Install all windows updates (including optional).  Reboot - I had to reboot twice as the FIM service wouldn't start the first time.  All seems to be working now.  Thanks for the info Thomas.

Monday, March 9, 2015

Updating Workday using .NET

The second post here will give you a good start how to update a user who's in Workday.  The community had zero examples how to do this, so you should find this helpful.

Read the earlier post regarding pre-reqs needed to connect to Workday using .NET.  This time I'll do it in VB.NET and the below code will update the email address.


  empId = "12345"
                workerType = "Employee_ID"

                Dim emailValue As String = ""
                Dim effectiveDate As Date = Now()

                Dim emailRequest As New Maintain_Contact_Information_for_Person_Event_RequestType()
                emailRequest.version = "v22.0"
                emailRequest.Add_Only = True

                emailRequest.Maintain_Contact_Information_Data = New Contact_Information_for_Person_Event_DataType()
                emailRequest.Maintain_Contact_Information_Data.Worker_Contact_Information_Data = New Contact_Information_DataType()

                emailRequest.Maintain_Contact_Information_Data.Worker_Contact_Information_Data.Email_Address_Data = New Email_Address_Information_DataType(0) {New Email_Address_Information_DataType()}

                emailRequest.Maintain_Contact_Information_Data.Worker_Reference = New WorkerObjectType()
                emailRequest.Maintain_Contact_Information_Data.Worker_Reference.ID = New WorkerObjectIDType(0) {New WorkerObjectIDType()}
                emailRequest.Maintain_Contact_Information_Data.Worker_Reference.ID(0).type = workerType
                emailRequest.Maintain_Contact_Information_Data.Worker_Reference.ID(0).Value = empId

                emailRequest.Maintain_Contact_Information_Data.Effective_Date = effectiveDate
                emailRequest.Maintain_Contact_Information_Data.Effective_DateSpecified = True

                emailRequest.Maintain_Contact_Information_Data.Worker_Contact_Information_Data.Email_Address_Data(0).Email_Address = emailValue
                emailRequest.Maintain_Contact_Information_Data.Worker_Contact_Information_Data.Email_Address_Data(0).Usage_Data = New Communication_Method_Usage_Information_DataType(0) {New Communication_Method_Usage_Information_DataType()}
                emailRequest.Maintain_Contact_Information_Data.Worker_Contact_Information_Data.Email_Address_Data(0).Usage_Data(0).[Public] = True

                emailRequest.Maintain_Contact_Information_Data.Worker_Contact_Information_Data.Email_Address_Data(0).Usage_Data(0).PublicSpecified = True

                emailRequest.Maintain_Contact_Information_Data.Worker_Contact_Information_Data.Email_Address_Data(0).Usage_Data(0).Type_Data = New Communication_Usage_Type_DataType(0) {New Communication_Usage_Type_DataType()}
                emailRequest.Maintain_Contact_Information_Data.Worker_Contact_Information_Data.Email_Address_Data(0).Usage_Data(0).Type_Data(0).Primary = True

                emailRequest.Maintain_Contact_Information_Data.Worker_Contact_Information_Data.Email_Address_Data(0).Usage_Data(0).Type_Data(0).PrimarySpecified = True

                emailRequest.Maintain_Contact_Information_Data.Worker_Contact_Information_Data.Email_Address_Data(0).Usage_Data(0).Type_Data(0).Type_Reference = New Communication_Usage_TypeObjectType()
                emailRequest.Maintain_Contact_Information_Data.Worker_Contact_Information_Data.Email_Address_Data(0).Usage_Data(0).Type_Data(0).Type_Reference.ID = New Communication_Usage_TypeObjectIDType(0) {New Communication_Usage_TypeObjectIDType()}
                emailRequest.Maintain_Contact_Information_Data.Worker_Contact_Information_Data.Email_Address_Data(0).Usage_Data(0).Type_Data(0).Type_Reference.ID(0).type = "Communication_Usage_Type_ID"
                emailRequest.Maintain_Contact_Information_Data.Worker_Contact_Information_Data.Email_Address_Data(0).Usage_Data(0).Type_Data(0).Type_Reference.ID(0).Value = "WORK"

                Dim emailProxy As Human_ResourcesPortClient = CreateHumanResourcesProxy()

                Dim emailResponse As Maintain_Contact_Information_for_Person_Event_ResponseType

                    emailResponse = emailProxy.Maintain_Contact_Information(emailRequest)
                    Console.WriteLine("email update done")
                Catch fe As FaultException
                    If fe.Message.Contains("Invalid ID value.") Then
                            Console.WriteLine("Email Update ERROR as Employee will try CW")
                            emailRequest.Maintain_Contact_Information_Data.Worker_Reference.ID(0).type = "Contingent_Worker_ID"
                            emailResponse = emailProxy.Maintain_Contact_Information(emailRequest)
                            Console.WriteLine("email update done")
                        Catch ex As Exception
                            Console.WriteLine("Email Update ERROR as CW also " + fe.Message)
                        End Try

                    End If
                    'Console.WriteLine("Email Update ERROR " + fe.Message)
                End Try


Notice that in the Try/Catch section, I catch in case the update doesn't work as an Employee then I try again as a Contingent Worker.

The CreateHumanResourcesProxy function can be found in the earlier post.

Reading from Workday using .NET

Workday is a huge HR service and many companies are moving. Trying to figure out how to interact with Workday has been difficult. Mostly because there are so few samples available.  Workday has lots of documentation on their API, but because the objects are nested/nested/nested, it make it convoluted to figure out exactly where you need to go.

So here I'm putting out how to read a user from the Human Resources WSDL.

Before you can actually get this code to work you have to create reference file using svcutil then modify it because it creates 2 and 3 dimensional arrays.  This is a problem with Visual Studio.
See here for the pre-reqs and how to fix the Human_Resources.cs file

   empId = "12345";

                    var request = new Get_Workers_RequestType { version = "v22.0" };
                    var workerId = new WorkerObjectIDType()
                        type = "Employee_ID",
                        Value = empId

                    var idTypes = new List { 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;
                        response = proxy.Get_Workers(request);
                        string first = response.Response_Data.FirstOrDefault().Worker_Data.Personal_Data.Name_Data.Preferred_Name_Data.Name_Detail_Data.First_Name;
                        string last = response.Response_Data.FirstOrDefault().Worker_Data.Personal_Data.Name_Data.Preferred_Name_Data.Name_Detail_Data.Last_Name;
                        Console.WriteLine(first + " " + last);
                    catch (FaultException fe)
                        // _logger.LogError("Error occurred invoking GetWorker", fe);
                        //return null;
                        Console.WriteLine("error " + fe.Message);

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

            var cb = new CustomBinding(
                new TextMessageEncodingBindingElement(MessageVersion.Soap11, Encoding.UTF8)
                    ReaderQuotas = new System.Xml.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(""));

            proxy.ClientCredentials.UserName.UserName = "userName@tenant";
            proxy.ClientCredentials.UserName.Password = "pass";
            return proxy;


Keep in mind this will work with a worktype of Employee.  You have to change a few things for a Contingent Worker.