Understanding Security Context in CRM 4 Workflow.


A “on demand” workflow runs under the security context of the user who ran that workflow using the “Run workflow” option.

In all other cases workflow would always run under the context of the user who owns that workflow.

Let’s take a simple example to understand this

Suppose this is our workflow, which is registered against lead entity and which runs while a lead record is created and can be run “on demand” as well. It updates one of the fields in the lead record.

wf1

The owner of the record is “Nishant Rana” i.e. me.
Now if i log into the CRM and create a new lead record. The workflow would get triggered and update the record.

Now if we check the properties we would find this

wf1 

Now suppose another user logs into CRM and creates a new lead record. The workflow would get triggered and it will update the lead record.

Here it would show the workflow owner’s name for the modified by field.

wf3

And if the same user is running the workflow manually using “Run Workflow” option, the modified by would get updated with the uuser’s name and not the owner of the workflow.

wf4

Bye..

Sample code for TargetCompoundSalesOrder and CompoundCreate Message


Just a sample code on how we can use the above classes

// retrieve the sales order class
TargetRetrieveSalesOrder targetSalesOrder =
 new TargetRetrieveSalesOrder();
targetSalesOrder.EntityId =
new Guid("guid");
RetrieveRequest myRReq = new RetrieveRequest();
myRReq.ColumnSet = new AllColumns();
myRReq.Target = targetSalesOrder;
RetrieveResponse myRRes = (RetrieveResponse)service.Execute(myRReq);
salesorder mySalesOrder =(salesorder)myRRes.BusinessEntity;
// setting guid to null else duplicate key error
mySalesOrder.salesorderid = null;
// retrieve all the sales order detail for the sales order
ConditionExpression expression = new ConditionExpression();
expression.AttributeName = "salesorderid";
expression.Operator = ConditionOperator.Equal;
expression.Values =
 new string[] { "guid" };
FilterExpression expression2 = new FilterExpression();
expression2.FilterOperator = LogicalOperator.And;
expression2.Conditions = new ConditionExpression[] { expression };
QueryExpression query = new QueryExpression();
query.EntityName = EntityName.salesorderdetail.ToString();
query.ColumnSet = new AllColumns();
query.Criteria = expression2;
BusinessEntityCollection entitys = service.RetrieveMultiple(query);
salesorderdetail[] salesDetail=
new salesorderdetail[entitys.BusinessEntities.Length];
int i = 0;
foreach(BusinessEntity be in entitys.BusinessEntities)
{
salesDetail[i] =(salesorderdetail) be;
salesDetail[i].salesorderdetailid = null;
i++;
}
// initialize and set properties for TargetCompoundSalesOrder class
TargetCompoundSalesOrder tcSalesOrder =
new TargetCompoundSalesOrder();
tcSalesOrder.SalesOrder = mySalesOrder;
tcSalesOrder.SalesOrderDetails = salesDetail;
// use CompoundCreateRequest class
CompoundCreateRequest ccReq = new CompoundCreateRequest();
ccReq.Target = tcSalesOrder;
CompoundCreateResponse ccRes =
(CompoundCreateResponse)service.Execute(ccReq);

Bye..

Advertisements

Clone Records in CRM


was just looking for different ways we can clone a record in CRM.

These are the different articles that i found :-

Cloning records through an ASP.NET page

http://blogs.inetium.com/blogs/microsoftcrm/archive/2009/04/27/cloning-records-in-microsoft-crm-4-0-using-ajax-controls.aspx

Cloning records without any code by making use of self-referential relationship and mapping

http://rc.crm.dynamics.com/rc/regcont/en_us/op/articles/cloneRecords.aspx

Cloning records through workflow

http://www.dynamicscrmtrickbag.com/2009/08/29/clone-workflow/

Cloning records through JavaScript

http://ronaldlemmen.blogspot.com/2007/05/clone-record.html

And below is the code which i have used to clone Sales Order with all related sales order details

