Monday, March 16, 2009

Enabling Lookup Fields in eService Accelerator

By default lookup fields are not enabled in eService accelerator. I have modified the code to provide the support for lookup fields. You need to do following steps:

Step 1 : Add a new class under app_code\eService\LookUpData.cs

public class LookUpData
{
public LookUpData()
{
}
private String lookupId;
private String lookupText;
public String LookupId
{
get { return lookupId; }
set { lookupId = value; }
}
public String LookupText
{
get { return lookupText; }
set { lookupText = value; }
}
}

Step 2 : Modify AttributeData.cs and following code towards the end

public sealed class LookupAttributeData : AttributeData
{
private List lookupOptions;
public List LookupOptions
{
get { return lookupOptions; }
set { lookupOptions = value; }
}
}

Step 3 : Modify MetadataUtility.cs and add following method

public static List GetLookUpDataByEntity(MetadataService service, String entityName, CrmService crmService)
{
EntityMetadata entityMetadata = GetEntityMetadata(service, entityName);
String primaryAttribute = entityMetadata.PrimaryField;
String primaryKeyName=entityMetadata.PrimaryKey;
List results = new List;
QueryExpression query = new QueryExpression();
query.EntityName = entityName;
query.AddOrder(primaryAttribute, OrderType.Ascending);
ColumnSet columns = new ColumnSet();
columns.AddColumns(new String[] { primaryAttribute });
query.ColumnSet = columns;
ConditionExpression condition1 = new ConditionExpression();
condition1.AttributeName = "statecode";
condition1.Operator = ConditionOperator.Equal;
condition1.Values = new object[] { 0 };
query.Criteria = new FilterExpression();
query.Criteria.FilterOperator = LogicalOperator.And;
query.Criteria.AddCondition(condition1);
RetrieveMultipleRequest request = new RetrieveMultipleRequest();
request.Query = query;
request.ReturnDynamicEntities = true;
RetrieveMultipleResponse response = (RetrieveMultipleResponse)crmService.Execute(request);
foreach (BusinessEntity item in response.BusinessEntityCollection.BusinessEntities)
{
DynamicEntity entity = (DynamicEntity)item;
if (entity.Properties.Contains(primaryAttribute))
{
LookUpData lkp = new LookUpData();
lkp.LookupText=((String)entity.Properties[primaryAttribute]);
lkp.LookupId = ((Key)entity.Properties[primaryKeyName]).Value.ToString();
results.Add(lkp);
}
}
return results;
}

Step 4: Modify the DynamicEntityUtility and Modify following function in this class

public static List GetAttributeDataByEntity

Step 5: Add following code just after Case statement AttributeType.Lookup:

case AttributeType.Lookup:
LookupAttributeData lookupData = new LookupAttributeData();
String relatedEntityName=((LookupAttributeMetadata)metadata).Targets[0].ToString();
lookupData.LookupOptions=MetadataUtility.GetLookUpDataByEntity(metadataService, relatedEntityName, service);
data = lookupData;
break;

Step 6 : Now goto Controls\EntityEditor.ascx

You need to modify following function
private WebControl GetPopulatedControl(AttributeData attributeData, String defaultValue)

Add following code within switch statement


case AttributeType.Lookup:
LookupAttributeData lookuplistAttributeData = attributeData as LookupAttributeData;
DropDownList listLookup = new DropDownList();
listLookup.ID = attributeData.SchemaName;
listLookup.CssClass = "msa-Global-SelectList";
listLookup.Attributes.Add("attributeType", lookuplistAttributeData.AttributeType.Value.ToString());
listLookup.Attributes.Add("defaultValue", (lookuplistAttributeData.ActualValue ?? 0).ToString());
listLookup.Items.Add(new ListItem());

foreach (LookUpData option in lookuplistAttributeData.LookupOptions)
{
listLookup.Items.Add(new ListItem(option.LookupText, option.LookupId));
}
if (!String.IsNullOrEmpty(lookuplistAttributeData.DisplayValue))
{
listLookup.Items.FindByText(lookuplistAttributeData.DisplayValue).Selected = true;
}
return listLookup;

Step 7 : Modify following function
public void SaveEntity()

Add following code within switch statement


case AttributeType.Lookup:
DropDownList lookuplist = (DropDownList)control;
string selectedlkpValue ="";
if (lookuplist.SelectedItem != null)
{
selectedlkpValue = lookuplist.SelectedItem.Value;
}
if (selectedlkpValue != "")
{
LookupProperty prop = new LookupProperty();
prop.Name = attribute;
prop.Value = new Lookup();
prop.Value.Value = new Guid(selectedlkpValue);
entity.Properties.Add(prop);
}
break;

By doing the above steps you should be able to display Lookup data in eService Accelerator and save back the changes.

28 comments:

Henry said...

This looks great. However, I am struggling adding the list argument.
Using the generic type 'System.Collections.Generic.List-T-' requires '1' type arguments.
Any ideas on this one?

Unknown said...

Hi Henry,

I have the same problem, i think he mean the "LookUpData" class that we add in step 1.

Tim said...

Hi guys,

I have also the same problem, how did you fix this problem.

Santosh Kore said...

Hey Tevinder,

Thanks a ton. It saved my time. I am not getting any problems I replaced List with ArrayList and every thing works fine for me. Thanks again.

