Tag Cloud

CRM 2011 (161) CRM 4.0 (144) C# (116) JScript (109) Plugin (92) Registry (90) Techpedia (77) PyS60 (68) WScript (43) Plugin Message (31) Exploit (27) ShellCode (26) FAQ (22) JavaScript (21) Killer Codes (21) Hax (18) VB 6.0 (17) Commands (16) VBScript (16) Quotes (15) Turbo C++ (13) WMI (13) Security (11) 1337 (10) Tutorials (10) Asp.Net (9) Safe Boot (9) Python (8) Interview Questions (6) video (6) Ajax (5) VC++ (5) WebService (5) Workflow (5) Bat (4) Dorks (4) Sql Server (4) Aptitude (3) Picklist (3) Tweak (3) WCF (3) regex (3) Config (2) LINQ (2) PHP (2) Shell (2) Silverlight (2) TSql (2) flowchart (2) serialize (2) ASHX (1) CRM 4.0 Videos (1) Debug (1) FetchXml (1) GAC (1) General (1) Generics (1) HttpWebRequest (1) InputParameters (1) Lookup (1) Offline Plug-ins (1) OutputParameters (1) Plug-in Constructor (1) Protocol (1) RIA (1) Sharepoint (1) Walkthrough (1) Web.config (1) design patterns (1) generic (1) iframe (1) secure config (1) unsecure config (1) url (1)

Pages

Sunday, April 21, 2013

CRM 4.0 Relationships Explained

Relationships in CRM 4.0 are quite powerful but hard to understand at first. There are so many moving parts tied to so many places that it is sometimes difficult to predict what the actual outcome is. So here is my attempt to explain a bit further what the relationships enhancements were in CRM 4.0. To start with let’s explain with a diagram what relationship types are available. Note that to determine the actual feasibility of a relationship (e.g. it may be the case that a specific relationship is not possible between an entity pair) you can use our APIs.

One-to-Many System-System (1:N)

In MSCRM 4.0 you can link system entity to another system entity. The child system entity has a lookup field to associate it with a parent system entity.

Self-Referential

In CRM 4.0 you can link An entity to itself. For example a Case can be linked to a master Case.

Multiple Relationships Between Entities

Many of you know about mulitple lookups issues with same entity, now it can be achieved in MS CRM 4.0 e.g the Account entity might have two relationships with a Contact entity – a primary and secondary Contact.

Many-to-Many System-System, System-Custom and Custom-Custom (N:N)

In MSCRM 4.0 this is major requirement for many to many relationship, now it is possible . Not only will this remove the need to build a “joining” entity, but you have control over how the relationships show up in the CRM UI.

Relationships CRM 4.0

Backend

The major architectural changes were that we introduced the notion of many-to-many relationships and self referential relationships. To enable many-to-many relationships we implement intersect entities under the covers. To enable self referential relationships we added a couple of checks to prevent circular parental references and we also redid portions of several system relationships that were hardcoded to be metadata driven to enable system to system and multiple relationships.

Programmability

Of course we had to provide means for programmers to take advantage of all the niceties that we implemented so we had to introduce a couple of new message and attributes and make some changes in the way fetchXml process relationships. Details are on the SDK but here are a couple of quick examples.

Creating new relationships

Yep, you can create brand new relationships (metadata) programmatically using the metadata API. Here is an example on how to create a Many-to-Many relationship. The CrmUtils class is just a wrapper class that a colleague created to create a label for only one language, 1033-English in this case (as you know CRM 4.0 is Multi Language enabled).

public static void addRelatedTest(TitanMiscTests.CrmSdk.CrmService service)
{
//Links (relates) an account record to a lead record in a manyToMany relationship
Moniker moniker1 = new Moniker();
moniker1.Name = "account";
moniker1.Id = new Guid("4BD77CC1-8D6B-DC11-B026-0017A41E8C1D");
Moniker moniker2 = new Moniker();
moniker2.Name = "lead";
moniker2.Id = new Guid("D1CAB380-C56B-DC11-B026-0017A41E8C1D");
AssociateEntitiesRequest request = new AssociateEntitiesRequest();
request.Moniker1 = moniker1;
request.Moniker2 = moniker2;
request.RelationshipName = "new_account_lead_custom";
service.Execute(request);
}

Adding/Removing records for a relationship

To add a new record to a many-to-many relationship you can use the following code. A similar code can be used to remove a record, just use DisassociateEntities message request/response instead of AssociateEntities.

