接触过CRM2011的同学们肯定考虑过这样的一个问题,就是我们CRM系统中的那些实体能否通过外部开发工具,比如VS2010来获取呢?更深一步的说,我们能否获取Workflow实体的所有数据,然后在VS2010中,通过程序来执行获取数据的Workflow?答案是肯定的。经过整理,我把整个实现过程和大家分享下。
下图是我的CRM系统中定义的所有的工作流,那么我们可以在VS2010中通过一个DataGridView控件来绑定取出的这些数据。
(图1)
主要的实现代码及步骤如下:
第一步, 首先当然是要配置下参数,以便连接到我们的CRM Server,
我设置了如下几个重要的配置参数,
Static string _discoveryServer = @"crmServerName"; //这个是服务器的机器名
Static string _orgName = "OrganzaitonName"; // CRM的Organization名字
Static string _domain = "domainName"; //你的域名
Static string _username = "username"; //服务器用户名
Static string _password = "******"; //服务器密码
第二步,参数设置完毕之后,然后就要建立连接,代码如下
ServerConnection serverConnect = new ServerConnection();
ServerConnection.Configuration serverConfig = serverConnect.GetServerConfiguration(_discoveryServer, _orgName, _username, _password, _domain);
// connect to the Organization service.
// this statement is required to enable early-bound type support.
_serviceProxy = new OrganizationServiceProxy (serverConfig.OrganizationUri,
serverConfig.HomeRealmUri,
serverConfig.Credentials,
serverConfig.DeviceCredentials));
这个serverConfig.OrganizationUri取到的值是经过我处理的,他应该是这样的http://{服务器的机器名}/XRMServices/2011/Discovery.svc。
这里我写了一个单独的ServerConnection 类去调用我们设置的参数,当然我们设置的连接参数也可以作为一个单独的XML文件去配置,然后通过读取XML取得设置的参数。这儿为了方便,我就直接在代码里面定义死了。
好了,这样就建立好了我们的连接,需要说明的是,这里面我们用到了一个OrganizationServiceProxy 类,这个类的命名空间是通过引用我们第三方的Dll生成的。CRM SDK里面有提供这些DLL,我列举下主要用到的DLL(如下图),你们可以去网上下载。
(图2)
对应命名空间写法是:
Using Microsoft.Xrm.Sdk;
Using Microsoft.Xrm.Portal;
Using Microsoft.Xrm.Client;
第三步 ,连接建立成功后,我们当然要去取数据啦。下面的代码就是取出
CRM 中所有激活状态workflow 的数据列表,并显示在DataGridview中。
// Retrieve the workflow.
QueryExpression entityQuery = new QueryExpression("workflow");
entityQuery.ColumnSet = new ColumnSet (new String [] {"name", "workflowid", "primaryentity", "activeworkflowid" });
entityQuery.Criteria = new FilterExpression (LogicalOperator.And); //这个地方我们可以通过它的And条件去找出我们激活状态的workflow数据
entityQuery.Criteria.AddCondition ("parentworkflowid", ConditionOperator.Null, null);
entityQuery.Criteria.AddCondition ("activeworkflowid", ConditionOperator.NotNull, null); //既然是激活状态,设置搜索条件当然是activeworkflowid 不能是Null啦。
DataCollection<Entity> workFlowCollection = _serviceProxy.RetrieveMultiple (entityQuery).Entities;
DataTable dt = new DataTable ("temptable");
dt.Columns.Add ("ID", typeof(int));
dt.Columns.Add ("workflowid", typeof (string));
dt.Columns.Add ("name", typeof(string));
dt.Columns.Add ("primaryentity", typeof (string));
int i = 0;
foreach (Entity entity in workFlowCollection)
{
i = i + 1;
string name = entity ["name"].ToString ();
String id = entity ["workflowid"].ToString ();
string primaryentity = entity["primaryentity"].ToString ();
DataRow dr = dt.NewRow ();
dr ["ID"] = i;
dr ["workflowid"] = id;
dr ["name"] = name;
dr ["primaryentity"] = primaryentity;
dt.Rows.Add (dr);
}
//binding the workflow data.
dataGridView1.DataSource = dt;
好了实现绑定之后,我们执行这个方法的时候,自然会把CRM数据列表中的数据显示在DataGridView中啦。
执行结果如下,我只取了四个重要的字段:分别是我wokflowid,name,primaryentity。
取出数据的结果如下图所示。通过工作流的name我们不难和上面图1中我列出在CRM中看到的数据是一致的。
(图3)
下面我们再做件事情,就是当点击每一行时,能把这行Workflow关联的所有Entity的数据在新的DataGridView中显示出来。代码就不多写了。和取工作流所有数据的代码步骤一样的。只是Entity的name是我们Workflow中的primayentity值而已。
string entityObjectName = dataGridView1.Rows[e.RowIndex].Cells["primaryentity"].Value.ToString ();
然后把这个entity的名字传给QueryExpression对象就可以啦。
QueryExpression entityQuery = new QueryExpression (entityObjectName);
接下来的代码和取workflow是一样的。执行后将会把这条entity的所有数据都显示出来,结果如下图所示。
当我们选中名字是'Test3'的workflow时,关联的所有entity数据都显示了出来,这里我们要取的最重要的一个数据就是Entityid和workflowid,因为最后一步我们要执行这条记录的工作流。我们只需要传递两个参数就可以执行了。这两个参数就是Entityid和workflowid。
执行工作流的代码如下:
// Create an ExecuteWorkflow request.
ExecuteWorkflowRequest request = new ExecuteWorkflowRequest ()
{
WorkflowId = WorkflowId,
EntityId = EntityId
};
// execute the workflow.
ExecuteWorkflowResponse response = (ExecuteWorkflowResponse) _serviceProxy.Execute (request);
执行工作流得代码很简单,一个request传入两个参数,然后response就可以执行我们要的结果啦!
这儿我们执行刚才名字是'Test3'的workflow。
去CRM系统中查看执行记录发现,被工作流被执行了。
下图中2012年11月1日建立的日期记录就是刚被执行触发的。
大功告成!