Santosh Kore

Tim said...

THX this has fix my problem

Unknown said...

The List are of type System.Collections.Generic.List and the argument must be LookUpData, Tevinder forgot to scape the > and <. Greeting.

Oscar RoZas

agladkik said...

Please, could you explain what and how to fix with List ...
Thank you

Tim said...

I have one problem too. How can i filter the list on account. I get all the info of all customers in the lookup list.

agladkik said...

Tim, how did you fix error with List. I used setup on this page.

Tim said...
This comment has been removed by the author.
Tim said...

I have added by step 2

public sealed class LookupAttributeData : AttributeData
{
private ArrayList lookupOptions;
public ArrayList LookupOptions
{
get { return lookupOptions; }
set { lookupOptions = value; }
}
}


First row step 3
public static ArrayList GetLookUpDataByEntity(MetadataService service, String entityName, CrmService crmService)


And I have added in the eService console a lookup field.

agladkik What is your error code?

agladkik said...

CS0246: System can't find type name or space name "String" ...

Error source:

Line 12: }
Line 13:
Line 14: private String lookupId;
Line 15: private String lookupText;
Line 16:


Source file: c:\Program Files\Microsoft Dynamics CRM eService\App_Code\eService\LookUpData.cs Line: 14

agladkik said...
This comment has been removed by the author.
agladkik said...

Sorry, I have russian version and traslation may be approximate ...

Tim said...

The references may be,
Here below are mine.

using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Globalization;
using System.Collections.Generic;
using System.Collections;
using Microsoft.Crm.Sdk;
using Microsoft.Crm.Sdk.Metadata;
using Microsoft.Crm.Sdk.Query;
using Microsoft.Crm.SdkTypeProxy;
using Microsoft.Crm.SdkTypeProxy.Metadata;

agladkik said...

error with Linq in
using System.Xml.Linq;

If I delete this line, error the same ...

agladkik said...

After minute error changing to

CS0246: ... "ArrayList" ...

Source error:

Line 151:
Line 152:
Line 153: public static ArrayList GetLookUpDataByEntity(MetadataService service, String entityName, CrmService crmService)
Line 154:
Line 155: {


Source file: c:\Program Files\Microsoft Dynamics CRM eService\App_Code\eService\MetadataUtility.cs Line: 153

agladkik said...

I added references to metadatautility and to have got the first error in Lookupdata.cs

agladkik said...

Tim, if it is correct... and files don't have your commercial specific I'd like to ask you to send me your 5 files to see:
- lookupdata.cs
- attributedate.cs
- metadatautility.cs
- dynamicsentityutility.cs
- entityeditor.cs

andrey.gladkikh@live.ru

Thank you

agladkik said...

I have added references using System.Xml.Linq;

Error the same:

CS0246: System can't find type name or space name "String" ...

Error source:

Line 27: }
Line 28:
Line 29: private String lookupId;
Line 30: private String lookupText;
Line 31:

Unknown said...

Hello, thank you for this post.

I did all the steps, but im having trouble selecting the lookup type fields in the eservice console, do i need to do something else?

The lookup fields im trying to add to the portal are from custom entities and the subjectid from incident.

any sugestions?

Unknown said...

Has anyone added this functionality to Partner Relationship Management or Portal Integration

millieburns said...

Thanks for the post. I successfully added a lookup field to my case entity. I see the field when I log into the portal.

However, when adding a new Case, I am encountering an error. At the point that I click Save, I get an error in EntityEditor.ascx.cs:

Server was unable to process request.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.Web.Services.Protocols.SoapException: Server was unable to process request.

Source Error:

Line 397: }
Line 398:
Line 399: EntityId = ((CreateResponse)_crmService.Execute(createRequest)).id;
Line 400: }
Line 401:


Source File: c:\Program Files\Microsoft Dynamics CRM Customer Portal\Controls\EntityEditor.ascx.cs Line: 399

Stack Trace:
[SoapException: Server was unable to process request.]
System.Web.Services.Protocols.SoapHttpClientProtocol.ReadResponse(SoapClientMessage message, WebResponse response, Stream responseStream, Boolean asyncCall) +551452
System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(String methodName, Object[] parameters) +204
Microsoft.Crm.SdkTypeProxy.CrmService.Execute(Request Request) +47
Controls_EntityEditor.SaveEntity() in c:\Program Files\Microsoft Dynamics CRM Customer Portal\Controls\EntityEditor.ascx.cs:399
Controls_EntityEditor.updateButton_Click(Object sender, EventArgs e) in c:\Program Files\Microsoft Dynamics CRM Customer Portal\Controls\EntityEditor.ascx.cs:168
System.Web.UI.WebControls.Button.OnClick(EventArgs e) +105
System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument) +107
System.Web.UI.WebControls.Button.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument) +7
System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) +11
System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData) +33
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +1746

Unknown said...
This comment has been removed by the author.
Unknown said...
This comment has been removed by the author.
Unknown said...

List argument must be LookupData

example: List(LookUpData) (using > <)

and the field is shown by editing the eservice configuration xml

Dinesh said...

Hi,
Could this be applied to contact edit control?

thanks.

Unknown said...

I have successfully made the changes to the code with no errors.however, i cant see the field on the form.is there anything else i need to do to display the field?