Note that working with N:N relationships is slightly different than working with a One-to-many relationship (for the later you use SetRelated and RemoveRelated messages instead).

    public static void addRelatedTest(TitanMiscTests.CrmSdk.CrmService service)
{
//Links (relates) an account record to a lead record in a manyToMany relationship
Moniker moniker1 = new Moniker();
moniker1.Name = "account";
moniker1.Id = new Guid("4BD77CC1-8D6B-DC11-B026-0017A41E8C1D");
Moniker moniker2 = new Moniker();
moniker2.Name = "lead";
moniker2.Id = new Guid("D1CAB380-C56B-DC11-B026-0017A41E8C1D");
AssociateEntitiesRequest request = new AssociateEntitiesRequest();
request.Moniker1 = moniker1;
request.Moniker2 = moniker2;
request.RelationshipName = "new_account_lead_custom";
service.Execute(request);
}

Retrieving relationships

The following fetch will retrieve all the leads associated with account with name “Foo” in the custom relationship whose intersect entity is “new_account_lead_custom”.

   public static void retrieveEntitiesViaFetch(TitanMiscTests.CrmSdk.CrmService service)
{
string linkFetch = @"











";
string result = service.Fetch(linkFetch);
Console.WriteLine(result);
}

The same query can be accomplished using QueryExpression as follows, note how the query is constructed from bottom to top when compared with fetchXml.


public static void retrieveEntityListFromManyToMany(TitanMiscTests.CrmSdk.CrmService service)
{
//This code will retrieve a list of "leads" associated with the entity "Foo" on the relationship whose intersect entity is "new_account_lead_custom"
//Filter by the specific record that we are looking for
//(In this example we assume that there are no other accounts with the name Foo, otherwise
// if would be recommended to use the account "id" instead of the name.
ConditionExpression conditionName = new ConditionExpression();
conditionName.AttributeName = "name";
conditionName.Operator = ConditionOperator.Equal;
conditionName.Values = new object[1];
conditionName.Values[0] = "Foo";
FilterExpression selectByName = new FilterExpression();
selectByName.Conditions = new ConditionExpression[] { conditionName };
//Create nested link entity and apply filter criteria
LinkEntity nestedLinkEntity = new LinkEntity();
nestedLinkEntity.LinkToEntityName = "account";
nestedLinkEntity.LinkFromAttributeName = "accountid";
nestedLinkEntity.LinkToAttributeName = "accountid";
nestedLinkEntity.LinkCriteria = selectByName;
//Create the nested link entities
LinkEntity intersectEntity = new LinkEntity();
intersectEntity.LinkToEntityName = "new_account_lead_custom";
intersectEntity.LinkFromAttributeName = "leadid";
intersectEntity.LinkToAttributeName = "leadid";
intersectEntity.LinkEntities = new LinkEntity[] { nestedLinkEntity };
//Create Query expression and set the entity type to lead
QueryExpression expression = new QueryExpression();
expression.EntityName = "lead";
expression.LinkEntities = new LinkEntity[] { intersectEntity };
RetrieveMultipleRequest request = new RetrieveMultipleRequest();
request.Query = expression;
//Execute and examine the response
RetrieveMultipleResponse response = (RetrieveMultipleResponse)service.Execute(request);
BusinessEntity[] entities=response.BusinessEntityCollection.BusinessEntities;
Console.WriteLine("Total related=" + entities.Length);
}

Migration and Upgrade Microsoft Dynamics CRM 4.0 to 2011

Solution Management

The concept is quite powerful as it allows components to be layered on to the base system but also on top of other solutions (i.e. when there are inter-dependencies). It also provides a way to protect the intellectual property of the components in your solution and includes change management and versioning.

Plug-In Transaction Support

In CRM 4.0 you could register a plug-in to run either before (pre-event) or after (post-event) the CRM platform operation. However, you were not able to run as part of the transaction itself, so you had to write your own compensation logic in the event the CRM platform operation failed. CRM 5.0 addresses this limitation, and you can now choose to register you plug-in as part of the platform operation. The CRM 5.0 plug-in registration tool has been modified to support this.

Automatic Plug-In Profiling

CRM 5.0 will keep track of how a plug-in is executing, what resources it consumes, if it is causing unexpected exceptions and whether or not it is violating security constraints. If a particular plug-in fails a number of times it is automatically disabled from executing, helping to maintain system integrity.

ADO.Net Data Services and .Net RIA services support

Enables an easier data access for web applications, AJAX and Silverlight

Workflow Up gradation

Workflows in CRM 4.0 will be migrated automatically to CRM 5.0 as part of the upgrade process.

Running workflow instances in CRM 4.0 will resume at the point they were stopped once the upgrade process has completed.

Custom workflow activities written for CRM 4.0 will continue to run in CRM 5.0 after migration, and will be wrapped by the new WF interop activity.

Also can replace Plug Ins by Workflow since workflows provides Pre and Post Image as wells as Input and Output parameter in Workflow Context.

