Common Context

This section describes the information that is available in the InputParameters and OutputParameters properties of IPluginExecutionContext. To understand the nature of this information, the relationship between an application making Web service calls and the context that a plug-in receives because of those calls must be described.

The following source code sample shows some typical calls to the Microsoft Dynamics CRM Web service.

[C#]
// Set up the CRM Service.
CrmService service = new CrmService();
service.Credentials = System.Net.CredentialCache.DefaultCredentials;

// Create the account object.
account account = new account();
account.name = "Fourth Coffee";

// Create the target object for the request.
TargetCreateAccount target = new TargetCreateAccount();
target.Account = account;

// Create the request object.
CreateRequest createRequest = new CreateRequest();
createRequest.Target = target;

// Execute the request.
CreateResponse createResponse = (CreateResponse)service.Execute(createRequest);
Guid accountID = createResponse.id;


Although this example uses Request/Response messages and the Execute method, you can use the other CrmService methods such as Create, Update, and Deleteto work with your business entities. The Microsoft Dynamics CRM system takes the information from those CrmService methods and transforms it intoRequest/Response messages that are processed by the event execution pipeline. The information on input/output parameters that follows still applies.

The following documentation relates the Web service calls in the example code to the context that a plug-in is passed. For the examples described herein, assume that a plug-in is registered to execute during the post-event of account creation so that the sample code causes the plug-in to execute.

Input Parameters


The InputParameters property bag contains all the information specified in the Request class whose message caused the plug-in to execute. The keys used to obtain values from the property bag are named according to the name of the Request class instance properties. An example of this is described next.

In the code sample, an account is created by using the CreateRequest class. The Target property of CreateRequest refers to a TargetCreateAccount object, which refers to an account object. This is shown in the following diagram.

CreateRequest and associated classes

When the plug-in is executed, the information that is in the Request object is passed to the plug-in in the InputParameters property of IPluginExecutionContext. For this example, the InputParameters property bag contains two key/value pairs. The first key is named "Target" and its associated value is the target of the request, namely the account object. The second key is named "OptionalParameters" and its associated value is the OptionalParameters instance property that is defined in the Request class from which CreateRequest is derived. In the sample code, no optional parameters were added to the CreateRequest, so that the optional parameters value in InputParameters is null.

The following figure shows an example plug-in that is being debugged in Visual Studio 2005.

Viewing the InputParameters property bag in a debugger

The figure shows the contents of the InputParameters property bag that has been passed in the context to the plug-in. Two key/value pairs are shown: Target andOptionalParameters.

The recommended way to specify these key names in code is to use the predefined names in the ParameterName class. For example, you can useParameterName.Target instead of "Target". Doing this reduces the possibility of a typing mistake in the key name when coding.

InputParameters contains Object types. Therefore, you must cast the property bag values to their appropriate types. The following sample plug-in code shows how to obtain the original account object.

[C#] DynamicEntity entity = (DynamicEntity)context.InputParameters.Properties[ParameterName.Target]

The account attributes can then be accessed in the plug-in.

[C#] string accountName = entity["name"]

Note The dynamic entity obtained from the InputParameters of the context contains only those attributes that are set to a value or null.

Output Parameters


For a post-event, the OutputParameters property bag contains the result of the core operation that is returned in the Response message. The key names that are used to access the values in the OutputParameters property bag match the names of the Response class instance properties.

CreateResponse class

In the source code example, the CreateResponse object contains the GUID of the new account instance after the Execute method is called. A post-event registered plug-in can obtain the GUID from the OutputParameters property bag by using the "id" key name or ParameterName.Id.

//[C#] 
Guid regardingobjectid = (Guid)context.OutputParameters[ParameterName.Id]

If a plug-in is registered for a pre-event, the OutputParameters property bag would not contain a value for the "id" key because the core operation would not yet have occurred.

CRM 2011 Visualizations

Visualizations - Charts


Visualizations - Dashboards

RemoveItemCampaign Message

Removes an item from a campaign.


//# The following code example shows how to use the RemoveItemCampaign message.

// Set up the CRM service.
CrmAuthenticationToken token = new CrmAuthenticationToken();
// You can use enums.cs from the SDK\Helpers folder to get the enumeration for Active Directory authentication.
token.AuthenticationType = 0;
token.OrganizationName = "AdventureWorksCycle";

CrmService service = new CrmService();
service.Url = "http://:/mscrmservices/2007/crmservice.asmx";
service.CrmAuthenticationTokenValue = token;
service.Credentials = System.Net.CredentialCache.DefaultCredentials;

// Create the request object.
RemoveItemCampaignRequest remove = new RemoveItemCampaignRequest();

// Set the ID of the campaign.
remove.CampaignId = new Guid("d7f33457-660e-de11-bf40-00155da4c706");

// Set the ID of the campaign item to remove.
remove.EntityId = new Guid("6e47aeb7-c30d-de11-bf40-00155da4c706");

// Execute the request.
RemoveItemCampaignResponse removed =
(RemoveItemCampaignResponse)service.Execute(remove);




RemoveMemberList Message

Removes a member from a list.



//# The following code example shows how to use the RemoveMemberList message.

// Set up the CRM service.
CrmAuthenticationToken token = new CrmAuthenticationToken();
// You can use enums.cs from the SDK\Helpers folder to get the enumeration for Active Directory authentication.
token.AuthenticationType = 0;
token.OrganizationName = "AdventureWorksCycle";

CrmService service = new CrmService();
service.Url = "http://:/mscrmservices/2007/crmservice.asmx";
service.CrmAuthenticationTokenValue = token;
service.Credentials = System.Net.CredentialCache.DefaultCredentials;

// Create the request object.
RemoveMemberListRequest remove = new RemoveMemberListRequest();

// Set the ID of the list.
remove.ListId = new Guid("18ECA720-493E-4800-BBFD-638BD54EB325");
// Set the ID of the list item to remove.
remove.EntityId = new Guid("2B951FBC-1C56-4430-B23B-20A1349068F3");

// Execute the request.
RemoveMemberListResponse removed = (RemoveMemberListResponse)service.Execute(remove);




Retrive Dynamic Entity based on Entity name & Guid



public DynamicEntity retriveEntity(string EntityName, string recordGuid)
{
TargetRetrieveDynamic targetRetrieve = new TargetRetrieveDynamic();

// Set the properties of the target.
targetRetrieve.EntityName = "contact";
targetRetrieve.EntityId = new Guid(rec_guid);

// Create the request object.
RetrieveRequest retrieve = new RetrieveRequest();

// Set the properties of the request object.
retrieve.Target = targetRetrieve;
retrieve.ColumnSet = new AllColumns();

// Indicate that the BusinessEntity should be retrieved as a DynamicEntity.
retrieve.ReturnDynamicEntities = true;

// Execute the request.
RetrieveResponse retrieved = (RetrieveResponse)_svc.Execute(retrieve);

// Extract the DynamicEntity from the request.
DynamicEntity R_entity = (DynamicEntity)retrieved.BusinessEntity;
return R_entity;
}




PublishXml Message

Publish the customizations for the specified entities.

   
//# The following code example shows how to use the PublishXml message.

// Set up the CRM service.
CrmAuthenticationToken token = new CrmAuthenticationToken();
// You can use enums.cs from the SDK\Helpers folder to get the enumeration for Active Directory authentication.
token.AuthenticationType = 0;
token.OrganizationName = "AdventureWorksCycle";

CrmService service = new CrmService();
service.Url = "http://:/mscrmservices/2007/crmservice.asmx";
service.CrmAuthenticationTokenValue = token;
service.Credentials = System.Net.CredentialCache.DefaultCredentials;

// Create the request.
PublishXmlRequest request = new PublishXmlRequest();

request.ParameterXml = @"<importexportxml>
<entities>
<entity>account</entity>
<entity>contact</entity>
</entities>
<nodes />
<securityroles />
<settings />
<workflows />
</importexportxml>";

// Execute the request.
PublishXmlResponse response = (PublishXmlResponse)service.Execute(request);




What is WCF RIA service?

WCF RIA service is a framework to develop n-tier application for Rich Internet Application (RIA). It is mainly used in RIA applications like Silverlight, AJAX client, etc. It solves the major problem while developing business application like decoupling the resource access, application logic and presentation layer. WCF RIA service was introduced in Silverlight 4 with .net framework 4, and it can be developed using visual studio2010.

Main problem developer are facing while developing the n-tier RIA application will be coordinating the application logic between middle tier and presentation tier. This problem will be solved by using WCF RIA service, it will synchronize the code between middle and presentation tier.

WCF RIA service will allow developer to write the set of service code and this server code will be available to the client side without manually duplicate that programming logic. RIA service client will be updated with business rule and entity present at the server side, when your recompile your project solution.

WCF RIA service will generate the code at the client side related to the service and domain entities declared at the server side.

RIA service exposes the data from server side to client side using Domain service, RIA service framework implements the each domain service as WCF service to access the data as business entity.

  1. WCF RIA Domain Service

  2. Problems solved in RIA Service

  3. Query/Update process in RIA

  4. How to create Silverlight-WCF RIA service

fig: WCF RIA Serive architecture
WCF RIA Serive architecture

 

Domain Service

Domain services are WCF services that expose the business logic of a WCF RIA Services application. Domain service contains set of business related data operation and it is exposed as WCF service.

Below diagram explains integration of the RIA service with WCF

The DomainService class is the base class for all classes that serve as domain services.

  • DomainServiceHost is the hosting class for domain service; internally
  • DomainServiceHost uses the WCF ServiceHost class to host the application.

A domain service class must be marked with the EnableClientAccessAttribute attribute to make the service available to the client project. The EnableClientAccessAttributeattribute is automatically applied to a domain service when you select the Enable client access check box in the Add New Domain Service Class dialog box. When the EnableClientAccessAttribute attribute is applied to a domain service, RIA Services generates the corresponding classes for the client project.

   1:  //Example:
   2:   [EnableClientAccess()]
   3:      public class EmployeeDomainService : DomainService
   4:      {
   5:          private EmployeeData data = EmployeeData.Instance;
   6:   
   7:          public IEnumerable < Employee> GetEmployees()
   8:          {
   9:              return data.EmployeeList;
  10:          }
  11:      }
  12:   



DomainContext class at the client side is used to consume the Domain service by using DomainClient object. DomainContext class available inside the name space "System.ServiceModel.DomainServices.Client"

fig: WCF RIA Domain Serive architecture
WCF RIA Domain Serive

 


Problem solved in RIA



  1. To have best performance of the RIA application, app logic need to be available in client and server side. This problem is solved by auto generating the code at the client side while recompiling the project.
  2. Asynchronous call – Asynch service call are supported in Domain service by using WCF infrastructure
  3. Handling large data and data across different tier – Large amount of data can be access and filter using IQueryable object. Since entity objects used in domain service are serializable and so it can be access across different layer
  4. Security/Access control – ASP.Net membership frameworks are integrated with RIA service to provide security systems to RIA service
  5. Validation – Entity can be validated based using adding attribute to the class members

   1:  //Example:
   2:    public class Member
   3:      {
   4:          [Key]
   5:          public int MemberId { get; set; }
   6:   
   7:   
   8:          public string Fname { get; set; }
   9:   
  10:          [Required]
  11:          public string Lname { get; set; }
  12:   
  13:          public DateTime JoinDate { get; set; }
  14:   
  15:          [Range(30,90, ErrorMessage="sorry, you are either too young or too old for our club!")]
  16:          public int Age { get; set; }
  17:      }

 


 


Querying/Updating data in RIA Service


The below diagram are self explanatory to discuss about the querying or updating the data using RIA service

fig: WCF RIA to Query data


fig: WCF RIA to update data




 


How to Create WCF RIA Service


Download:
Silverlight_WCF_RIA_Service.zip

Let us understand more about the WCF RIA service by creating Silverlight client application which read and updated the Employee details from WCF RIA Service.

Step 1:Start the Visual Studio 2010 and click File -> New-> Project. Enter the project name and click “Create”

Project creation

Step 2:Select “Enable WCF RIA Services”. This will make your Silverlight application to user WCF RIA service

Select RIA service

Step 3:Create “Data” folder and add DataModel” class as shown below. This is the data class which will return list of Employee and update the employee list

Data Model class:


   1:  public class Employee
   2:      {
   3:          [Key]
   4:          public int EmpId { get; set; }
   5:          public string Fname { get; set; }
   6:          public string Lname { get; set; }
   7:          public DateTime JoinDate { get; set; }
   8:          public int Age { get; set; }
   9:      }
  10:   
  11:   
  12:      public partial class EmployeeData
  13:      {
  14:          private static readonly EmployeeData _instance = new EmployeeData();
  15:          private EmployeeData() { }
  16:          public static EmployeeData Instance
  17:          {
  18:              get
  19:              {
  20:                  return _instance;
  21:              }
  22:          }
  23:   
  24:   
  25:          private List < Employee > empList = new List < Employee>()
  26:          {
  27:              new Employee() { EmpId  = 1, Fname = "Sam", Lname = "kumar", 
  28:                              JoinDate=new DateTime(2010,7, 21), Age=30},
  29:              new Employee() { EmpId = 2, Fname = "Ram", Lname = "kumar", 
  30:                              JoinDate=new DateTime(2009,6,8), Age=35},    
  31:              new Employee() { EmpId = 3, Fname = "Sasi", Lname = "M", 
  32:                              JoinDate=new DateTime(2008,3,5), Age=39},  
  33:              new Employee() { EmpId = 4, Fname = "Praveen", Lname = "KR", 
  34:                              JoinDate=new DateTime(2010, 5,1), Age=56},
  35:              new Employee() { EmpId = 5, Fname = "Sathish", Lname = "V", 
  36:                              JoinDate = new DateTime(2006,12,15), Age=72},  
  37:              new Employee() { EmpId = 6, Fname = "Rosh", Lname = "A", 
  38:                              JoinDate=new DateTime(2009,2,2), Age=25}
  39:          };
  40:   
  41:          public IEnumerable< Employee > EmployeeList
  42:          {
  43:              get
  44:              {
  45:                  return empList;
  46:              }
  47:          }
  48:   
  49:   
  50:          public void Update(Employee updEmployee)
  51:          {
  52:              Employee existing = empList.Find(p => p.EmpId == updEmployee.EmpId);
  53:              if (existing == null)
  54:                  throw new KeyNotFoundException("Specified Employee cannot be found");
  55:   
  56:              existing.Fname = updEmployee.Fname;
  57:              existing.Lname = updEmployee.Lname;
  58:              existing.JoinDate = updEmployee.JoinDate;
  59:              existing.Age = updEmployee.Age;
  60:          }
  61:      }



Step 4:To expose the Employee related operation to the client side, Create domain service class. By right click project file and select Add new item.

Create Domain Service

Step 5:Add code to return the Employee list

Domain Service class:


   1:  // TODO: Create methods containing your application logic.
   2:      [EnableClientAccess()]
   3:      public class EmployeeDomainService : DomainService
   4:      {
   5:          //Create instance of the Data access layer
   6:          private EmployeeData data = EmployeeData.Instance;
   7:   
   8:          public IEnumerable< Employee> GetEmployee()
   9:          {
  10:              return data.EmployeeList ;
  11:          }
  12:   
  13:          public void UpdateEmployee(Employee emp)
  14:          {
  15:              data.Update(emp);
  16:          }
  17:      }



Step 6:Compile the solution – After compilation RIA service will generate the application logic at the client side using DomainContext object. Enable show all files option for the solution and view the auto generated code.

Auto generated code

Step 7:View the DomainContext class are created at the client side.

Domain Context class at client:


   1:   /// 
   2:      /// The DomainContext corresponding to the 'EmployeeDomainService' DomainService.
   3:      /// 
   4:      public sealed partial class EmployeeDomainContext : DomainContext
   5:      {
   6:          
   7:          #region Extensibility Method Definitions
   8:   
   9:          /// 
  10:          /// This method is invoked from the constructor once initialization is complete and
  11:          /// can be used for further object setup.
  12:          /// 
  13:          partial void OnCreated();
  14:   
  15:          #endregion
  16:          
  17:          
  18:          /// 
  19:          /// Initializes a new instance of the < see cref="EmployeeDomainContext"/> class.
  20:          /// 
  21:          public EmployeeDomainContext() : 
  22:                  this(new WebDomainClient< IEmployeeDomainServiceContract>(new 
  23:                                Uri("MyFirstRIAApplication-Web-EmployeeDomainService.svc", 
  24:                                                          UriKind.Relative)))
  25:          {
  26:          }
  27:   
  28:          ........
  29:          ........



Step 8:Add DataGrid to Main.xaml file to display the employee details query from DataModel and add two buttons to update and reject the data changed from client side.


Main.xaml

 < Grid x:Name="LayoutRoot" Background="White">
        < StackPanel Orientation="Vertical" HorizontalAlignment="Left"  >
        < sdk:DataGrid x:Name="EmployeeGrid" AutoGenerateColumns="True"  
                        RowEditEnded="EmployeeGrid_RowEditEnded" />
            < Button Content="Accept" Height="23" Name="btnAccept" 
                        Width="75" Margin="5" Click="btnAccept_Click"  />
            < Button Content="Reject" Height="23" Name="btnReject" 
                        Width="75" Margin="5" Click="btnReject_Click"/>
        </StackPanel>
    </Grid>


    

Main.xaml.vb

   1:  public partial class MainPage : UserControl
   2:      {
   3:          //create instance of Doman context class
   4:          EmployeeDomainContext ctx = new EmployeeDomainContext();
   5:   
   6:          public MainPage()
   7:          {
   8:              InitializeComponent();
   9:              //Load query data , Read data from DAL layer to UI
  10:              EntityQuery< Employee> query = ctx.GetEmployeeQuery();
  11:              LoadOperation< Employee> lo = ctx.Load< Employee>(query);
  12:              EmployeeGrid.ItemsSource = lo.Entities;
  13:          }
  14:   
  15:          private void EmployeeGrid_RowEditEnded(object sender, 
  16:                                  DataGridRowEditEndedEventArgs e)
  17:          {
  18:   
  19:          }
  20:   
  21:          private void btnAccept_Click(object sender, RoutedEventArgs e)
  22:          {
  23:              //Update the DAL with user changes
  24:              ctx.SubmitChanges();
  25:          }
  26:   
  27:          private void btnReject_Click(object sender, RoutedEventArgs e)
  28:          {
  29:              //Roll back the user changes
  30:              ctx.RejectChanges();
  31:          }
  32:      }



Step 9:Run the application and see the output as shown below

RIA service output

CRM 2011 UX Extensibility

UX Extensibility - Intro


UX Extensibility - WebResources


UX Extensibility - Client Scripting


UX Extensibility - Filtered Lookups

Convert a Fax to a Task

This sample code shows how to convert a fax to a task. The code first creates an incoming Fax activity, and then converts it to a Follow-up Task with a due date a week after it was received.



[C#]
using System;
using Microsoft.Crm.Sdk.Utility;

namespace Microsoft.Crm.Sdk.HowTo
{
// Microsoft Dynamics CRM namespaces.
using CrmSdk;

///
/// This sample shows how to convert a fax into a task.
///

public class ConvertFaxToTask
{
static void Main(string[] args)
{
// TODO: Change the server URL and organization to match your Microsoft Dynamics CRM server and Microsoft Dynamics CRM organization.
ConvertFaxToTask.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;

// Get the current user.
WhoAmIRequest userRequest = new WhoAmIRequest();
WhoAmIResponse user = (WhoAmIResponse)service.Execute(userRequest);

// Create the fax object.
fax fax = new fax();

// Set the properties of the fax.
fax.subject = "Test Fax";
fax.description = "New Fax";

// Create the party sending and receiving the fax.
activityparty party = new activityparty();

// Set the properties of the activity party.
party.partyid = new Lookup();
party.partyid.type = EntityName.systemuser.ToString();
party.partyid.Value = user.UserId;

// The party sends and receives the fax.
fax.from = new activityparty[] { party };
fax.to = new activityparty[] { party };

// Create the fax.
Guid createdFaxId = service.Create(fax);

// Retrieve the created fax.
// Be aware that using AllColumns may adversely affect
// performance and cause unwanted cascading in subsequent
// updates. A best practice is to retrieve the least amount of
// data required.
fax newFax = (fax)service.Retrieve(EntityName.fax.ToString(), createdFaxId, new AllColumns());

// Create the task object.
task task = new task();

// Set the properties of the task.
task.subject = "Follow Up: " + newFax.subject;

// Set the due date of the task.
task.scheduledend = new CrmDateTime();

// Get the date that the fax was received.
CrmDateTime endDate = newFax.createdon;

// Set the due date of the task to one week later.
task.scheduledend.Value = endDate.UniversalTime.AddDays(7).ToString();

// Create the task.
Guid createdTaskId = service.Create(task);

#region check success

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

#endregion

#region Remove Data Required for this Sample

service.Delete(EntityName.fax.ToString(), createdFaxId);
service.Delete(EntityName.task.ToString(), createdTaskId);

#endregion
}
catch (System.Web.Services.Protocols.SoapException)
{
// Add your error handling code here.
}

return success;
}
}
}





Merge Message

Merges the information from two entity instances of the same type.



//# The following code example shows how to use the Merge message.

// Set up the CRM service.
CrmAuthenticationToken token = new CrmAuthenticationToken();
// You can use enums.cs from the SDK\Helpers folder to get the enumeration for Active Directory authentication.
token.AuthenticationType = 0;
token.OrganizationName = "AdventureWorksCycle";

CrmService service = new CrmService();
service.Url = "http://:/mscrmservices/2007/crmservice.asmx";
service.CrmAuthenticationTokenValue = token;
service.Credentials = System.Net.CredentialCache.DefaultCredentials;

// Create the target for the request.
TargetMergeAccount target = new TargetMergeAccount();
// EntityId is the GUID of the account that is being merged into.
target.EntityId = new Guid("2B951FBC-1C56-4430-B23B-20A1349068F3");

// Create the request.
MergeRequest merge = new MergeRequest();
// SubordinateId is the GUID of the account merging.
merge.SubordinateId = new Guid("AD618DB2-F0DB-4A6A-8C4B-2F2213EAA38E");
merge.Target = target;
merge.PerformParentingChecks = false;

account updateContent = new account();
updateContent.address1_line1 = "test";
merge.UpdateContent = updateContent;


// Execute the request.
MergeResponse merged = (MergeResponse)service.Execute(merge);