Using HAT with CRM in CCA


HAT is a useful tool,  its pretty easy to use (once you get the basic’s) and fairly simple to debug.  However there are some times when using HAT with CRM, or other complex applications, seems to throw you a curve ball

I am going to take you though a few common scenarios and solve them here.  I will cover:

  1. On the result of a search, open either the Account or Contact form  – I will cover this in this post..
  2. Create a workflow that creates a case and populates the case title with the account or customer name  – I will cover this in a future post.

If this is your first time though HAT, or you need a refresher on CCA’s structure and Context information, Please read [Showing CRM data in the Customer Care Accelerator] first.   It will help set the stage a bit and hopefully make some sense of what we are going to do here.

The main difference between what I covered in [Showing CRM data in the Customer Care Accelerator] and this post is that we are only going to use HAT here,  in my other post I used simple URL replacement to get the job done, which works for simple cases that can be driven via URL.

So lets get started.

Displaying the account or contact that you opened via a search

I often encourage folks to articulate in a sentence or two what it is they are trying to do.. when you lay out what your trying to do in a statement, you will often find that you are actually describing the steps you need to do in HAT.  In my case, the task we want to accomplish here is;

“When I search for and find a customer in CCA, I want to show either the account or contact form from CRM, depending on what type of customer I returned.”

Ok that seems pretty straight forward. Now lets break it down.

“When I search form and find a customer in CCA,”

This means,  click the search icon, plug a customer in and select a result.  In UII terms we are starting a new Session.  I know that a Session can contain global, or instanced applications or controls.  In this case it sounds like we are going to do this task in a Instanced Session.  We also know that the Session has a Context, and in the case of CCA, that context looks like this :

<UiiContext>
<State>WA</State>
<CustomerID>cd14c2c5-715c-df11-9795-001a6b4be739</CustomerID>
<CustomerLastName>Adams</CustomerLastName>
<AccountID></AccountID>
<BillingAddress>
3397 Rancho View Drive
Redmond WA, 90000
</BillingAddress>
<Phone1></Phone1>
<Email1>someone@example.com</Email1>
<City>Redmond</City>
<Phone2></Phone2>
<CustomerName>Jay Adams</CustomerName>
<Street>3397 Rancho View Drive</Street>
<IsNewCustomer>False</IsNewCustomer>
<CustomerFirstName>Jay</CustomerFirstName>
<CustomerType>contact</CustomerType>
<AccountName></AccountName>
<ZipCode>90000</ZipCode>
<Country>U.S.</Country>
</UiiContext>

When I’m done searching a customer, that is what will be in my Context.

The next part of the statement is :

“I want to show either the account or contact form from CRM, depending on what type of customer I returned”

So here is the meat of the task. We know in CRM that there is a form for an account, and a form for contact… so we need to determine which one to use, then navigate the form to the right record.  We know this needs to happen in an Instanced Session and really it makes sense to use only one window, as I’m going to be showing “either the account or contact”.

So here is where we start with Visual Studio on this project.

I created a new project called CrmAccountContactView :

image

That drops me into the solution explorer for my project,

Next I need to add a new application to my project

Now there are a few ways I can do that… I can import an existing application in from CRM, or I can add a new one here.  I personally find that adding a everything via the Visual Studio interface is simpler.  So I’m going to add it all via VS.

image

And I am going to call the application “Crm Customer View”

image

Click “OK” and I’m presented next with :

image

This will allow me to denote which type of hosted application I’m working with.  For CRM, I’m going to choose “HTML ( Web application )”

Because I choose a HTML Web Application, HAT will ask me for the URL next.

image

The URL we are going to enter here is the URL that is treated as the “Startup” URL by UII,  so in this case I’m going to use the default loading screen, it really doesn’t matter at this point as we are going to redirect the window where we want it to go later.

Now I clicked “Finish”.   My Project explorer now looks like this:

image

Now I need to Add an Automation,  Automations in UII are Really just Sequential workflow projects, so in my case, I’m going to add a new Sequential workflow project to the Automation Folder.

image

Select Sequential workflow and give it a name…

image

With that done,  My Solution now looks like this :

image

Just a few more house keeping jobs and we will get to the business at hand.  I am going to change the name of the class WorkFlow1.cs to something that is more appropriate to what its doing.

Let me take a moment here to highlight why I’m doing this.

In the most straight forward example, in HAT and UII , a given workflow class equates to an Action. Any given workflow assembly can contain multiple workflow class’s.  As such, if I wanted to use “Workflow1.cs” as my default action,  I rename it “Default.cs”.  because that class will be called by the default action.  Subsequent workflow class’s would be named accordingly to what their action names are.  While this is not required by UII, it makes troubleshooting and code maintenance simpler as you do not need to cross reference from UII Configuration to Workflow class.

I rename the class Workflow1.cs to Default.cs

image

Now I need to associate my Default.cs Workflow as the default workflow for the the Crm Customer View Application. To do that I right clicked on the Crm Customer View and choose “Set Startup Automation”

