DynamicActivity validation error in CRM 2011 workflow - dynamics-crm-2011

I was building a workflow for a custom lead qualifying.
I build a workflow in CRM and I am invoking the custom workflow activity passing the lead reference as an input parameter and I expect the reference of the created account as a return parameter.
The code is:
using System;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Workflow;
using Microsoft.Xrm.Sdk.Query;
using System.Activities;
using Microsoft.Crm.Sdk.Messages;
namespace Quicksale
{
/// <summary>
/// Provide the functionality to qualify a lead
/// </summary>
public class QualifyLead : CodeActivity
{
#region Parameters
[Input("EntityReference leadIn")]
[ReferenceTarget("lead")]
public InOutArgument<EntityReference> LeadReference { get; set; }
[Output("newAccount")]
[ReferenceTarget("account")]
[RequiredArgument]
public OutArgument<EntityReference> accountRef { get; set; }
#endregion Parameters
public Guid existingAccount(Guid leadId, IOrganizationService service)
{
QueryExpression accQuery = new QueryExpression("account");
ColumnSet accColumnSet = new ColumnSet("accountid");
accQuery.ColumnSet = accColumnSet;
accQuery.Criteria = new FilterExpression();
accQuery.Criteria.FilterOperator = LogicalOperator.Or;
accQuery.Criteria.AddCondition("originatingleadid", ConditionOperator.Equal, leadId);
accQuery.Criteria.AddCondition("custom_editableoriginatinglead",
ConditionOperator.Equal, leadId);
EntityCollection retrieved = service.RetrieveMultiple(accQuery);
Guid retrievedAccount = Guid.Empty;
// Iterate through returned collection.
foreach (var c in retrieved.Entities)
{
retrievedAccount = new Guid(c.Attributes["accountid"].ToString());
return retrievedAccount;
}
return Guid.Empty;
}
public Guid existingContact(Guid leadId, IOrganizationService service)
{
QueryExpression contQuery = new QueryExpression("contact");
ColumnSet contColumnSet = new ColumnSet("contactid");
contQuery.ColumnSet = contColumnSet;
contQuery.Criteria = new FilterExpression();
contQuery.Criteria.FilterOperator = LogicalOperator.Or;
contQuery.Criteria.AddCondition("originatingleadid",
ConditionOperator.Equal, leadId);
contQuery.Criteria.AddCondition("custom_editableoriginatinglead",
ConditionOperator.Equal, leadId);
EntityCollection retrieved = service.RetrieveMultiple(contQuery);
Guid retrievedContactId = Guid.Empty;
// Iterate through returned collection.
foreach (var c in retrieved.Entities)
{
retrievedContactId = new Guid(c.Attributes["contactid"].ToString());
return retrievedContactId;
}
return Guid.Empty;
}
/// <summary>
/// Overridden Execute() function to provide functionality to the workflow.
/// </summary>
/// <param name="executionContext">Execution context of the Workflow</param>
/// <returns></returns>
protected override void Execute(CodeActivityContext executionContext)
{
#region context
//Create the context
IWorkflowContext context = executionContext.GetExtension<IWorkflowContext>();
IOrganizationServiceFactory serviceFactory =
executionContext.GetExtension<IOrganizationServiceFactory>();
IOrganizationService service =
serviceFactory.CreateOrganizationService(context.UserId);
ITracingService tracingService = executionContext.GetExtension<ITracingService>();
#endregion context
tracingService.Trace("Retrieving lead...");
Entity leadEntity = Helper.ActualEntity(LeadReference.Get(executionContext), service);
tracingService.Trace("Lead retrieved.");
tracingService.Trace("Qualifying lead...");
QualifyLeadRequest req = new QualifyLeadRequest();
Guid leadId = new Guid(leadEntity.Attributes["leadid"].ToString());
req.LeadId = new EntityReference("lead", leadId);
//Set the lead to qualified status
req.Status = new OptionSetValue(3);
//choose what records to create from the lead
tracingService.Trace("Checking if lead has already been qualified as an account...");
Guid accountId = existingAccount(leadId, service);
tracingService.Trace("If lead has already been qualified as an account checked.");
req.CreateAccount = accountId == Guid.Empty;
tracingService.Trace("Checking if lead has already been qualified as a contact...");
req.CreateContact = existingContact(leadId,service)==Guid.Empty;
tracingService.Trace("If lead has already been qualified as a contact checked.");
req.CreateOpportunity = false;
QualifyLeadResponse resp = (QualifyLeadResponse)service.Execute(req);
tracingService.Trace("Lead qualified.");
tracingService.Trace("Retrieving account id...");
if (accountId == Guid.Empty) {
accountId = existingAccount(leadId, service);
}
tracingService.Trace("Account id retrieved.");
tracingService.Trace("Setting output account reference...");
accountRef.Set(executionContext, new EntityReference("account", accountId));
tracingService.Trace("Output account reference set.");
}
}
}
When I execute the workflow I get this error:
Unhandled Exception: System.ServiceModel.FaultException`1[[Microsoft.Xrm.Sdk.OrganizationServiceFault,
Microsoft.Xrm.Sdk, Version=5.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]]:
The following errors were encountered while processing the workflow tree:
'
DynamicActivity': The private implementation of activity '1:
DynamicActivity' has the following validation error: Compiler error(s) encountered processing expression
"DirectCast(CustomActivityStep13_1_converted, Microsoft.Xrm.Sdk.EntityReference)".Invalid L-value expression.:Reference expressions cannot end with Conversion.
The provided expression's type must exactly match the type T of VisualBasicReference<T>
or LambdaReference<T>.Detail:
<OrganizationServiceFault xmlns:i="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://schemas.microsoft.com/xrm/2011/Contracts">
<ErrorCode>-2147220970</ErrorCode>
<ErrorDetails xmlns:d2p1="http://schemas.datacontract.org/2004/07/System.Collections.Generic" />
<Message>The following errors were encountered while processing the workflow tree:&#13;&#10;&#39;DynamicActivity&#39;: The private implementation of activity &#39;1: DynamicActivity&#39; has the following validation error: Compiler error(s) encountered processing expression &quot;DirectCast(CustomActivityStep13_1_converted, Microsoft.Xrm.Sdk.EntityReference)&quot;.Invalid L-value expression.:Reference expressions cannot end with Conversion. The provided expression&#39;s type must exactly match the type T of VisualBasicReference&lt;T&gt; or LambdaReference&lt;T&gt;.</Message>
<Timestamp>2013-09-25T08:40:17.2376169Z</Timestamp>
<InnerFault>
<ErrorCode>-2147220970</ErrorCode>
<ErrorDetails xmlns:d3p1="http://schemas.datacontract.org/2004/07/System.Collections.Generic" />
<Message>Unhandled Exception: System.Activities.InvalidWorkflowException: The following errors were encountered while processing the workflow tree:
'DynamicActivity': The private implementation of activity '1: DynamicActivity' has the following validation error: Compiler error(s) encountered processing expression "DirectCast(CustomActivityStep13_1_converted, Microsoft.Xrm.Sdk.EntityReference)".Invalid L-value expression.:Reference expressions cannot end with Conversion. The provided expression's type must exactly match the type T of VisualBasicReference<T> or LambdaReference<T>.
at System.Activities.Hosting.WorkflowInstance.ValidateWorkflow(WorkflowInstanceExtensionManager extensionManager)
at System.Activities.WorkflowApplication.EnsureInitialized()
at System.Activities.WorkflowApplication.Enqueue(InstanceOperation operation, Boolean push)
at System.Activities.WorkflowApplication.WaitForTurn(InstanceOperation operation, TimeSpan timeout)
at System.Activities.WorkflowApplication.InternalRun(TimeSpan timeout, Boolean isUserRun)
at Microsoft.Crm.Workflow.SynchronousRuntime.ActivityHost.StartWorkflowExecution(Activity workflow, ICommonWorkflowContext context)
at Microsoft.Crm.Workflow.SynchronousRuntime.ActivityHost.StartWorkflow(ICommonWorkflowContext context)
</Message>
<Timestamp>2013-09-25T08:40:17.2376169Z</Timestamp>
<InnerFault i:nil="true" />
<TraceText i:nil="true" />
</InnerFault>
<TraceText i:nil="true" />
</OrganizationServiceFault>
Any ideas about why this is happening? It seems quite regular code to me

In argument definition you have InOutArgument decorated only with Input attribute
[Input("EntityReference leadIn")]
[ReferenceTarget("lead")]
public InOutArgument<EntityReference> LeadReference { get; set; }
Changing type to InArgument
public InArgument<EntityReference> LeadReference { get; set; }
will fix this problem.

Related

CRM 2011: Custom Workflow Activity Output Parameters don´t show

everyone,
I'm having a problem that does not appear in the output parameter list on the right side under "Look for" underneath "Local Values", I do not understand the problem or reason for not appear, since in terms of input parameters's okay.
protected override void Execute(CodeActivityContext executionContext)
{
ITracingService tracingService = executionContext.GetExtension<ITracingService>();
//Create the context
IWorkflowContext context = executionContext.GetExtension<IWorkflowContext>();
IOrganizationServiceFactory serviceFactory = executionContext.GetExtension<IOrganizationServiceFactory>();
IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
tracingService.Trace("Creating Account");
Account entity = new Account();
entity.Name = AccountName.Get<string>(executionContext);
Guid entityId = service.Create(entity);
string a = entity.Name;
AccountNameTest.Set(executionContext, a);
tracingService.Trace("Account created with Id {0}", entityId.ToString());
tracingService.Trace("Create a task for the account");
Task newTask = new Task();
newTask.Subject = TaskSubject.Get<string>(executionContext);
newTask.RegardingObjectId = new EntityReference(Account.EntityLogicalName, entityId);
Guid taskId = service.Create(newTask);
tracingService.Trace("Task has been created");
tracingService.Trace("Retrieve the task using QueryByAttribute");
QueryByAttribute query = new QueryByAttribute();
query.Attributes.AddRange(new string[] { "regardingobjectid" });
query.ColumnSet = new ColumnSet(new string[] { "subject" });
query.EntityName = Task.EntityLogicalName;
query.Values.AddRange(new object[] { entityId });
tracingService.Trace("Executing the Query for entity {0}", query.EntityName);
//Execute using a request to test the OOB (XRM) message contracts
RetrieveMultipleRequest request = new RetrieveMultipleRequest();
request.Query = query;
Collection<Entity> entityList = ((RetrieveMultipleResponse)service.Execute(request)).EntityCollection.Entities;
//Execute a request from the CRM message assembly
tracingService.Trace("Executing a WhoAmIRequest");
service.Execute(new WhoAmIRequest());
if (1 != entityList.Count)
{
tracingService.Trace("The entity list was too long");
throw new InvalidPluginExecutionException("Query did not execute correctly");
}
else
{
tracingService.Trace("Casting the Task from RetrieveMultiple to strong type");
Task retrievedTask = (Task)entityList[0];
if (retrievedTask.ActivityId != taskId)
{
throw new InvalidPluginExecutionException("Incorrect task was retrieved");
}
tracingService.Trace("Retrieving the entity from IOrganizationService");
//Retrieve the task using Retrieve
retrievedTask = (Task)service.Retrieve(Task.EntityLogicalName, retrievedTask.Id, new ColumnSet("subject"));
if (!string.Equals(newTask.Subject, retrievedTask.Subject, StringComparison.Ordinal))
{
throw new InvalidPluginExecutionException("Task's subject did not get retrieved correctly");
}
//Update the task
retrievedTask.Subject = UpdatedTaskSubject.Get<string>(executionContext);
service.Update(retrievedTask);
}
}
//
[Input("Name conta")]
[Default("testv01")]
public InArgument<string> AccountName { get; set; }
[Input("Task")]
[Default("testv01")]
public InArgument<string> TaskSubject { get; set; }
[Input("Update task")]
[Default("testUPDATED:v01}")]
public InArgument<string> UpdatedTaskSubject { get; set; }
[Output("Account ID Guid")]
[Default("testUPDATED:v01")]
public OutArgument<string> AccountNameTest { get; set; }
Ok, problem solved, just restart IIS to assume the fields, or through version change. The problem was the update of the plugin, this also happens with workflows. According to CRM 4.0 i realized this situation does not happen in CRM 4.0.
Even though this Question is already answered I wanted to share two Cases where this solution didn't work (even in a recent Version of CRM):
Case 1
Having choosen Input-Parameter-Names that contained german Umlauts (äöüß).
IIS-restart did not help.
Choosing Names without Umlauts solved the Problem for me.
Case 2
We recently also had a case where a normal In-Argument did not show up, even after restarting the entire Maschine CRM was running on. The Solution was not to obvious:
Open PluginRegistrationTool from SDK
Choose the Assembly that contains your CWA
Choose your CWA
Hit the Save-Button in the Properties-Tab of your CWA

Factories, services, repository in DDD

I have some questions regarding factories, repositories and services in DDD. I have the following entities: Folder, file, FileData.
In my opinion the "Folder" is an aggregate root and should have the responsibility of creating the File and FileData object.
So my first question is should I use a factory to create this aggreate or is it up to the repository? At this time I have 2 repositories, one for Folder and another for File, but it seems to me I should merge them together. The following code snippet, shows my Folder Repository, which is located in my infrastructure layer:
public class FolderRepository : IFolderRepository
{
#region Fields
private readonly IFolderContext _context;
private readonly IUnitOfWork _unitOfWork;
#endregion
#region Constructor
public FolderRepository(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
_context = _unitOfWork.Context as IFolderContext;
}
#endregion
public IUnitOfWork UnitOfWork
{
get { return _unitOfWork; }
}
public IQueryable<Folder> All
{
get { return _context.Folders; }
}
public Folder Find(Guid id)
{
return _context.Folders.Find(id);
}
public void InsertGraph(Folder entity)
{
_context.Folders.Add(entity);
}
public void InsertOrUpdate(Folder entity)
{
if (entity.Id == Guid.Empty)
{
_context.SetAdd(entity);
}
else
{
_context.SetModified(entity);
}
}
public bool Delete(Guid id)
{
var folder = this.Find(id) ?? _context.Folders.Find(id);
_context.Folders.Remove(folder);
return folder == null;
}
public int AmountOfFilesIncluded(Folder folder)
{
throw new NotImplementedException();
//return folder.Files.Count();
}
public void Dispose()
{
_context.Dispose();
}
}
Next I have created a service in my application layer, this is called "IoService". I have my doubts about the location of the service. Should it be moved to the domain layer?
public class IoService : IIoService
{
#region Fields
private readonly IFolderRepository _folderRepository;
private readonly IFileRepository _fileRepository;
private readonly IUserReferenceRepository _userReferenceRepository;
#endregion
#region Constructor
public IoService(IFolderRepository folderRepository, IFileRepository fileRepository, IUserReferenceRepository userReferenceRepository)
{
if(folderRepository == null)
throw new NullReferenceException("folderRepository");
if(fileRepository == null)
throw new NullReferenceException("fileRepository");
if (userReferenceRepository == null)
throw new NullReferenceException("userReferenceRepository");
_folderRepository = folderRepository;
_fileRepository = fileRepository;
_userReferenceRepository = userReferenceRepository;
}
#endregion
#region Folder Methods
/// <summary>
/// Create a new 'Folder'
/// </summary>
/// <param name="userReference"></param>
/// <param name="name"></param>
/// <param name="parentFolder"></param>
/// <param name="userIds">The given users represent who have access to the folder</param>
/// <param name="keywords"></param>
/// <param name="share"></param>
public void AddFolder(UserReference userReference, string name, Folder parentFolder = null, IList<Guid> userIds = null, IEnumerable<string> keywords = null, bool share = false)
{
var userReferenceList = new List<UserReference> { userReference };
if (userIds != null && userIds.Any())
{
userReferenceList.AddRange(userIds.Select(id => _userReferenceRepository.Find(id)));
}
var folder = new Folder
{
Name = name,
ParentFolder = parentFolder,
Shared = share,
Deleted = false,
CreatedBy = userReference,
UserReferences = userReferenceList
};
if (keywords != null)
{
folder.Keywords = keywords.Select(keyword =>
new Keyword
{
Folder = folder,
Type = "web",
Value = keyword,
}).ToList();
}
//insert into repository
_folderRepository.InsertOrUpdate(folder);
//save
_folderRepository.UnitOfWork.Save();
}
/// <summary>
/// Get 'Folder' by it's id
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public Folder GetFolder(Guid id)
{
return _folderRepository.Find(id);
}
#endregion
#region File Methods
/// <summary>
/// Add a new 'File'
/// </summary>
/// <param name="userReference"></param>
/// <param name="folder"></param>
/// <param name="data"></param>
/// <param name="name"></param>
/// <param name="title"></param>
/// <param name="keywords"></param>
/// <param name="shared"></param>
public void AddFile(UserReference userReference, Folder folder, FileData data, string name, string title = "", IEnumerable<string> keywords = null, bool shared = false)
{
var file = new File
{
Name = name,
Folder = folder,
FileData = data,
CreatedBy = userReference,
Type = data.Type
};
if (keywords != null)
{
file.Keywords = keywords.Select(keyword =>
new Keyword
{
File = file,
Type = "web",
Value = keyword,
}).ToList();
}
folder.Files.Add(file);
folder.Updated = DateTime.UtcNow;
_folderRepository.InsertOrUpdate(folder);
//save
_folderRepository.UnitOfWork.Save();
}
/// <summary>
/// Get 'File' by it's id
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public File GetFile(Guid id)
{
return _fileRepository.Find(id);
}
#endregion
}
To summarize:
Should I use the service for creating the folder object. Or should the service just use a factory, which have the responsibility of creating the object and send the created object to the repository? What about dependency injection in the service, should I inject my services from the UI layer with IOC containers like Unity or should I just hardcode the dependencies in the service?
Thanks
So my first question is should I use a factory to create this aggregate
or is it up to the repository?
A factory is responsible for creation while a repository is responsible for persistence. Upon reconstitution, the repository will effectively create instances. However, often times this creation process is done with reflection and doesn't go through a factory to prevent initialization that should only occur at creation time.
At this time I have 2 repositories, one for Folder and another for
File, but it seems to me I should merge them together.
In DDD, you'd have a repository for each aggregate. This repository would be responsible for persisting all entities and value objects that are part of the aggregate.
I have my doubts about the location of the service. Should it be moved
to the domain layer?
IMO, an application service can be placed into the domain layer since it already serves as a facade and keeping them together would bring the benefits of cohesion. One thought about the IoService is that methods such as AddFile would usually be parameterized by aggregate identities as opposed to instances. Since the application service already references a repository, it can load the appropriate aggregates as needed. Otherwise, calling code would be responsible for calling the repository.
Should I use the service for creating the folder object. Or should the
service just use a factory, which have the responsibility of creating
the object and send the created object to the repository?
The IoService looks good as is except for the previous comment about being parameterized by identities rather than instances.
What about dependency injection in the service, should I inject my
services from the UI layer with IOC containers like Unity or should I
just hardcode the dependencies in the service?
This is a matter of preference. If you can benefit from using an IoC container then use it. However, don't use it just to use it. You are already doing dependency injection, just without a fancy IoC container.
SAMPLE
class File
{
public File(string name, Folder folder, FileData data, UserReference createdBy, IEnumerable<string> keywords = null)
{
//...
}
}
...
class Folder
{
public File AddFile(string name, FileData data, UserReference createdBy, IEnumerable<string> keywords = null)
{
var file = new File(name, this, data, createdBy, keywords)
this.Files.Add(file);
this.Updated = DateTime.UtcNow;
return file;
}
}
...
public void AddFile(UserReference userReference, Guid folderId, FileData data, string name, string title = "", IEnumerable<string> keywords = null, bool shared = false)
{
var folder = _folderRepository.Find(folderId);
if (folder == null)
throw new Exception();
folder.AddFile(name, data, keywords);
_folderRepository.InsertOrUpdate(folder);
_folderRepository.UnitOfWork.Save();
}
In this example, more of the behavior is delegated to the Folder aggregate and File entity. The application service simple calls the appropriate methods on the aggregate.

The given key was not present in the dictionary Plugin CRM 2011 online

Could anyone tell me what I am doing wrong, I've been trying for over a week now.
Follow the code.
Unexpected exception from plug-in (Execute):
Microsoft.Crm.Sdk.Samples.ProjectTotalAmount:
System.Collections.Generic.KeyNotFoundException: The given key was not
present in the dictionary.
namespace Microsoft.Crm.Sdk.Samples
{
public class ProjectTotalAmount : IPlugin
{
public void Execute(IServiceProvider serviceProvider)
{
Microsoft.Xrm.Sdk.IPluginExecutionContext context = (Microsoft.Xrm.Sdk.IPluginExecutionContext) serviceProvider.GetService(typeof(Microsoft.Xrm.Sdk.IPluginExecutionContext));
if (context.InputParameters.Contains("Target") &&
context.InputParameters["Target"] is Entity)
{
IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
//create a service context
var ServiceContext = new OrganizationServiceContext(service);
//ITracingService tracingService = localContext.TracingService;
Entity entity = (Entity)context.InputParameters["Target"];
if (entity.LogicalName == "new_project")
{
Guid projectGUID = ((EntityReference)entity["new_project"]).Id;
Entity a = service.Retrieve("new_project", ((EntityReference)entity["new_project"]).Id, new ColumnSet(true));
decimal totalAmount = 0;
try
{
//fetchxml to get the sum total of estimatedvalue
string new_amount_sum = string.Format(#"
<fetch distinct='false' mapping='logical' aggregate='true'>
<entity name='new_projectitem'>
<attribute name='new_amount' alias='new_amount' aggregate='sum' />
<filter type='and'>
<condition attribute='new_projectid' operator='eq' value='{0}' uiname='' uitype='' />
</filter>
</entity>
</fetch>", a.Id);
EntityCollection new_amount_sum_result = service.RetrieveMultiple(new FetchExpression(new_amount_sum));
foreach (var c in new_amount_sum_result.Entities)
{
totalAmount = ((Money)((AliasedValue)c["new_amount_sum"]).Value).Value;
}
//updating the field on the account
Entity acc = new Entity("new_project");
acc.Id = a.Id;
acc.Attributes.Add("new_amount", new Money(totalAmount));
service.Update(acc);
}
catch (FaultException ex)
{
throw new InvalidPluginExecutionException("An error occurred in the plug-in.", ex);
}
}
}
}
}
}
The settings for the plugin:
Post-validation
Synchronous execution mode
Server deployment
A few pointers to help you before we start looking at your code...
This error usually means your code is referring to an attribute that does not exist (or does not have a value)
You haven't said on which message your plugin is registered. This may affect the available parameters at runtime
You've commented out your tracingService variable but this can help you at least see how far your code has come. Reinstate it and add a few lines such as this to track your progress prior to the failure. This information will be written to the error log that is offered to you in the client side Exception dialog.:
tracingService.Trace("Project Id is {0}", projectGUID);`
and
tracingService.Trace("Number of returned records: {0}", new_amount_sum_result.Entities.Count);`
The following line seems entirely redundant since you are only using the attribute Id from a and this already exists as entity.Id:
Entity a = service.Retrieve("new_project", ((EntityReference)entity["new_project"]).Id, new ColumnSet(true));

Cannot create a contact in CRM 2011 Online using a plug-in

Below is the code I am using to create a contact in CRM 2011 online. It's not throwing any error but it also not creating any contact. I have registered the plugin on Post-Operation create event of the e-mail entity. I don't know if I am missing something. Any help would be appreciate.
public class RegistrationPlugin : IPlugin
{
private OrganizationServiceContext oContext;
public void Execute(IServiceProvider serviceProvider)
{
Microsoft.Xrm.Sdk.IPluginExecutionContext context = (Microsoft.Xrm.Sdk.IPluginExecutionContext)
serviceProvider.GetService(typeof(Microsoft.Xrm.Sdk.IPluginExecutionContext));
IOrganizationServiceFactory factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
IOrganizationService service = factory.CreateOrganizationService(context.UserId);
oContext = new OrganizationServiceContext(service);
//service.EnableProxyTypes();
if (context.InputParameters.Contains("Target") &&
context.InputParameters["Target"] is Entity)
{
try
{
Entity entity = (Entity)context.InputParameters["Target"];
if (entity.LogicalName == "email")
{
Guid _contactId;
var contact = new Contact()
{
FirstName = "Mary Kay",
LastName = "Andersen",
Address1_Line1 = "23 Market St.",
Address1_City = "Sammamish",
Address1_StateOrProvince = "MT",
Address1_PostalCode = "99999",
Telephone1 = "12345678",
EMailAddress1 = "marykay#contoso.com",
Id = Guid.NewGuid()
};
_contactId = contact.Id;
oContext.AddObject(contact);
}
}
catch (Exception x)
{
throw new Exception(x.ToString() + "\n" + x.InnerException.ToString());
}
}
}
}
I can see that you're missing one statement which is:
oContext.AddObject(contact);
oContext.SaveChanges(); // <= Saves the changes
It does solves the problem but it is now throwing another error:
Unhandled Exception: System.ServiceModel.FaultException`1[[Microsoft.Xrm.Sdk.OrganizationServiceFault, Microsoft.Xrm.Sdk, Version=5.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]]: Unexpected exception from plug-in (Execute): Microsoft.Crm.Sdk.Samples.RegistrationPlugin: System.Exception: Microsoft.Xrm.Sdk.SaveChangesException: An error occured while processing this request. ---> System.TypeLoadException: Inheritance security rules violated while overriding member: 'Microsoft.Crm.Services.Utility.DeviceRegistrationFailedException.GetObjectData(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)'. Security accessibility of the overriding method must match the security accessibility of the method being overriden.
at System.Reflection.RuntimeAssembly.GetExportedTypes(RuntimeAssembly assembly, ObjectHandleOnStack retTypes)
at System.Reflection.RuntimeAssembly.GetExportedTypes()
at Microsoft.Xrm.Sdk.KnownProxyTypesProvider.LoadKnownTypes(Assembly assembly)
at Microsoft.Xrm.Sdk.KnownProxyTypesProvider.RegisterAssembly(Assembly assembly)
at Microsoft.Xrm.Sdk.AssemblyBasedKnownProxyTypesProvider.GetTypeForName(String name, Assembly proxyTypesAssembly)
at..................
It seems to me a problem of rights. Can you suggest what I am missing now?
UPDATE: I solved the problem by adding OwnerID = new EntityReference("systemuser", context.UserId)
hmm, I think you don't need to complete the ID field, because when you will create it, the CRM will send you the ID.
Don't know if it could help you, cause I don't create a contact but an incident. But I think the process is the same. So I let you look.
private Guid createCase(IOrganizationService CrmService, Entity email)
{
ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
tracingService.Trace("Just to tracing my plugin");
/* CREATE AN ENTITY: incident here, but could be contact, account, ... */
Entity incident = new Entity("incident");
incident["title"] = email.Attributes["subject"].ToString();
incident["caseorigincode"] = new OptionSetValue(2);
EntityCollection ec = email.Attributes["from"] as EntityCollection;
Entity from = ec.Entities.FirstOrDefault();
incident["customerid"] = (EntityReference)from.Attributes["partyid"];
/* END */
tracingService.Trace("tracing 2.");
/* HERE YOU CREATE THE RECORD IN THE CRM */
Guid caseid = CrmService.Create(incident);
/* END */
tracingService.Trace("tracing 3. ID: "+ caseid.ToString());
return caseid;
}