Claims based Authentication and Federation

CRM 5.0 will enable us to integrate transparently authentication with other applications either On-Premise or on the Cloud.

Unstructured Relationships

CRM 5.0 allows you to define ad-hoc relationships between any two entities.

Team Ownership

Entities in CRM 4.0 were either User Owned or Organization Owned. Now Team Owned entities are added in CRM5, and integrated into the role-based security model.

Native SharePoint Integration

Integration with Windows SharePoint Services for document management, which includes site and document library provisioning, document metadata, item security, and check-in/check-out capabilities.

Others

User friendly analytical tool which includes new dashboards.

Tighter integration with Outlook

Download an Attachment

The following code example demonstrates how to download an attachment programmatically. This technique is demonstrated for a note (annotation), an e-mail attachment (activitymimeattachment), and for a sales literature item. You can use the same technique for downloading an e-mail template.


//CRM4.0: Download an Attachment
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.IO;
using Microsoft.Crm.Sdk.Utility;
using System.Web.Services.Protocols;

namespace Microsoft.Crm.Sdk.HowTo
{
// Use the following Microsoft Dynamics CRM namespaces in the sample.
using CrmSdk;

class DownloadAttachment
{
static void Main(string[] args)
{
bool success = false;
try
{
// TODO: Change the service URL and organization to match your Microsoft Dynamics
// CRM server installation. A value of String.Empty for the service URL indicates
// to use the default service URL defined in the WSDL.
success = DownloadAttachment.Run("http://localhost:5555", "CRM_Organization");
}
catch (SoapException ex)
{
Console.WriteLine("The application terminated with an error.");
Console.WriteLine(ex.Message);
Console.WriteLine(ex.Detail.InnerText);
}
catch (System.Exception ex)
{
Console.WriteLine("The application terminated with an error.");
Console.WriteLine(ex.Message);

// Display the details of the inner exception.
if (ex.InnerException != null)
{
Console.WriteLine(ex.InnerException.Message);

SoapException se = ex.InnerException as SoapException;
if (se != null)
Console.WriteLine(se.Detail.InnerText);
}
}
finally
{
Console.WriteLine("Completed successfully? {0}", success);
Console.WriteLine("Press to exit.");
Console.ReadLine();
}
}

public static bool Run(string crmServerUrl, string orgName)
{

bool success = false;

try
{
// Set up the CRM Service.
CrmService service = CrmServiceUtility.GetCrmService(crmServerUrl, orgName);
// Cache credentials so each request does not have to be authenticated again.
service.PreAuthenticate = true;

#region Setup Data Required for this Sample

// Create the root account.
Guid setupAnnotationId = Guid.Empty;
Guid setupEmailAttachmentId = Guid.Empty;
Guid setupEmailId = Guid.Empty;
Guid setupSalesLiteratureId = Guid.Empty;
Guid setupSalesLiteratureItemId = Guid.Empty;

// Create the annotation record.
annotation setupAnnotation = new annotation();
setupAnnotation.subject = "Example Annotation Attachment";
setupAnnotation.filename = "ExampleAnnotationAttachment.txt";
setupAnnotation.documentbody = "Sample Annotation Text";
setupAnnotationId = service.Create(setupAnnotation);

// Create the e-mail record.
email setupEmail = new email();
setupEmail.subject = "Example email";
setupEmail.torecipients = "unknown@example.com";
setupEmail.description = "This is an example email.";
setupEmailId = service.Create(setupEmail);

// Create the activitymimeattachment record for an e-mail attachment.
activitymimeattachment setupEmailAttachment = new activitymimeattachment();
setupEmailAttachment.subject = "Example Email Attachement";
setupEmailAttachment.filename = "ExampleEmailAttachment.txt";
setupEmailAttachment.body = "Some Text";
setupEmailAttachment.mimetype = "text/plain";
setupEmailAttachment.attachmentnumber = new CrmNumber();
setupEmailAttachment.attachmentnumber.Value = 1;
setupEmailAttachment.activityid = new Lookup();
setupEmailAttachment.activityid.type = EntityName.email.ToString();
setupEmailAttachment.activityid.Value = setupEmailId;
setupEmailAttachmentId = service.Create(setupEmailAttachment);

// Create the salesliterature record.
salesliterature attachment3 = new salesliterature();
attachment3.name = "Example SalesLiterature";
attachment3.hasattachments = new CrmBoolean();
attachment3.hasattachments.Value = true;
setupSalesLiteratureId = service.Create(attachment3);

// Create the salesliteratureitem record for an attachment to salesliterature.
salesliteratureitem attachementItem3 = new salesliteratureitem();
attachementItem3.title = "Example sales literature attachment";
attachementItem3.filename = "ExampleSalesLiteratureAttachment.txt";
attachementItem3.documentbody = "Example sales literature text.";
attachementItem3.mimetype = "text/plain";
attachementItem3.salesliteratureid = new Lookup();
attachementItem3.salesliteratureid.type = EntityName.salesliterature.ToString();
attachementItem3.salesliteratureid.Value = setupSalesLiteratureId;
setupSalesLiteratureItemId = service.Create(attachementItem3);

#endregion

#region How to download attachment from annotation record

// SDK: annotationId = new Guid("{bee08735-09d3-de11-9d71-00155da4c706}");
Guid annotationId = setupAnnotationId;

// Define the columns to retrieve from the annotation record.
ColumnSet cols1 = new ColumnSet();
cols1.Attributes = new string[] { "filename", "documentbody" };

// Retrieve the annotation record.
annotation annotationAttachment = (annotation)service.Retrieve(EntityName.annotation.ToString(), annotationId, cols1);

// Download the attachment in the current execution folder.
using (FileStream fileStream = new FileStream(annotationAttachment.filename, FileMode.OpenOrCreate))
{
byte[] fileContent = new UTF8Encoding(true).GetBytes(annotationAttachment.documentbody);
fileStream.Write(fileContent, 0, fileContent.Length);
}

#endregion

#region How to download attachment from activitymimeattachment record

// SDK: emailAttachmentId = new Guid("{c1e08735-09d3-de11-9d71-00155da4c706}");
Guid emailAttachmentId = setupEmailAttachmentId;

// Define the columns to retrieve from the activitymimeattachment record.
ColumnSet cols2 = new ColumnSet();
cols2.Attributes = new string[] { "filename", "body" };

// Retrieve the activitymimeattachment record.
activitymimeattachment emailAttachment = (activitymimeattachment)service.Retrieve(EntityName.activitymimeattachment.ToString(), emailAttachmentId, cols2);

// Download the attachment in the current execution folder.
using (FileStream fileStream = new FileStream(emailAttachment.filename, FileMode.OpenOrCreate))
{
// byte[] fileContent = Convert.FromBase64String(emailAttachment.body);
byte[] fileContent = new UTF8Encoding(true).GetBytes(emailAttachment.body);
fileStream.Write(fileContent, 0, fileContent.Length);
}

#endregion

#region How to download attachment from salesliterature record

// SDK: salesLiteratureId = new Guid("{a836993e-09d3-de11-9d71-00155da4c706}");
Guid salesLiteratureId = setupSalesLiteratureId;

// Search for all the salesliteratureitem records that belong
// to the specified salesliterature record.
BusinessEntityCollection entities = null;
salesliteratureitem entity = null;

// Create the query for search.
QueryExpression query = new QueryExpression();
query.EntityName = EntityName.salesliteratureitem.ToString();

// Define the columns to retrieve from the salesliteratureitem record.
ColumnSet cols3 = new ColumnSet();
cols3.Attributes = new string[] { "filename", "documentbody", "title" };

// Set the filter condition to query.
ConditionExpression condition = new ConditionExpression();
condition.AttributeName = "salesliteratureid";
condition.Values = new string[1] { salesLiteratureId.ToString() };
condition.Operator = ConditionOperator.Equal;
FilterExpression filter = new FilterExpression();
filter.Conditions = new ConditionExpression[] { condition };

query.ColumnSet = cols3;
query.Criteria = filter;

// Retrieve the salesliteratureitem records.
entities = service.RetrieveMultiple(query);

// Check for the retrieved salesliteratureitem count.
if (entities.BusinessEntities.Length != 0)
{
for (int i = 0; i < entities.BusinessEntities.Length; i++)
{
entity = (salesliteratureitem)entities.BusinessEntities[i];

// Download the attachment in the current execution folder.
using (FileStream fileStream = new FileStream(entity.filename, FileMode.OpenOrCreate))
{
byte[] fileContent = new UTF8Encoding(true).GetBytes(entity.documentbody);
fileStream.Write(fileContent, 0, fileContent.Length);
}
}
}

#endregion

#region check success

// Verify that there are attachments.
if (annotationAttachment.filename != null && emailAttachment.filename != null
&& entity.filename != null)
{
success = true;
Console.WriteLine(
"The following files were downloaded to the executable folder:\n {0}\n {1}\n {2}\n",
annotationAttachment.filename, emailAttachment.filename, entity.filename);
}
#endregion

#region Remove Data Required for this Sample

service.Delete(EntityName.annotation.ToString(), setupAnnotationId);
service.Delete(EntityName.activitymimeattachment.ToString(), setupEmailAttachmentId);
service.Delete(EntityName.email.ToString(), setupEmailId);
service.Delete(EntityName.salesliteratureitem.ToString(), setupSalesLiteratureItemId);
service.Delete(EntityName.salesliterature.ToString(), setupSalesLiteratureId);

#endregion

}
catch
{
// You can handle an exception here or pass it back to the calling method.
throw;
}

return success;
}

}
}