image

That presents me with a window like this:

image

Here I just went with the defaults, however, if you have more then one workflow project or more then one workflow class, you can choose a workflow class from any project.   This setting will tell HAT what the default assembly and class should be when the project is published to UII.

This completes all the house keeping tasks,  Now we can start adding behaviors to the automation.

Looking back at the Context, I can see that there is a “CustomerType” tag that is populated with either ‘account’ or ‘contact’ depending on what type of customer was loaded from search. I know this by taking a glance at the searchcontrol.cs project where the context is created from CRM Search result.  Now that I know that’s the context has a bit of data I need to make a decision on I need to pull that bit of data into my automation.  To do that I use a “GetContext” shape from HAT. I then need to configure the properties as below :

image

I set the name of the Shape to “GetCustomerType” and the context key to “CustomerType”.  Case is important in this, so make sure its right.

image

Now I need to add an IfElse shape.  My IfElse shape will decided what path I need to go down based on the value, or lack thereof , in the GetCustomerType shape.

I drag in the IfElse and drop it under the GetCustomerType shape and rename it to IfCustomerType.  By Default I get 2 branches with the IfElse Shape, which branch it takes is based on an evaluation at the top of the branch,  in my case I have 3 possible outcomes;

  1. CustomerType == Account
  2. CustomerType == Contact
  3. CustomerType == null/empty

So I need a 3ed branch.

image

Now I will go though and rename the braches appropriately.

My Automation now looks like this:

image

Now I need to add in some logic to each branch, I will use a Declarative Rule Condition for my Rules.

In order :

Name: IsAccount

Condition : this.GetCustomerType.ContextValue.Equals("account", System.StringComparison.CurrentCultureIgnoreCase)

Name: IsContact

Condition : this.GetCustomerType.ContextValue.Equals("contact", System.StringComparison.CurrentCultureIgnoreCase)

I assign the IsAccount Condition to the IfIsAccount branch and IsContact to the IfIsContact branch.  The IfIsUnknown I leave blank because it serves as the “Else” part of the IfElse structure.

Now I’m going to add a GetContext shape to the IfIsAccount and IfIsContact nodes.

image

My 2 GetContext shapes are actually getting the same context key, Reasonably I could have put it outside of the IfElse shape, however for readability iv placed them inside the each condition area and named them to equate to what they are doing.

image

Both are Getting the ContextKey CustomerID.

Next I need to drop in 2 Navigate shapes, These shapes direct the browser to navigate to the appropriate page inside CRM.  My Workflow now looks like this:

image

Iv Configured the Navigate Shapes with specific names and URL’s, Iv also identified the application that the Navigate shape will work against.

For my Account condition, I modified the Navigate shape as :

Name = NavToAccount

ApplicationName = "Crm Customer View”

Url = http://localhost:5551/UiiDemo/sfa/accts/edit.aspx

For my Contact condition, I modified the Navigate shape as :

Name = NavToContact

ApplicationName = "Crm Customer View”

Url = http://localhost:5551/UiiDemo/sfa/conts/edit.aspx

Next thing to do is put in a bit of code to update the URL for the Navigate shape based on the branch.

To do that, I add a code condition to the Account condition between the GetContext and Nav Shapes and Iv named it coMakeAccountUrl. Then, in the Execute code property, I type MakeAccountUrl and hit enter.  That will bring me to a code window that will allow me to type in whatever I need to do.  In this case I’m going to create the Account url.  My code looks like this:

private void MakeAccountUrl(object sender, EventArgs e)
{
string sUrl = NavToAccount.Url + "?id=" + GetAccountId.ContextValue;
Uri targetUri = new Uri(NavToAccount.Url);
if (Uri.TryCreate(sUrl, UriKind.Absolute, out targetUri))
{
NavToAccount.Url = targetUri.ToString();
}
System.Diagnostics.Trace.WriteLine(string.Format("Nav View to {0}", NavToAccount.Url));
}

What this code is doing is creating a new URL based on the GetAccountId Shape’s value and the URL from the NavToAccount, then, if it’s a valid Url, updating the NavtToAccount url shape.

My workflow now looks like this:

image

Now I need to add another code block for Contacts, with a code block to create the URL.  In this case I called the shape coMakeContactUrl, and the ExecuteCode Property MakeContactUrl.

private void MakeContactUrl(object sender, EventArgs e)
{
string sUrl = NavToContact.Url + "?id=" + GetContactId.ContextValue;
Uri targetUri = new Uri(NavToContact.Url);
if (Uri.TryCreate(sUrl, UriKind.Absolute, out targetUri))
{
NavToContact.Url = targetUri.ToString();
}
System.Diagnostics.Trace.WriteLine(string.Format("Nav View to {0}", NavToContact.Url));
}

 

And one last thing to do now before we publish this code and try it,  I need to handle the IfIsUnknown path.  To do that I’m just going to insert a bit of code that logs an alert to the TraceLog.  

Once again I use a Code Shape,  the shape is called coUnknownCustomerType and the Execute Method is called UnknownCustomerType. My code for that block is :

