How to Insert data using lookup CRM 365 through Plugin C# - c#

i have a lookup "new_lookuptransactionheader" in my entity "new_trialxrmservicetoolkit". This lookup linked from "new_transactionheader" entity. How can i insert data using c# crm plugin?
this mycode:
public void InsertDataUsingLookup(XrmServiceContext xrm, Entity entitiy, ITracingService tracer)
{
new_trialxrmservicetoolkit trial = new new_trialxrmservicetoolkit();
trial.new_name = "testplugin";
trial.new_LookupTransactionHeader = null; //this is i don't know how to get value from new_LookupTransactionHeader
trial.new_Notes = "this is test plugin using c#";
xrm.AddObject(trial);
xrm.SaveChanges();
}
I updated mycode and this solve:
public void InsertDataUsingLookup(XrmServiceContext xrm, Entity entitiy, ITracingService tracer)
{
new_trialxrmservicetoolkit trial = new new_trialxrmservicetoolkit();
trial.new_name = "testplugin";
trial.new_LookupTransactionHeader = new EntityReference("new_transactionheader", Guid.Parse("5564B5F0-0292-E711-8122-E3FE48DB937B"));
trial.new_Notes = "this is test plugin using c#";
xrm.AddObject(trial);
xrm.SaveChanges();
}

trial.Attributes["new_LookupTransactionHeader"] = new EntityReference("new_transactionheader", new_transactionheaderId-GUID);
You have to use EntityReference like above to setup lookup attribute.

Related

Dynamics 365 Plugin for lookup values

Error: 0x80040203 Invalid Argument
I'm new to Dynamics. In preparation for getting lookup values from external data source into Dynamics via a plugin, I wanted to test first with hard coded values with this code. But after I registered the assembly, data provider and data source, I created a virtual entity in dynamics which I linked up to a field (lookup type) on a form. After publishing, clicking on the field throws error - Invalid Argument
using System;
using Microsoft.Xrm.Sdk;
namespace Hardcoded.Names.Plugin
{
public class NamesLookupPlugin : IPlugin
{
public void Execute(IServiceProvider serviceProvider)
{
var context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
var serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
serviceFactory.CreateOrganizationService(context.UserId);
var tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
try
{
var results = new EntityCollection();
var itemOne = new Entity
{
["ID"] = Guid.NewGuid(),
["Name"] = "First Item"
};
var itemTwo = new Entity()
{
["ID"] = Guid.NewGuid(),
["Name"] = "Second Item"
};
results.Entities.Add(itemOne);
results.Entities.Add(itemTwo);
context.OutputParameters["BusinessEntityCollection"] = results;
}
catch (Exception e)
{
tracingService.Trace($"{e.Message} {e.StackTrace}");
if (e.InnerException != null)
tracingService.Trace($"{e.InnerException.Message} {e.InnerException.StackTrace}");
throw new InvalidPluginExecutionException(e.Message);
}
}
}
}
I expect to see "First Item" and "Second Item" selectable in the lookup field.
You’re hooking on RetrieveMultiple message in your plug-in. There is also Retrieve message (get single record by EntityReference) - you need to hook on that message as well for your entity.

Dynamics 365 (On-Prem): Share record with multiple teams - C#