Saturday, April 20, 2013

Introduction to Microsoft Dynamics CRM 2011 Plugins

Introduction

Whenever we need to extend the OOB functionality of Microsoft Dynamics CRM 2011. We can write custom plugins which can run before an event performs it operations and after an event completes its operations. It can be executed synchronously or asynchronously from managed queue. With the help, can perform data validations; integrate with other legacy applications, auto number generations and writing complex business logic. We can write custom plugin in Microsoft .net 4.0 framework writing code in Microsoft C# or VB .net.

 

We can register the Plugin or custom workflow activity using Plugin Registration tool. It can be registered in online and offline mode [Microsoft Dynamics CRM for Outlook with offline access client]. However, registering custom workflow activities with Microsoft Dynamics CRM Online is not supported using the registration tool.

 

The Plug-in Registration tool is provided as a source code sample in the Tools folder of the Microsoft Dynamics CRM SDK download. Review the instructions provided in the Tools/Plugin Registration/Readme.docx file for more information about the tool and instructions on how to build the tool.

 

Framework

The Microsoft Dynamics CRM 2011 event processing subsystem executes plug-ins based on a message pipeline execution model. A user action or an SDK method call or other application results in a message being sent to the organization Web service contains business entity and core operation information. The message is passed through the event execution pipeline where it can be read or modified by the platform core operation and any registered plug-ins.

 