private void UnknownCustomerType(object sender, EventArgs e)
{
System.Diagnostics.Trace.WriteLine(string.Format("Missing Context Key for {0}", GetCustomerType.ContextKey));
}

 

and my completed workflow\automation looks like this :

image

I’m all done with this an now ready to Test it in CCA,  Now I just need to configure a few more points then publish it to CCA.

To do that I’m going to right click on the Application “Crm Customer View” and choose properties..

image

This will open the properties window for the Application and allow us to configure bits before publishing to CRM\Uii.  That window looks like this :

image

First I need to set the display group to “Mainpanel” as I want this app to be shown in the center of the desktop, I am also going to change the Hosting Method to UseSetParent and set the HomePageUrl to about:blank.   The reason I point the homepage to a blank page is to allow the browser to finish it loading process as quickly as possible, were I to leave it at the CRM home page, HAT would need to wait till the CRM home page finished loading prior to moving to the next page.

image

Now I’m ready to deploy this to the server.  To do that I right click on the application and choose Deploy to Server.

image

I am then presented with this dialog,

image

The service URL is the URL to the CRMService.asmx and the Organization is the Org Name for your UII deployment.  I test the connection, and if everything is good, I click “deploy”.

When I run the CCA desktop and choose a customer, either the account or contact forms will appear now.. it should look something like this:

image

You can download the code for this project here: [CrmAccountContactView.zip], and try it for yourself.

if you do, make sure you change the URL’s on the Navigate shapes to point to the right URL’s for your CRM Server.

Next Post will be on using CCA workflow and HAT to create CRM Case.

Comments (9)

  1. Anand Wani says:

    Hi mbarbour,

    Nice post …

    Its working sucessfully. Great job ..

    Do u know how 2 use HAT in contact application.As we select HAT as adapter in contact the default action get neglected, can u help me in this?

  2. MattB-MSFT says:

    I’m not sure I understand your question.. however I think you’re asking if you can use a default action with URL replacement at the same time as a HAT adapter.

    If your using a HAT adapter, then you need to use HAT for actions,  for example you cannot use the URL replacement I describe here (blogs.msdn.com/…/showing-crm-data-in-the-customer-care-accelerator.aspx )  with a HAT adapter ( In UII Release 1 )..  

    You can however create Hybrid adapters based on Hosted controls that will allow you to use them interchangeably.

  3. Ben says:

    Hi Matt

    I have an interesting problem where I'm hosting a Windows application within CCA and trying to pass values from CRM controls to the Windows App controls using a HAT workflow developed in VS2008.

    The problem is, although I've successfully captured the controls of the windows app in VS 2008 using the the App Inspector, the HAT workflow fails to set the controls at runtime…..

    Do you have any tips on 1. How to ensure control bindings are correctly identified for a Win App in the CCA, 2. How to set up the debugger in this instance, 3. Hosting and using HAT with Win Apps in CCA in general (gotcha's etc.)?

    (It's worth mentioning my Win App has an 'splash' screen which authenticates the user before getting to the 'main windows' where the controls live that I'm trying to set. I'm also hosting the Win App with the 'hosted outside' setting)

    I can email my control binding XML if this helps?

    Thanks for your help.

  4. Question says:

    Hi Matt-

    I am getting same error message when I compile my project and your project.  

    AutomationAdapter (app=CRM Customer View,action=default): Exception while starting action: Microsoft.Uii.Common.TypeProvider.TypeProviderException: TPV010: Unable to retrieve type ,file://e:softwareacceleratorsccacrmaccountcontactviewloadcrmaccountuiobjdebugloadcrmaccountui.dll

    Any Ideas?  

    Thanks in advance,

    Steven

  5. Mila says:

    I have a small requirement.. I used my crm projoect link in CCA. When I click on any link its opening as a separate window. Is there any option that the window can open as a tab next to CRM.

    Please guide me.

    Thanks in advance.

    Regards,

    Mila

  6. MattB-MSFT says:

    Need to work on keeping up with this more.. sorry guys..

    Ben:  when you are working with a splash screen you need to use the FindWindow tag in the Bindings to locate the right window to pull from.  The Inspector in HAT will only get you part of the way there.

    Steve:  That will happen when the path is incorrect,  if the path your showing there is the full path then its missing the rest of the word Debug and the Assembly name.

    Mila: Iv done a few posts on this on the CCA discussion group.

    take a look at this post:

    crmcca.codeplex.com/…/View.aspx

  7. Naga says:

    Hi Matt,

    Thats a very clear & nice post. But I'm finding it very difficult to work with CCA R2 for CRM 2011 and with .NET4.0, Could it be possible for you to give a demo/a post some thing like this also for CCA R2 with 4.0 ?

    Thanks again Matt..

  8. Hi Naga,

    Yes I did it using WF 4.0 its very simple.

  9. Hi Matt,

    Im still wayting your next exemple, about haw to cerate a case using HAT.

    Thanks

Skip to main content