Connecting LUIS dialog to form dialog and mapping builtin fields - bots

I have a similar issue to this: Connecting LUIS dialog to form dialog and mapping the right fields
Except I am using built in entities in LUIS such as builtin.number, which I have given a name in LUIS e.g. Amount, but the mapping seems to only be between the field type in the form class and the entity type in the LUIS JSON. Obviously I can't have a field named builtin.number.
How would I go about mapping built in LUIS entities with a form field?

An alternative would be to create a new EntityRecommendation in your LuisIntent method using the Type that will map against your form class. Then you can add that entity into the list of entities you will pass to your form.
// not checking if entity exists for simplicity
var builtInEntity = result.Entities.First(x => x.Type == "builtin.number");
var entity = new EntityRecommendation();
entity.Type = "Amount";
entity.Entity = builtInEntity.Entity;
result.Entities.Add(entity);

Related

Relation between Retieve AND Update in a Dynamic CRM PLUGIN

Is there a relation between Retrieve and Update in a Dynamic CRM Plugin?
For example if I am retrieving only one field:
Entity e = (Entity)service.Retrieve("EntityLogicalName", EntityGuid,
new ColumnSet(new string[] {"entityid"}));
Can I update another field in the Entity e that has NOT been retrieved?
For example:
e.Attributes["AnotherEntityField1] = "test1";
e.Attributes["AnotherEntityField2] = "test2";
service.update(e);
By NOT including all fields that to be updated in the Retrieve, may this cause some hidden issues?
Assuming, as it appears, that you are just retrieving the entity's primary key, entityid, you won't need to do the retrieve.
Entity e = new Entity("EntityLogicalName") { Id = EntityGuid };
e.Attributes.Add("AnotherEntityField1", "test1");
e.Attributes.Add("AnotherEntityField2", "test2");
service.Update(e);
If you are doing a retrieve to confirm the record exists you need to try/catch or use a retrieve multiple since a Retrieve will throw an exception if the record does not exist.
What you are trying to do is perfectly acceptable and won't cause any problems. Since you obtained the Entity instance via a Retrieve operation the required LogicalName and Id will be set correctly for an update.
Your code would need to read as below for adding new attributes not retrieved initially otherwise you'll get a KeyNotFoundException as the Entity type is just a wrapper over Dictionary<string,string>.
e.Attributes.Add("AnotherEntityField2","test2");
When you're trying to update an entity you don't need that an field exists in the attributes colletion, but to avoid the exception "The given key is not presented in the dictionary" is a good practise to check first if the Attributes Colletion contains the field you want to updated. If yes just update it otherwise you have to add it to the Attributes Colletion of the entity.
if(e.Attributes.Contains("AnotherEntityField1"))
{
e.Attributes["AnotherEntityField1"] = "test1";
}
else
{
e.Attributes.Add("AnotherEntityField1", "test1");
}
// now update operation

crm 2011 Unable to cast object of type 'System.Guid' to type 'Microsoft.Xrm.Sdk.EntityReference

The code below creates a set of records from an entity I use to hold "template" records. I loop through the templates and create records which works including the lookup fields where I use an EntityReferenceentity. But when I use an EntityReference to create a relationship back to the parent entity record I get this error.
crm 2011 Unable to cast object of type 'System.Guid' to type
'Microsoft.Xrm.Sdk.EntityReference'
foreach (var template in templateSteps.Entities)
{
Entity step = new Entity("img_workflowmanager");
step["subject"] = template["img_name"];
if (step.Contains("img_poststepid"))
{
step["img_poststepid"] = (EntityReference)template["img_poststepid"];
}
if (step.Contains("img_prestepid"))
{
step["img_prestepid"] = (EntityReference)template["img_prestepid"];
}
step["img_workflowstepsid"] = (EntityReference)postMessageImage["img_procurementpackageid"];
this._orgService.Create(step);
}
The message is clear, postMessageImage["img_procurementpackageid"] contains a Guid and not an EntityReference.
Assuming the entity name is img_workflowsteps you can write
Guid packageId = (Guid)postMessageImage["img_procurementpackageid"];
step["img_workflowstepsid"] = new EntityReference("img_workflowsteps", packageId);
By the way, the first two if conditions will be never executed, because when you create an entity with that syntax, no attributes are defined.

How to discover all Entity Types? One of each?

I need to write a service that connects to CRM, and returns with a list of all of the entity available on the server (custom or otherwise).
How can I do this? To be clear, I am not looking to return all data for all entities. Just a list of every type, regardless of whether any actually exist.
You need to use RetrieveAllEntitiesRequest
RetrieveAllEntitiesRequest request = new RetrieveAllEntitiesRequest()
{
EntityFilters = EntityFilters.Entity,
RetrieveAsIfPublished = true
};
// service is the IOrganizationService
RetrieveAllEntitiesResponse response = (RetrieveAllEntitiesResponse)service.Execute(request);
foreach (EntityMetadata currentEntity in response.EntityMetadata)
{
string logicalName = currentEntity.LogicalName;
// your logic here
}
note that you will get also system or hidden entities, like wizardpage or recordcountsnapshot
You will probably find these sections of the MSDN useful:
Customize Entity Metadata (lookout for the samples linked on that page).
Retrieve and Detect Changes to Metadata.

Adding custom field to User programmatically through liferay.expando

I am trying to add fields to com.liferay.portal.model.User, an extra attribute using Expando. Can someone explain to me how this method is adding a field because docs don't have much description.
private void addUserCustomAttribute(long companyId, ExpandoTable userExpandoTable, String attributeName, int type) throws PortalException, SystemException {
ExpandoColumnLocalServiceUtil.getColumn(userExpandoTable.getTableId(), attributeName); //should be addColumn(long tableId, String name, int type) ???
} //and where can find type description couse i have very specific type, Map(String,Object) couse in ExpandoColumnConstants didn't see it
I have taken this from Liferay Expando Wiki's Adding User Custom Attributes.
When should I call this all? Where to put this in my project? What change is required or everything needs to be changed to call it.
Some good tutorial will be nice because it's hard to find something from 0 to end, always found only some part with no explanation.
The question is not very clear. But if you simply want to add a custom attribute for your User then you can refer to my answer here and reproduced for your reference:
Custom field for the user-entity can be created through:
Control Panel -> Portal -> Custom Fields -> User.
And programmatically can be created as follows:
user.getExpandoBridge().addAttribute("yourCustomFieldKey");
Then set the value as:
user.getExpandoBridge().setAttribute("yourCustomFieldKey", "valueForCustomField");
If your custom field is already present you can check like this:
if (user.getExpandoBridge().hasAttribute("yourCustomFieldKey")) { ... };
The data is stored in tables prefixed with "EXPANDO":
EXPANDOCOLUMN: stores the custom field key and other settings
(contains the tableId refrences)
EXPANDODATA: stores the custom field value for the key (contains the
columnId and tableId refrences)
EXPANDOTABLE: stores for which liferay entity (user) are you adding
the custom field
EXPANDOROW: stores linking information between a user and its values
(contains tableId and userId refrences)
Hope this helps.
If your custom field is multivalue, you can use this:
String customVal = "yourCustomFieldValue";
user.getExpandoBridge().setAttribute("yourCustomFieldKey", new String[] {customVal }, false);
The last parameter set to "false" avoids permission check.

How do I access the data passed back from a workflow association form?

How do I access the data passed back from a workflow association form?
Scenario: When an admin associates a workflow with a sharepoint list I want to display a infopath form that allows variables to be set that apply to all instances on that list. The association form comes up as I would expect and it submits the data entered back to the hosting environment. I've read that I can get to the data once inside an instance workflow through SPWorkflowActivationProperties.ActivationData but this is an xml string. Is it not possible to access the returned data through extended properties much like what you do with normal infopath forms?
As far as I know this doesn't seem possible using InfoPath OOTB. However most of my experience with custom initiation forms used ASP.NET web forms where we serialized a class and stuffed it into ActivationData.
Possible approaches might be:
Encapsulate XML parsing
Use xsd.exe to create a class based off the schema of your infopath form.
1. Encapsulate XML parsing
You could create a class that encapsulates your form data and takes the xml string as a parameter of it's constructor.
Infopath form:
<?xml version="1.0" encoding="UTF-8"?><?mso-infoPathSolution solutionVersion="1.0.0.2" productVersion="12.0.0" PIVersion="1.0.0.0" href="file:///C:\Documents%20and%20Settings\Administrator\My%20Documents\Template1.xsn" name="urn:schemas-microsoft-com:office:infopath:Template1:-myXSD-2005-10-21T21-12-27" ?><?mso-application progid="InfoPath.Document" versionProgid="InfoPath.Document.2"?><my:assetTracking xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:my="http://schemas.microsoft.com/office/infopath/2003/myXSD/2005-10-21T21:12:27" xmlns:xd="http://schemas.microsoft.com/office/infopath/2003" xml:lang="en-gb">
<my:employee>
<my:employeeName></my:employeeName>
<my:employeeDepartment></my:employeeDepartment>
</my:employee>
<my:assets>
<my:asset>
<my:assetID></my:assetID>
<my:assetDescription></my:assetDescription>
<my:assetMake></my:assetMake>
<my:assetModel></my:assetModel>
<my:assetSerialNumber></my:assetSerialNumber>
<my:assetAssignedTo></my:assetAssignedTo>
<my:assetDepartment></my:assetDepartment>
<my:assetLocation></my:assetLocation>
<my:assetCategory></my:assetCategory>
<my:assetNotes></my:assetNotes>
</my:asset>
</my:assets>
Custom form data class
public class FormData
{
public string EmployeeName { get; set; }
public string EmployeeDepartment { get; set; }
public FormData(string formData)
{
XmlDocument document = new XmlDocument();
document.LoadXml(formData);
XmlNamespaceManager namespaceManager = new XmlNamespaceManager(document.NameTable);
namespaceManager.AddNamespace("my", "http://schemas.microsoft.com/office/infopath/2003/myXSD/2007-05-08T04:21:20");
// Initialize member fields
this.EmployeeName = document.SelectSingleNode("/my:employee/my:employeeName", nsmgr).InnerText;
this.EmployeeDepartment = doc.SelectSingleNode("/my:employee/my:employeeDepartment", nsmgr).InnerText;
etc....
}
}
2. Use xsd.exe
xsd can be used to generate a class that is based on the schema used by your workflow form. See: How to: Access Association and Initiation Form Data in a Workflow

Resources