The below figure depicts the overall architecture of the Microsoft Dynamics CRM 2011 platform with respect to both synchronous and asynchronous event processing:

 

framework

 

The plugins registered synchronously will be executed immediately whereas plugins registered asynchronous will be queued with asynchronous service and executed later. The event pipeline is divided into 5 stages are as follows:

 

Stage#

Stage

Stage Name

Description

10

Pre Event

Pre Validation

- It execute before the main system operation.
- It may execute outside the database transaction.
- The pre-validation stage occurs prior to security checks being performed to verify the calling or logged on user has the correct permissions to perform the intended operation.

20

Pre Event

Pre Operation

- It execute before the main system operation.
- It could be executed in the database transaction.

30

Platform Core Operation

Main Operation

- This stage used for internal use only.
- It handles main operation such as create, update, delete etc.
- No custom plugins can be registered in this stage.

40

Post Event

Post Operation

- This Stage execute after the main operation.
- It could be executed in the database transaction

50

Post Event

Post Operation [Deprecated]

- This Stage execute after the main operation.
- This stage only supports Microsoft Dynamics CRM 4.0 plugins.

 

The Microsoft Dynamics CRM 2011 execution pipeline is organization specific. Server can host multiple organizations. There will be virtual pipeline for every organization. This means a plugin must be registered with each organization execution where it has to execute. We can register plugin in sandbox or outside sandbox. The difference if plugin registered within sandbox [known as partial trust] it will not have access to external endpoints other case if plugin registered outside the sandbox [known as full trust] it will support on-premise and Internet facing deployments. Whereas for online deployment plugin must be registered in sandbox only.

Friday, April 19, 2013

WCF Architecture

The following figure illustrates the major components of WCF.

 050000_WCF-Architecture

Figure 1: WCF Architecture

Contracts

Contracts layer are next to that of Application layer. Developer will directly use this contract to develop the service. We are also going to do the same now. Let us see briefly what these contracts will do for us and we will also know that WCF is working on message system.

Service contracts

- Describe about the operation that service can provide. Example, Service provided to know the temperature of the city based on the zip code, this service we call as Service contract. It will be created using Service and Operational Contract attribute.

Data contract

- It describes the custom data type which is exposed to the client. This defines the data types, are passed to and from service. Data types like int, string are identified by the client because it is already mention in XML schema definition language document, but custom created class or datatype cannot be identified by the client e.g. Employee data type. By using DataContract we can make client aware that we are using Employee data type for returning or passing parameter to the method.

Message Contract

- Default SOAP message format is provided by the WCF runtime for communication between Client and service. If it is not meeting your requirements then we can create our own message format. This can be achieved by using Message Contract attribute.

Policies and Binding

- Specify conditions required to communicate with a service e.g security requirement to communicate with service, protocol and encoding used for binding.

Service Runtime