sharepoint custom workflow activity is doing nothing, not even log messages

I am trying to create a custom workflow activity which gives me the list of recipients that I am storing in list. But once I deploy and start the workflow nothing is happening, not even log messages are coming. So i tried to debug the code but breakpoints are not set and I am getting the error "The Breakpoint will not currently be hit. No symbols have been loaded for this document." Can anyone please help me to deal with this issue.
Below are the steps I have followed in creating this activity.
1. created a workflow activity library.
(please find my code file attached)
added .dll to GAC
updated web.config and WSS.actions files.
Now I see the action in designer, so i have created a workflow using designer.
strted the workflow manually on an item.
Here nothing is happening, not even an error. Please let me know if you need any further information.
Please find the code below.
using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Collections;
using System.Drawing;
using System.Linq;
using System.Workflow.ComponentModel.Compiler;
using System.Workflow.ComponentModel.Serialization;
using System.Workflow.ComponentModel;
using System.Workflow.ComponentModel.Design;
using System.Workflow.Runtime;
using System.Workflow.Activities;
using System.Workflow.Activities.Rules;
using Microsoft.SharePoint;
using System.Diagnostics;
using Microsoft.SharePoint.Workflow;
using Microsoft.SharePoint.WorkflowActions;
namespace CustomWorkflowActivityLibrary
{
public partial class CustomWorkflowActivity: SequenceActivity
{
SPList _list;
private EventLog _log;
SPFieldUserValueCollection objUserFieldValueCol;
string semailsettingKeyword1;
string semailsettingKeyword2;
public CustomWorkflowActivity()
{
InitializeComponent();
}
public static DependencyProperty __ContextProperty = DependencyProperty.Register("__Context", typeof(WorkflowContext), typeof(CustomWorkflowActivity));
[DescriptionAttribute("__Context")]
[BrowsableAttribute(true)]
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
public WorkflowContext __Context
{
get { return ((WorkflowContext)(base.GetValue(CustomWorkflowActivity.__ContextProperty))); }
set { base.SetValue(CustomWorkflowActivity.__ContextProperty, value); }
}
public static DependencyProperty ListIdProperty = DependencyProperty.Register("ListId", typeof(string), typeof(CustomWorkflowActivity));
[DescriptionAttribute("ListId")]
[BrowsableAttribute(true)]
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
public string ListId
{
get { return ((string)(base.GetValue(CustomWorkflowActivity.ListIdProperty))); }
set { base.SetValue(CustomWorkflowActivity.ListIdProperty, value); }
}
public static DependencyProperty ListItemProperty = DependencyProperty.Register("ListItem", typeof(int), typeof(CustomWorkflowActivity));
[DescriptionAttribute("ListItem")]
[BrowsableAttribute(true)]
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
public int ListItem
{
get { return ((int)(base.GetValue(CustomWorkflowActivity.ListItemProperty))); }
set { base.SetValue(CustomWorkflowActivity.ListItemProperty, value); }
}
private void codeActivity1_ExecuteCode(object sender, EventArgs e)
{
}
protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
{
_log = new EventLog("Add Description");
_log.Source = "Share Point Workflows";
try
{
//Execute method as a elevated method
SPSecurity.CodeToRunElevated elevatedExecuteMethod = new SPSecurity.CodeToRunElevated(ExecuteMethod);
SPSecurity.RunWithElevatedPrivileges(elevatedExecuteMethod);
}
catch (Exception ex)
{
_log.WriteEntry("Error" + ex.Message.ToString(), EventLogEntryType.Error);
}
return ActivityExecutionStatus.Closed;
}
private void ExecuteMethod()
{
try
{
//retrieveing the Site object
SPSite _site = new SPSite(__Context.Site.Url);
//retrieveing the Web object
SPWeb _web = (SPWeb)(__Context.Web);
//retrieveing the list object
_list = _web.Lists[new Guid(this.ListId)];
//retrieveing the list item object
SPListItem _listItem = _list.GetItemById(this.ListItem);
_site.AllowUnsafeUpdates = true;
_web.AllowUnsafeUpdates = true;
string semailsubject = _listItem["E-Mail Subject"].ToString();
string semailfrom = _listItem["emailfrom"].ToString();
_log = new EventLog("get vendor info");
_log.WriteEntry("semailsubject");
_log.WriteEntry("semailfrom");
/* _listItem.Update();
_list.Update();
_site.AllowUnsafeUpdates = false;
_web.AllowUnsafeUpdates = false;*/
using (SPSite mysite = new SPSite("http://dlglobaltest.dl.com/Admin/IT/Application%20Development%20Group/LibraryEmailDistribution"))
{
using (SPWeb myweb = mysite.OpenWeb())
{
SPList settingsList = myweb.Lists["EmailDistributionSettings"];
SPQuery oQuery = new SPQuery();
oQuery.Query = "<Where><Eq><FieldRef Name='Sender' /><Value Type='Text'>" + semailfrom + "</Value></Eq></Where>";
SPListItemCollection ColListItems = settingsList.GetItems(oQuery);
foreach (SPListItem oListItem in ColListItems)
{
semailsettingKeyword1 = oListItem["Keyword1"].ToString();
semailsettingKeyword2 = oListItem["Keyword2"].ToString();
//SPFieldUserValue objUserFieldValue = new SPFieldUserValue(myweb, oListItem["Recipients"].ToString());
if ((semailsubject.Contains(semailsettingKeyword1)) || (semailsubject.Contains(semailsettingKeyword2)))
{
objUserFieldValueCol = new SPFieldUserValueCollection(myweb, oListItem["Recipients"].ToString());
_log = new EventLog(objUserFieldValueCol.ToString());
}
}
}
}
}
catch (Exception ex)
{ }
}
}
}
Web.Config:
<authorizedType Assembly="CustomWorkflowActivityLibrary, Version=1.0.0.0, Culture=neutral, PublicKeyToken=a95e146fc1062337" Namespace="CustomWorkflowActivityLibrary" TypeName="*" Authorized="True" />
WSS.Actions:
<Action Name="Get Recipients"
ClassName="CustomWorkflowActivityLibrary.CustomWorkflowActivity"
Assembly="CustomWorkflowActivityLibrary, Version=1.0.0.0, Culture=neutral, PublicKeyToken=a95e146fc1062337"
AppliesTo="all" Category="Custom">
<RuleDesigner Sentence="Get Recipients for %1 ">
<FieldBind Field="ListId,ListItem" Text="this list" Id="1" DesignerType="ChooseListItem" />
</RuleDesigner>
<Parameters>
<Parameter Name="__Context" Type="Microsoft.SharePoint.WorkflowActions.WorkflowContext" Direction="In" />
<Parameter Name="ListId" Type="System.String, mscorlib" Direction="In" />
<Parameter Name="ListItem" Type="System.Int32, mscorlib" Direction="In" />
</Parameters>
</Action>
Thanks,
I am not sure if this will help but you could try changing the following line in your code from this:
SPSecurity.RunWithElevatedPrivileges(elevatedExecuteMethod);
To this:
SPSecurity.RunWithElevatedPrivileges(delegate(){
ExecuteMethod();
});
Another shot-in-the-dark reply:
Try changing the class you're inheriting ( http://msdn.microsoft.com/en-us/library/ms173149(v=VS.80).aspx ) from SequenceActivity to Activity (SequenceActivity inherits from CompositeActivity, which itself inherits from Activity. See: http://msdn.microsoft.com/en-us/library/system.workflow.activities.sequenceactivity(v=VS.90).aspx )
If that doesn't work, try removing your constructor entirely. You should be able to use the base (Sequence)Activity constructor (since you're inheriting the class, not implementing it)
Hope that helps...

Resources