I have a situation where I will need to share records with all teams. All my traces show that all the team names and record are what they should be (I took out the traces in the code to save space). However, the record isn't sharing upon testing. Do I have this written correctly? I guess my logic was to loop through all teams and share the record. Pulling my hair out with the one. The following is my wf assembly code:
using Microsoft.Xrm.Sdk.Workflow;
using System;
using System.Activities;
using System.Diagnostics;
using System.ServiceModel;
using Microsoft.Crm.Sdk.Messages;
using Microsoft.Xrm.Sdk.Query;
namespace workfow_ShareWithAllTeams
{
public class workfow_ShareWithAllTeams : CodeActivity
{
protected override void Execute(CodeActivityContext executionContext)
{
ITracingService tracer = executionContext.GetExtension<ITracingService>();
IWorkflowContext context = executionContext.GetExtension<IWorkflowContext>();
IOrganizationServiceFactory serviceFactory = executionContext.GetExtension<IOrganizationServiceFactory>();
IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
try
{
Entity entity = (Entity) context.InputParameters["Target"];
//TODO: Do stuff
QueryExpression qe = new QueryExpression();
qe.EntityName = "team";
qe.ColumnSet = new ColumnSet();
qe.ColumnSet.Columns.Add("teamid");
qe.ColumnSet.Columns.Add("name");
var teams = service.RetrieveMultiple(qe);
Guid Id = context.PrimaryEntityId;
QueryExpression query = new QueryExpression("item");
query.ColumnSet = new ColumnSet();
query.ColumnSet.Columns.Add("itemid");
query.ColumnSet.Columns.Add("name");
query.Criteria.AddCondition(new ConditionExpression("itemid", ConditionOperator.Equal, Id));
var recordToShare = service.RetrieveMultiple(query);
foreach (Entity team in teams.Entities) //looping through all teams to share
{
foreach (Entity record in recordToShare.Entities)//only one record in entity collection
{
GrantAccessRequest grant = new GrantAccessRequest();
grant.Target = new EntityReference(entity.LogicalName, entity.Id);
PrincipalAccess principal = new PrincipalAccess();
principal.Principal = new EntityReference(team.LogicalName, team.Id);
principal.AccessMask = AccessRights.ReadAccess | AccessRights.AppendAccess |
AccessRights.WriteAccess | AccessRights.AppendToAccess |
AccessRights.ShareAccess | AccessRights.AssignAccess;
grant.PrincipalAccess = principal;
}
}
}
catch (Exception e)
{
throw new InvalidPluginExecutionException(e.Message);
}
}
}
}
Everything is perfect, except the below line is missing:
service.Execute(grant);
Well, I think I answered my own question. Took me hours to figure I was missing the following 1 line of vital code:
GrantAccessResponse granted = (GrantAccessResponse)serice.Execute(grant);
Adding this worked.

How to get Unique Display name for VSTS/TFS identity?

I am a writing a .Net application using the VSTS/TFS Rest .Net libraries and in one place I need to update workitems' System.AssignedTo field values and while I do want to adhere to the new(ish), unique displayname rules for identity work item fields, I have a hard time finding a method to get the Unique display name(s) for given identities.
The old / client object model does have an explicit helper method to get these unique names, but I have not found any rest endpoint nor client api method that would provide the same.
So I am wondering, given a list of identities, how do I get their corresponding unique display names which I can use to unambiguously set identity work item fields?
String collectionUri = "http://collectionurl/";
VssCredentials creds = new VssClientCredentials();
creds.Storage = new VssClientCredentialStorage();
VssConnection connection = new VssConnection(new Uri(collectionUri), creds);
TeamHttpClient thc = connection.GetClient<TeamHttpClient>();
List<IdentityRef> irs = thc.GetTeamMembersAsync("ProjectName","TeamName").Result;
foreach (IdentityRef ir in irs)
{
Console.WriteLine(ir.UniqueName);
Console.WriteLine(ir.DisplayName);
}
You could try the code below to get unique name:
using System;
using System.Collections.Generic;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.Framework.Client;
using Microsoft.TeamFoundation.Framework.Common;
namespace ConsoleApplication3
{
class Program
{
static void Main(string[] args)
{
TfsConfigurationServer tcs = new TfsConfigurationServer(new Uri("http://tfsserver:8080/tfs"));
IIdentityManagementService ims = tcs.GetService<IIdentityManagementService>();
TeamFoundationIdentity tfi = ims.ReadIdentity(IdentitySearchFactor.AccountName, "[TEAM FOUNDATION]\\Team Foundation Valid Users", MembershipQuery.Expanded, ReadIdentityOptions.None);
TeamFoundationIdentity[] ids = ims.ReadIdentities(tfi.Members, MembershipQuery.None, ReadIdentityOptions.None);
foreach (TeamFoundationIdentity id in ids)
{
if (id.Descriptor.IdentityType == "System.Security.Principal.WindowsIdentity")
{
Console.WriteLine(id.DisplayName);
Console.WriteLine(id.UniqueName);
}
}
Console.ReadLine();
}
}
}
foreach (var workItem in workItems)
{
if (workItem.Fields.ContainsKey("System.AssignedTo"))
{
var person = (IdentityRef)workItem.Fields["System.AssignedTo"];
string codereview_reviewer = person.DisplayName;
Console.WriteLine(codereview_reviewer);
}
}

How to write a Unit Test in CRM 2011 development