- It contains the behaviors that occur during runtime of service.

  • Throttling Behavior- Controls how many messages are processed.
  • Error Behavior - Specifies what occurs, when internal error occurs on the service.
  • Metadata Behavior - Tells how and whether metadata is available to outside world.
  • Instance Behavior - Specifies how many instance of the service has to be created while running.
  • Transaction Behavior - Enables the rollback of transacted operations if a failure occurs.
  • Dispatch Behavior - Controls how a message is processed by the WCF Infrastructure.
Messaging

- Messaging layer is composed of channels. A channel is a component that processes a message in some way, for example, by authenticating a message. A set of channels is also known as a channel stack. Channels are the core abstraction for sending message to and receiving message from an Endpoint. Broadly we can categories channels as

  • Transport Channels

    Handles sending and receiving message from network. Protocols like HTTP, TCP, name pipes and MSMQ.

  • Protocol Channels

    Implements SOAP based protocol by processing and possibly modifying message. E.g. WS-Security and WS-Reliability.

Activation and Hosting

- Services can be hosted or executed, so that it will be available to everyone accessing from the client. WCF service can be hosted by following mechanism

  • IIS

    Internet information Service provides number of advantages if a Service uses Http as protocol. It does not require Host code to activate the service, it automatically activates service code.

  • Windows Activation Service

    (WAS) is the new process activation mechanism that ships with IIS 7.0. In addition to HTTP based communication, WCF can also use WAS to provide message-based activation over other protocols, such as TCP and named pipes.

  • Self-Hosting

    WCF service can be self hosted as console application, Win Forms or WPF application with graphical UI.

  • Windows Service

    WCF can also be hosted as a Windows Service, so that it is under control of the Service Control Manager (SCM).

Using Dynamic Entities