public void CloneSalesOrder(string salesOrderId, CrmService crmService)
{
Guid id = new Guid(salesOrderId);
// get all the attributes values using AllColumns
salesorder originalSalesOrder = (salesorder)crmService.
Retrieve(EntityName.salesorder.ToString(), id, new AllColumns());
salesorder cloneSalesOrder = new salesorder();
// assign the original sales order to the cloned one
cloneSalesOrder = originalSalesOrder;
cloneSalesOrder.name = "Cloned SalesOrder";
// set sales order id and order number as null
cloneSalesOrder.salesorderid = null;
cloneSalesOrder.ordernumber = null;
TargetCreateSalesOrder order = new TargetCreateSalesOrder();
order.SalesOrder = cloneSalesOrder;
CreateRequest request = new CreateRequest();
request.Target = order;
CreateResponse response = (CreateResponse)crmService.Execute(request);
// clone all the line items as well
CloneSalesOrderLineItems(salesOrderId, response.id.ToString(),
crmService);
}
private void CloneSalesOrderLineItems(string objPoId, string
objClonedPoId, CrmService service)
{
CrmService crmService = service;
//Retrieve all the sales order details from the original sales
//order record
ConditionExpression expression = new ConditionExpression();
expression.AttributeName = "salesorderid";
expression.Operator = ConditionOperator.Equal;
expression.Values = new string[] { objPoId.Trim() };
FilterExpression expression2 = new FilterExpression();
expression2.FilterOperator = LogicalOperator.And;
expression2.Conditions = new ConditionExpression[] { expression };
QueryExpression query = new QueryExpression();
query.EntityName = EntityName.salesorderdetail.ToString();
query.ColumnSet = new AllColumns();
query.Criteria = expression2;
BusinessEntityCollection entitys = crmService.RetrieveMultiple(query);
if (entitys != null)
{
// one by one create sales order detail record and set its sales
//order id as the new cloned record id
foreach (salesorderdetail salesorderdetail in entitys.BusinessEntities)
{
salesorderdetail salesorderdetail2 = new salesorderdetail();
salesorderdetail2 = salesorderdetail;
Guid guid = new Guid(objClonedPoId);
salesorderdetail2.salesorderid = null;
salesorderdetail2.salesorderdetailid = null;
Lookup lookup = new Lookup();
lookup.Value = guid;
salesorderdetail2.salesorderid = lookup;
salesorderdetail2.salesorderid.Value = lookup.Value;
TargetCreateSalesOrderDetail detail = new
TargetCreateSalesOrderDetail();
detail.SalesOrderDetail = salesorderdetail2;
CreateRequest request = new CreateRequest();
request.Target = detail;
CreateResponse response = (CreateResponse)crmService.Execute(request);
}
}
}

 

Bye..

ForceSubmit and Plug-In in CRM


Hi,

We had been facing one issue over here, it was regarding a particular field’s value getting set to blank on updating the SalesOrder record in CRM.

This used to occur when we were updating that record from within our SharePoint application which was using CrmService. However from within CRM, things were working absolutely fine.

After spending lot of time on that we realized that it was because of using ForceSubmit on that field/attribute.

If we are working from within the form in CRM, the value for that field would be passed to our plugin’s inputparameter, even if its value hasn’t been modified, in case of update event.

However if the record is getting updated using CrmService from an external application, the ForceSubmit thing won’t work as it is defined at form level, so the value for that field wouldn’t get passed. Its value will be passed only if that field’s value is modified.

So in our case we than modified our code to use Retrieve method to get that field’s value.

Bye..

Context’s InputParameters and InvalidPluginExecutionException


Hi,

This is something peculiar i found while throwing the InvalidPluginExecutionException for a pre-update plugin.

In our plugin as usual we will first convert the Target InputParameter property to DynamicEntity,

DynamicEntity entity = (DynamicEntity)context.InputParameters.Properties["Target"];

Ideally for a pre-update event, the inputparameters should contain only those attributes whose values have been modified.

For e.g. if i change the value for Salutation and FirstName field in the Contact form, i will get the following attributes in the InputParameter.

input

However if we throw InvalidPluginExecutionException and try to save the form again, we would receive almost all the attributes passed into inputparameters property bag.

input1

This is something we should be aware of while using InvalidPluginExectuionException.

Bye..

The query cannot be run for the following DataObject: InfoPath cannot run the specified query. Access is denied


Hi,

we got the above error while using a Web Service as a data connection.

This is the step we followed to resolve it

Go to Tools–>Form Options–>Select “Security and Trust ” and set it to “Full Trust”.

Bye..