Executing CRM Workflow programmatically from an external application. CRM 4.0 using ExecuteWorkflowRequest

There is a method named ExecuteWorkflowRequest using which we can execute our workflow programmatically. We had a requirement to find all the opportunities which haven’t been modified for past 30 days and to decrease their probability attribute value by 10.

Now the thing over here was that there wasn’t any specific event against which we could have fired the above workflow. So we thought of writing an application which than we could scheduled, which will periodically run the above workflow

This is how we implemeneted it within a windows application

private void Form1_Load(object sender, EventArgs e){

CrmAuthenticationToken token = new CrmAuthenticationToken();

token.OrganizationName = “organizationName”;

//0 – AD

//1 – Passport

//2 – Form Authentication

token.AuthenticationType = 0;

CrmService crmService = new CrmService();

crmService.Credentials = System.Net.CredentialCache.DefaultCredentials;

crmService.CrmAuthenticationTokenValue = token;

crmService.Url = http://servername:port/mscrmservices/2007/crmservice.asmx”;


// Create an ExecuteWorkflow request.

ExecuteWorkflowRequest request = new ExecuteWorkflowRequest();

//Assign the ID of the workflow you want to execute to the request.

// use this query to get the id select parentworkflowid,name,* from dbo.Workflow

// id is the parentworkflowid

request.WorkflowId = new Guid(“21B9528D-D13D-4B93-9F91-FA7468D3C82C”);

// We want to run it against all the opportunity which are in open state

ArrayList OpportunityGuids = GetOpportunityGuids(crmService);

foreach (String oppGuid in OpportunityGuids){

//Assign the ID of the entity to execute the workflow on to the request.

request.EntityId = new Guid(oppGuid);

ExecuteWorkflowResponse response = (ExecuteWorkflowResponse)crmService.Execute(request);}

// Execute the workflow. }

catch (SoapException ex){

// write in log}

catch (Exception ex){

// write in log} }

private ArrayList GetOpportunityGuids(CrmService crmService){

// using QueryByAttribute to retrieve all the opportunity having statuscode as 1 i.e. Open

QueryByAttribute myOppQuery = new QueryByAttribute();

myOppQuery.Attributes = new String[] { “statuscode” };

myOppQuery.Values = new String[] {“1”};

ColumnSet myCols = new ColumnSet();

myOppQuery.ColumnSet = myCols;

myOppQuery.EntityName = EntityName.opportunity.ToString();

WindowsFormsApplication2.CrmSdk.BusinessEntityCollection myOppCollection= crmService.RetrieveMultiple(myOppQuery);

ArrayList opportunityGuids = new ArrayList();

foreach (WindowsFormsApplication2.CrmSdk.BusinessEntity opp in myOppCollection.BusinessEntities ){

opportunity myOpp = (opportunity)opp;

opportunityGuids.Add(myOpp.opportunityid.Value.ToString()); }

return opportunityGuids;


Bye ..

Error: The request failed with HTTP status 401 or Error 401.2: Unauthorized while using CrmService in ASP.NET or windows application CRM 4.0

To use CrmService or Metadata Service (CRM 4.0) within an ASP.NET page or a windows application we need to make use of CRM Authentication token.If we are using Active Directory Authentication this is the code for that

CrmAuthenticationToken token = new CrmAuthenticationToken();

token.OrganizationName = “organizationName”;

//0 – AD

//1 – Passport

//2 – Form Authentication

token.AuthenticationType = 0;

CrmService service = new CrmService();

service.Credentials =System.Net.CredentialCache.DefaultCredentials;

service.CrmAuthenticationTokenValue = token;

service.Url = http://servername:port/mscrmservices/2007/crmservice.asmx”;


WhoAmIRequest myReq = new CrmSdk.WhoAmIRequest();

WhoAmIResponse myResp = (CrmSdk.WhoAmIResponse)service.Execute(myReq);


catch (SoapException ex){



catch (Exception ex){



If we get the above unauthorized access error it could be because either there is problem in our CrmAuthenticationToken, may be we could have assigned wrong organization name or authentication type. If we are using CrmService in an ASP.NET page than we need to use impersonation.


<authentication mode=Windows/>

<identity impersonate=true/>


If we are using 2006 end point of CrmService we don’t have to use CrmAuthenticationToken.

FileUpload : Page Cannot be displayed and maximum request length exceeded error

By default, ASP.NET permits only files that are 4,096 kilobytes (KB) or less to be uploaded to the Web server.  To upload larger files, we must change the maxRequestLength parameter of the <httpRuntime> section in the Web.config file. By default, the <httpRuntime> element is set to the following parameters in the Machine.config file:









We can change the value of maxRequestLength to a desired value in our web.config of the application. For 10 mb we can set it to 10240 KB. Even in this case if user tries to upload a file with size more than 10 mb we than get the above “Page cannot be displayed error ” or the page simply hang up. In this case we can catch the error in the Application_Error event handler of the Global.asax file.

void Application_Error(object sender, EventArgs e)


if (System.IO.Path.GetFileName(Request.Path) == “Default.aspx”)


System.Exception appException = Server.GetLastError();

if (appException.InnerException.Message == “Maximum request length exceeded.”)



Response.Write(“The form submission cannot be processed because it exceeded the maximum length allowed by the Web administrator. Please resubmit the form with less data.”);

Response.Write(“<BR><a href=’Default.aspx’>Click Here to go back to page</a> </BR>”);

Response.End();  } } }

I tried with the above code, but it isn’t consistent.

The best solution for this could be to set the value of maxRequestLength to a very high value.

and checking in the code for the size.

Say changing the value to say 700mb ( not sure what the maximum length of request could be)

<httpRuntime useFullyQualifiedRedirectUrl=true



And checking for the length in your code

// Putting the constraint of 1 mb

if (FileUpload1.FileContent.Length < 1024){

FileUpload1.SaveAs(@”C:/MyFolder/” + FileUpload1.FileName);}



At least the above solution would save us from the page not displayed error.

And the last solution which i found was creating an httpmodule to intercept the web request.

using System;

using System.Collections.Generic;

using System.Text;

using System.Web;

namespace HAMModule{

public class MyModule : IHttpModule{

public void Init(HttpApplication app){

app.BeginRequest += new EventHandler(app_BeginRequest);


void app_BeginRequest(object sender, EventArgs e){

HttpContext context = ((HttpApplication)sender).Context;

// check for size if more than 4 mb

if (context.Request.ContentLength > 4096000){

IServiceProvider provider = (IServiceProvider)context;

HttpWorkerRequest wr = (HttpWorkerRequest)provider.GetService(typeof(HttpWorkerRequest));

// Check if body contains data

if (wr.HasEntityBody()){

// get the total body length

int requestLength = wr.GetTotalEntityBodyLength();

// Get the initial bytes loaded

int initialBytes = wr.GetPreloadedEntityBody().Length;

if (!wr.IsEntireEntityBodyIsPreloaded()){

byte[] buffer = new byte[512000];

// Set the received bytes to initial bytes before start reading

int receivedBytes = initialBytes;

while (requestLength – receivedBytes >= initialBytes){

// Read another set of bytes

initialBytes = wr.ReadEntityBody(buffer, buffer.Length);

// Update the received bytes

receivedBytes += initialBytes;


initialBytes = wr.ReadEntityBody(buffer, requestLength – receivedBytes);}}

// Redirect the user to an error page.


public void Dispose(){}


and add the following information to web.config


<add type=HAMModule.MyModule name=MyModule/>




The last solution worked properly!!!!

BeginRequest event –The BeginRequest event signals the creation of any given new request. This event is always raised and is always the first event to occur during the processing of a request.

Article on creating a custom http module



CallerOrigin property of Plugin Context

We had one of our workflow running on create of lead which was updating one of the attribute in the lead. When the workflow was updating the record one of our plugin registered on the post update event of the lead was getting triggered. This was resulting in an error , so we had to update the post update plugin to include the callerOrigin to handle the things properly

if (context.CallerOrigin.ToString() != “Microsoft.Crm.Sdk.AsyncServiceOrigin”)

////////// our logic


CallerOrigin -Using it we can determine the origin of the call. Possible Values are

Static Property Description
Application Gets the caller orgin for the application.
AsyncService Gets the caller orgin for the async service.
WebServiceApi Gets the caller orgin for the Web services.


Used SharedVariables in Microsoft Dynamics CRM 4.0

Today we wrote a plugin which was making use of new shared variables concept for plugin in Microsoft Dynamics CRM 4.0

We had one of our plugin registered in post create event of opportunity which was generating a unique number/id for that opportunity record (i.e auto-numbering).
Than we had to write one more plugin again for the same post create event of opportunity but in that plugin we wanted to access the value of that auto generated unique id.
So first what we did was changing the rank of the above two plugin i.e. execution order, if we are registering through plugin-registration tool.
For first plugin which used to generate the unique id we set the rank as 1
and for the second plugin we set it as 2.
But still we were not able to access the value of the unique id attribute in the second plugin.
Than we finally thought of making use of shared variables concept.

The SharedVariables property allows plug-ins to share data with each other. So the plugin which is getting fired first could put some data in the SharedVariables propertybag which than could be accessed by a plugin which is getting fired later.The order of execution of plugin depends on the rank set for it. However we should be careful of not creating too much dependencies among plug-ins.

So, in our first plugin we put the value in the shared variable
context.Properties.Add( new PropertyBagEntry(“MySharedVariable”, myAutoNumber));
and accessed it in the second plugin as following
String mySharedVariable = (string)context.[“MySharedVariable”];


SharePoint and Javascript

The following links explains how to use javascript within SharePoint

Using JavaScript to manipulate a list form field.


Hide a field from NewForm.aspx


Using Simple JavaScript in SharePoint


and few other links