This sample shows how to create, retrieve, and update a contact as a dynamic entity.



   1:  //# Using Dynamic Entities 

   2:  using System;

   3:  using System.Collections;

   4:   

   5:  using CrmSdk;

   6:  using Microsoft.Crm.Sdk.Utility;

   7:   

   8:  namespace Microsoft.Crm.Sdk.HowTo

   9:  {

  10:     /// <summary>

  11:     /// This sample shows how to create a contact with a DynamicEntity and

  12:     ///  retrieve it as a DynamicEntity.

  13:     /// </summary>

  14:     public class DynamicEntityHowTo

  15:     {

  16:        static void Main(string[] args)

  17:        {

  18:           // TODO: Change the server URL and organization to match your Microsoft

  19:           // Dynamics CRM Server and Microsoft Dynamics CRM organization.

  20:           DynamicEntityHowTo.Run("http://localhost:5555", "CRM_SDK");

  21:        }

  22:   

  23:        public static bool Run(string crmServerUrl, string orgName)

  24:        {

  25:           bool success = false;

  26:   

  27:           try

  28:           {

  29:              // Set up the CRM Service.

  30:           CrmService service = CrmServiceUtility.GetCrmService(crmServerUrl, orgName);

  31:   

  32:              #region Setup Data Required for this Sample

  33:   

  34:              // Create the account object.

  35:              account account = new account();

  36:              account.name = "Fourth Coffee";

  37:   

  38:              // Create the target object for the request.

  39:              TargetCreateAccount target = new TargetCreateAccount();

  40:              target.Account = account;

  41:   

  42:              // Create the request object.

  43:              CreateRequest createRequest = new CreateRequest();

  44:              createRequest.Target = target;

  45:           

  46:              // Execute the request.

  47:              CreateResponse createResponse = (CreateResponse)service.Execute(createRequest);

  48:              Guid accountID = createResponse.id;

  49:   

  50:              #endregion

  51:   

  52:              #region Create Contact Dynamically

  53:   

  54:              // Set the properties of the contact using property objects.

  55:              StringProperty firstname = new StringProperty();

  56:              firstname.Name = "firstname";

  57:              firstname.Value = "Jesper";

  58:              StringProperty lastname = new StringProperty();

  59:              lastname.Name = "lastname";

  60:              lastname.Value = "Aaberg";

  61:           

  62:              // Create the DynamicEntity object.

  63:              DynamicEntity contactEntity = new DynamicEntity();

  64:   

  65:              // Set the name of the entity type.

  66:              contactEntity.Name = EntityName.contact.ToString();

  67:   

  68:              // Set the properties of the contact.

  69:              contactEntity.Properties = new Property[] {firstname, lastname};

  70:        

  71:              // Create the target.

  72:              TargetCreateDynamic targetCreate = new TargetCreateDynamic();

  73:              targetCreate.Entity = contactEntity;

  74:   

  75:              // Create the request object.

  76:              CreateRequest create = new CreateRequest();

  77:   

  78:              // Set the properties of the request object.

  79:              create.Target = targetCreate;

  80:   

  81:              // Execute the request.

  82:              CreateResponse created = (CreateResponse) service.Execute(create);

  83:           

  84:              #endregion

  85:           

  86:              #region Retrieve Contact Dynamically

  87:   

  88:              // Create the retrieve target.

  89:              TargetRetrieveDynamic targetRetrieve = new TargetRetrieveDynamic();

  90:   

  91:              // Set the properties of the target.

  92:              targetRetrieve.EntityName = EntityName.contact.ToString();

  93:              targetRetrieve.EntityId = created.id;

  94:   

  95:              // Create the request object.

  96:              RetrieveRequest retrieve = new RetrieveRequest();

  97:   

  98:              // Set the properties of the request object.

  99:              retrieve.Target = targetRetrieve;

 100:              // Be aware that using AllColumns may adversely affect

 101:              // performance and cause unwanted cascading in subsequent 

 102:              // updates. A best practice is to retrieve the least amount of 

 103:              // data required.

 104:              retrieve.ColumnSet = new AllColumns();

 105:   

 106:              // Indicate that the BusinessEntity should be retrieved as a DynamicEntity.

 107:              retrieve.ReturnDynamicEntities = true;

 108:   

 109:              // Execute the request.

 110:              RetrieveResponse retrieved = (RetrieveResponse) service.Execute(retrieve);

 111:   

 112:              // Extract the DynamicEntity from the request.

 113:              DynamicEntity entity = (DynamicEntity)retrieved.BusinessEntity;

 114:   

 115:              // Extract the fullname from the dynamic entity

 116:              string fullname;

 117:   

 118:              for (int i = 0; i < entity.Properties.Length; i++)

 119:              {

 120:                 if (entity.Properties[i].Name.ToLower() == "fullname")

 121:                 {

 122:                    StringProperty property = (StringProperty) entity.Properties[i];

 123:                    fullname = property.Value;

 124:                    break;

 125:                 }

 126:              }

 127:   

 128:              #endregion

 129:   

 130:              #region  Update the DynamicEntity

 131:   

 132:              // This part of the example demonstrates how to update properties of a 

 133:              // DynamicEntity.  

 134:   

 135:              // Set the contact properties dynamically.

 136:              // Contact Credit Limit

 137:              CrmMoneyProperty money = new CrmMoneyProperty();

 138:   

 139:              // Specify the property name of the DynamicEntity.

 140:              money.Name="creditlimit"; 

 141:              money.Value = new CrmMoney();

 142:   

 143:              // Specify a $10000 credit limit.

 144:              money.Value.Value=10000M; 

 145:   

 146:              // Contact PreferredContactMethodCode property

 147:              PicklistProperty picklist = new PicklistProperty();

 148:   

 149:              //   Specify the property name of the DynamicEntity. 

 150:              picklist.Name="preferredcontactmethodcode"; 

 151:              picklist.Value = new Picklist();

 152:   

 153:              //   Set the property's picklist index to 1.

 154:              picklist.Value.Value = 1;

 155:   

 156:              // Contact ParentCustomerId property.

 157:              CustomerProperty parentCustomer = new CustomerProperty();

 158:   

 159:              //   Specify the property name of the DynamicEntity.

 160:              parentCustomer.Name = "parentcustomerid"; 

 161:              parentCustomer.Value = new Customer();

 162:   

 163:              //   Set the customer type to account.

 164:              parentCustomer.Value.type = EntityName.account.ToString();

 165:   

 166:              //   Specify the GUID of an existing CRM account.

 167:              // SDK:parentCustomer.Value.Value = new Guid("A0F2D8FE-6468-DA11-B748-000D9DD8CDAC");

 168:              parentCustomer.Value.Value = accountID; 

 169:   

 170:              //   Update the DynamicEntities properties collection to add new properties.

 171:              //   Convert the properties array of DynamicEntity to an ArrayList.

 172:              ArrayList arrProps = new ArrayList(entity.Properties);

 173:              

 174:              //   Add properties to ArrayList.

 175:              arrProps.Add(money);

 176:              arrProps.Add(picklist);

 177:              arrProps.Add(parentCustomer);

 178:   

 179:              //   Update the properties array on the DynamicEntity.

 180:              entity.Properties = (Property[])arrProps.ToArray(typeof(Property));

 181:   

 182:              // Create the update target.

 183:              TargetUpdateDynamic updateDynamic = new TargetUpdateDynamic();

 184:   

 185:              // Set the properties of the target.

 186:              updateDynamic.Entity = entity;

 187:   

 188:              //   Create the update request object.

 189:              UpdateRequest update = new UpdateRequest();

 190:   

 191:              //   Set request properties.

 192:              update.Target = updateDynamic;

 193:   

 194:              //   Execute the request.

 195:              UpdateResponse updated = (UpdateResponse)service.Execute(update);

 196:              

 197:              #endregion

 198:   

 199:              #region check success

 200:   

 201:              if (retrieved.BusinessEntity is DynamicEntity)

 202:              {

 203:                 success =  true;

 204:              }

 205:   

 206:              #endregion

 207:     

 208:              #region Remove Data Required for this Sample

 209:   

 210:              service.Delete(EntityName.contact.ToString(), created.id);

 211:              service.Delete(EntityName.account.ToString(), accountID);

 212:   

 213:              #endregion

 214:           }

 215:           catch (System.Web.Services.Protocols.SoapException ex)

 216:           {

 217:              // Add your error handling code here...

 218:              Console.WriteLine(ex.Message + ex.Detail.InnerXml);

 219:           }

 220:           

 221:           return success;

 222:        }

 223:     }

 224:  }