I am willing to start writing Unit Tests for my CRM 2011 code. I have very little experience of Unit Testing, so I would like some help with it.
The method I would like to test is:
public Proxy.custom_serviceobject PopulateServiceObject(Proxy.custom_serviceobject crmServiceObject, serviceobject irisServiceObject, Guid locationId)
{
//set the reference to the location the order is connected to
crmServiceObject.custom_location = new EntityReference("custom_location", locationId);
//add the reference to the product in the serviceobject
crmServiceObject.custom_product = new EntityReference("product", new Guid(irisServiceObject.ItemId));
//convert the errorid to an int
Int32 errorId;
var success = Int32.TryParse(irisServiceObject.ErrorId, out errorId);
crmServiceObject.custom_errorclassOptionSetValue = success ? new OptionSetValue(errorId) : new OptionSetValue(Int32.MinValue);
crmServiceObject.custom_serviceobjecttype =
new EntityReference("custom_serviceobjecttype", new Guid(irisServiceObject.ObjectType.Id));
crmServiceObject.custom_placement = irisServiceObject.SortId;
crmServiceObject.custom_yearofinstallationOptionSetValue = new OptionSetValue(irisServiceObject.AuditYear);
crmServiceObject.custom_yearofmanufactureOptionSetValue = new OptionSetValue(irisServiceObject.ProductionYear);
crmServiceObject.custom_location = new EntityReference("custom_location", new Guid(irisServiceObject.Location));
crmServiceObject.custom_quantity = irisServiceObject.Qty;
crmServiceObject.custom_remark = irisServiceObject.ExternalNote;
crmServiceObject.custom_internalremark = irisServiceObject.InternalNote;
if (irisServiceObject.Cancelled)
{
var setStateRequest = new SetStateRequest
{
EntityMoniker = new EntityReference
{
Id = crmServiceObject.Id,
LogicalName = "custom_serviceobject"
},
State = new OptionSetValue(StatusInactive),
Status = new OptionSetValue(StatusReasonInactive)
};
Service.Execute(setStateRequest);
}
return crmServiceObject;
}
Do you have some ideas about what kind of test I could write? Should I mock some components?
Your method only does two things, update some values in the crmServiceObject, and execute an update statement. Since there is nothing CRM specific (besides besides the crmServiceObject being a type defined by CRM) to unit testing updating an object I'll skip that part of it.
As far as the CRM call to disable the entity, you've got two options for a unit test. Verify that CRM performed a disable or not, or mock an IOrganizationService and assert that the Execute call was made or not. It's up to you really.
This question may be helpful as well, although it relates to plugins specifically.

CRM2011 - "The given key was not present in the dictionary"

I am what you call a "n00b" in CRM plugin development. I am trying to write a plugin for Microsoft's Dynamics CRM 2011 that will create a new activity entity when you create a new contact. I want this activity entity to be associated with the contact entity.
This is my current code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xrm.Sdk;
namespace ITPH_CRM_Deactivate_Account_SSP_Disable
{
public class SSPDisable_Plugin: IPlugin
{
public void Execute(IServiceProvider serviceProvider)
{
// Obtain the execution context from the service provider.
IPluginExecutionContext context = (IPluginExecutionContext)
serviceProvider.GetService(typeof(IPluginExecutionContext));
IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
if (context.InputParameters.Contains("Target") && context.InputParameters["target"] is Entity)
{
Entity entity = context.InputParameters["Target"] as Entity;
if (entity.LogicalName != "account")
{
return;
}
Entity followup = new Entity();
followup.LogicalName = "activitypointer";
followup.Attributes = new AttributeCollection();
followup.Attributes.Add("subject", "Created via Plugin.");
followup.Attributes.Add("description", "This is generated by the magic of C# ...");
followup.Attributes.Add("scheduledstart", DateTime.Now.AddDays(3));
followup.Attributes.Add("actualend", DateTime.Now.AddDays(5));
if (context.OutputParameters.Contains("id"))
{
Guid regardingobjectid = new Guid(context.OutputParameters["id"].ToString());
string regardingobjectidType = "account";
followup["regardingobjectid"] = new EntityReference(regardingobjectidType, regardingobjectid);
}
service.Create(followup);
}
}
}
But when i try to run this code: I get an error when i try to create a new contact in the CRM environment. The error is: "The given key was not present in the dictionary" (Link *1). The error pops up right as i try to save the new contact.
Link *1: http://puu.sh/4SXrW.png
(Translated bold text: "Error on business process")
Microsoft Dynamics CRM uses the term activity to describe several types of interactions. The types of activities are:
Phone Call, Task, E-mail, Letter, Fax and Appointment.
ActivityPointer (Activity) Entity
To make your code working Replace the following line:
Entity followup = new Entity();
with
Entity followup = new Entity("task");
And remove the following line:
followup.LogicalName = "activitypointer";
Also please read my comment and Guido Preite's commend above. You need to modify your code to make it working with contact.
Edited
Make sure ContactId does exist in CRM before referencing it to Activity.
This can often happen if you are explicity adding an attribute value to the target entity in you plugin where it already has been added.
Rather than entity.Attributes.Add(...)
use entity["attributename"] = ...

Categories

Resources