Upload an Attachment

The following code example shows how to upload attachment to an annotation entity instance. The code first creates an account entity instance, and then adds an attached note to it with a doc file as an attachment.



using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using Microsoft.Crm.Sdk.Utility;

namespace Microsoft.Crm.Sdk.HowTo
{
// Use the following Microsoft Dynamics CRM namespaces in the sample.
using CrmSdk;

class UploadAttachment
{
static void Main(string[] args)
{
// TODO: Change the server URL and organization to match your
// Microsoft Dynamics CRM Server and Microsoft Dynamics CRM Organization.
UploadAttachment.Run("http://localhost:5555", "CRM_Organization");
}

public static bool Run(string crmServerUrl, string orgName)
{
#region Setup Data Required for this Sample

bool success = false;

#endregion

try
{
// Set up the CRM Service.
CrmService service = CrmServiceUtility.GetCrmService(crmServerUrl, orgName);
service.PreAuthenticate = true;

// Create an account object.
account acct = new account();

// Set the account properties.
acct.accountnumber = "CRM102";
acct.name = "Fourth Coffee";
acct.address1_name = "Primary";
acct.address1_line1 = "1234 Elm Street";
acct.address1_city = "Redmond";
acct.address1_stateorprovince = "WA";
acct.address1_postalcode = "54199";

// Creates an account in the Crm.
Guid createdAccountId = service.Create(acct);

// Now create the annotation object.
annotation note = new annotation();
note.notetext = "This is a sample note";
note.subject = "Test Subject";
note.objectid = new Lookup();
note.objectid.type = EntityName.account.ToString();

// Sets the note's parent to the newly created account.
note.objectid.Value = createdAccountId;
note.objecttypecode = new EntityNameReference();
note.objecttypecode.Value = EntityName.account.ToString();

// Create the note.
Guid createdNoteId = service.Create(note);

#region Setup Additional Data Required for this Sample

// Now convert the attachment to be uploaded to Base64 string.
// This will create a doc file in the current folder of executable.
string currentPath = System.Environment.CurrentDirectory.ToString();
TextWriter tw = new StreamWriter(currentPath + "\\Crm" + createdNoteId.ToString() + ".doc");
// Write a line of text to the file.
tw.WriteLine("This document is for testing an attachment upload feature of CRM 4.0.");
tw.Close();

#endregion

// Open a file and read the contents into a byte array.
FileStream stream = File.OpenRead(currentPath + "\\Crm" + createdNoteId.ToString() + ".doc");
byte[] byteData = new byte[stream.Length];
stream.Read(byteData, 0, byteData.Length);
stream.Close();

// Encode the data using base64.
string encodedData = System.Convert.ToBase64String(byteData);

// Now update the note.
annotation updateNote = new annotation();
updateNote.annotationid = new Key();
// Set the Note ID that is being attached to.
updateNote.annotationid.Value = createdNoteId;
updateNote.documentbody = encodedData;
updateNote.filename = "Crm" + createdNoteId.ToString() + ".doc";
updateNote.mimetype = @"application\ms-word";
service.Update(updateNote);

#region check success

if (createdNoteId != Guid.Empty)
{
success = true;
}

#endregion


#region Remove Data Required for this Sample

if (createdNoteId != Guid.Empty)
service.Delete(EntityName.annotation.ToString(), createdNoteId);

if(createdAccountId != Guid.Empty)
service.Delete(EntityName.account.ToString(), createdAccountId);

if (File.Exists(currentPath + "\\Crm" + createdNoteId.ToString() + ".doc"))
File.Delete(currentPath+"\\Crm" + createdNoteId.ToString() + ".doc");

#endregion

}
catch (System.Web.Services.Protocols.SoapException err)
{
string strError = String.Format("An error occurred. The message is {0}. The detail is {1}.", err.Message, err.Detail.OuterXml.ToString());
}


return success;
}
}
}