Wednesday, March 7, 2012

Meta Data Web Service in CRM with Example in 4.0.


Metadata Web Service

This Web Service is the one that provides access to the entire CRM metadata.
A new feature with this version of Microsoft CRM, the metadata can now be used to create, update, or delete entities, as well as create or delete relationships within entities. You can also use it to add, delete, or modify attributes to an existing entity programmatically.
This Web Service can be very useful for ISVs to look up entities on a setup installer to see if the product was already installed or to check whether any conflict exists with the entities of the CRM system on which a customization would be deployed.

The URL for this Web Service reference is
http://<servername>:<portnumber>/MSCrmServices/2007/MetadataService.asmx

For example:
http://crm4:5555/MSCrmServices/2007/MetadataService.asmx

To add a Web Reference for this Web Service, go to Visual Studio 2005 and, using the new console application project you created, right-click the project name in the Solution Explorer and choose Add Web Reference from the menu. Enter the URL of the metadata Web Service, click GO, and then enter CrmSdk.Metadata as the Web Reference Name

Click Add Reference to finally add the Web Service reference to your project.
This Web Service exposes only one method, the Execute method.
Execute Method
This method accepts the following submethods:

CreateAttribute
CreateEntity
CreateManyToMany
CreateOneToMany
DeleteAttribute
DeleteEntity
DeleteOptionValue
DeleteStatusValue
DeleteRelationship
InsertOptionValue
InsertStatusValue
OrderOption
OrderStatus
RetrieveAllEntities
RetrieveAttribute
RetrieveEntity
RetrieveRelationship
RetrieveTimestamp
UpdateAttribute
UpdateEntity
UpdateOptionValue
UpdateStatusValue
UpdateRelationship

Each of these submethods has its own Request and Response classes.
To use the CreateAttribute method, for example, you must create an instance of CreateAttributeRequest, and the Execute method would return an instance of CreateAttributeResponse.
For example, you might use the following code to find out whether the custom entity new_MyNewCustomEntity already exists in a CRM implementation. As with the Main Data Web Service, you will generate a common method to retrieve the Metadata Web Service URL for the organization by using the Discovery Web Service. You will use this method throughout the samples related to the Metadata Web Service.

Example:
namespace MetadataWebService
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(CheckEntity("ORGNAME","account"));
            Console.ReadKey();
        }
        private static bool CheckEntity(string organizationName, string entityName)
        {
            try
            {
                CrmSdk.Metadata.MetadataService myCrm = new CrmSdk.Metadata.MetadataService();
                myCrm.Url = GetCrmServiceForOrganization(organizationName);
                CrmSdk.Metadata.CrmAuthenticationToken myToken = new CrmSdk.Metadata.CrmAuthenticationToken();
                myToken.AuthenticationType = 0;
                myToken.OrganizationName = organizationName;
                myCrm.CrmAuthenticationTokenValue = myToken;
                myCrm.Credentials = System.Net.CredentialCache.DefaultCredentials;

                CrmSdk.Metadata.RetrieveEntityRequest myRequest = new CrmSdk.Metadata.RetrieveEntityRequest();
                myRequest.LogicalName = entityName.ToLower();
                CrmSdk.Metadata.RetrieveEntityResponse myResponse;
                myResponse = (CrmSdk.Metadata.RetrieveEntityResponse)myCrm.Execute(myRequest);
                return true;
            }
            catch (System.Web.Services.Protocols.SoapException soapEx)
            {
                Console.WriteLine("SOAP exception: " + soapEx.Detail.InnerText + "  " + soapEx.ToString());
                return false;
            }
            catch (Exception ex)
            {
                Console.WriteLine("General exception: " + ex.ToString());
                return false;
            }
        }
        private static string GetCrmServiceForOrganization(string organizationName)
        {
            string urlResult = "";
            CrmSdk.Discovery.CrmDiscoveryService myCrm = new CrmSdk.Discovery.CrmDiscoveryService();

            //myCrm.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
            System.Net.CredentialCache.DefaultNetworkCredentials.UserName = "kartik.patel";
            System.Net.CredentialCache.DefaultNetworkCredentials.Domain = "server";
            System.Net.CredentialCache.DefaultNetworkCredentials.Password = "password";
            myCrm.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
            CrmSdk.Discovery.RetrieveOrganizationsRequest myRequest = new CrmSdk.Discovery.RetrieveOrganizationsRequest();

            CrmSdk.Discovery.RetrieveOrganizationsResponse myResponse = (CrmSdk.Discovery.RetrieveOrganizationsResponse)myCrm.Execute(myRequest);
            foreach (CrmSdk.Discovery.OrganizationDetail tDetail in myResponse.OrganizationDetails)
            {
                Console.WriteLine("Organization = " + tDetail.OrganizationName);
                if (String.Compare(tDetail.OrganizationName, organizationName, true) == 0)
                {
                    return tDetail.CrmServiceUrl;
                }
            }
            return urlResult;

        }
    }
}

Above code check that account entity is exist or not.Now Lets see another Example.

private static bool CreateCustomEntity(string organizationName, string entityName)
{
   try
   {

       CrmSdk.Metadata.MetadataService myCrm = new CrmSdk.Metadata.MetadataService();
       myCrm.Url = GetCrmMetadataServiceForOrganization(organizationName);
       CrmSdk.Metadata.CrmAuthenticationToken myToken = new CrmSdk.Metadata.CrmAuthenticationToken();
       myToken.AuthenticationType = 0;
       myToken.OrganizationName = organizationName;
       myCrm.CrmAuthenticationTokenValue = myToken;
       myCrm.Credentials = System.Net.CredentialCache.DefaultCredentials;

       // Creates new entity
       CrmSdk.Metadata.EntityMetadata myNewEntity = new CrmSdk.Metadata.EntityMetadata();
       myNewEntity.Description = CreateLabel(entityName);
       myNewEntity.DisplayCollectionName = CreateLabel(entityName);
       myNewEntity.DisplayName = CreateLabel(entityName);

       myNewEntity.IsAvailableOffline = new CrmSdk.Metadata.CrmBoolean();
       myNewEntity.IsAvailableOffline.Value = true;
       myNewEntity.DuplicateDetection = new CrmSdk.Metadata.CrmBoolean();
       myNewEntity.DuplicateDetection.Value = true;
       myNewEntity.SchemaName = entityName;
       myNewEntity.LogicalName = entityName;
       myNewEntity.OwnershipType = new CrmSdk.Metadata.CrmOwnershipTypes();
       myNewEntity.OwnershipType.Value = CrmSdk.Metadata.OwnershipTypes.UserOwned;

       // creates primary attribute
       CrmSdk.Metadata.StringAttributeMetadata myPrimaryAttr = new CrmSdk.Metadata.StringAttributeMetadata();
       myPrimaryAttr.DisplayName = CreateLabel("Name");
       myPrimaryAttr.Description = CreateLabel("this is the Name");
       myPrimaryAttr.AttributeType = new CrmSdk.Metadata.CrmAttributeType();
       myPrimaryAttr.AttributeType.Value = CrmSdk.Metadata.AttributeType.String;
       myPrimaryAttr.MaxLength = new CrmSdk.Metadata.CrmNumber();       myPrimaryAttr.MaxLength.Value = 100;
       myPrimaryAttr.SchemaName = "new_Name";
       myPrimaryAttr.Format = new CrmSdk.Metadata.CrmStringFormat();
       myPrimaryAttr.Format.Value = CrmSdk.Metadata.StringFormat.Text;
       myPrimaryAttr.RequiredLevel = new CrmSdk.Metadata.CrmAttributeRequiredLevel();
       myPrimaryAttr.RequiredLevel.Value = CrmSdk.Metadata.AttributeRequiredLevel.Required;
       myPrimaryAttr.DisplayMask = new CrmSdk.Metadata.CrmDisplayMasks();
       myPrimaryAttr.DisplayMask.Value = CrmSdk.Metadata.DisplayMasks.PrimaryName;
       myPrimaryAttr.LogicalName = "new_name";

       // prepare request
       CrmSdk.Metadata.CreateEntityRequest myRequest = new CrmSdk.Metadata.CreateEntityRequest();
       myRequest.Entity = myNewEntity;
       myRequest.HasActivities = true;
       myRequest.HasNotes = true;
       myRequest.PrimaryAttribute = myPrimaryAttr;

       CrmSdk.Metadata.CreateEntityResponse myResponse;
       myResponse = (CrmSdk.Metadata.CreateEntityResponse)myCrm.Execute(myRequest);
       return true;
   }
   catch (System.Web.Services.Protocols.SoapException soapEx)
   {
       Console.WriteLine("SOAP exception: " + soapEx.Detail.InnerText + "  " + soapEx.ToString());
       return false;
   }
   catch (Exception ex)
   {
       Console.WriteLine("General exception: " + ex.ToString());
       return false;
   }
}

                                        

Note

The code uses a custom method called CreateLabel to simplify the code used to set up the labels; they must be managed in a collection because of the Multilanguage feature. This sample uses only the English language for the strings, but you can easily customize it to use other languages.

private static CrmSdk.Metadata.CrmLabel CreateLabel(string myString)
{
   CrmSdk.Metadata.CrmLabel myLabel = new CrmSdk.Metadata.CrmLabel();
   CrmSdk.Metadata.LocLabel[] myLabels = new CrmSdk.Metadata.LocLabel[1];
   myLabels[0] = new CrmSdk.Metadata.LocLabel();
   myLabels[0].Label = myString;
   myLabels[0].LanguageCode = new CrmSdk.Metadata.CrmNumber();
   myLabels[0].LanguageCode.Value = 1033; // English code
   myLabel.LocLabels = myLabels;
   return myLabel;
}

Now if you want to create a new entity with the name of new_MyNewCustomEntity on the organization with the name Webfortis, you could use the following code:
static void Main(string[] args)
{
        CreateCustomEntity("Webfortis", "new_MyNewCustomEntity");

        Console.ReadKey();
}

Note

Be sure the entity name doesn't already exist in the CRM system, or the Execute method will raise an exception. To be sure, you could use the CheckEntity method you created before and use a code as follows:
static void Main(string[] args)
{
   if (!CheckEntity("Webfortis", "new_MyNewCustomEntity"))
         {
             CreateCustomEntity("Webfortis", "new_MyNewCustomEntity");
         }
    Console.ReadKey();
}

In addition, you must set at least the primary attribute on the request, and this one must be required.

You can also use this Web Service if you want to show all the options from a Picklist attribute on another application.
As another example, imagine that you needed to retrieve all possible values for the Shipping Method property for Accounts. Because the Shipping Method is a Picklist, you would have to query the MetaData to get the values.
This method can be used as follows:
Code View:
private static void GetShippingMethod(string organizationName)
{
    CrmSdk.Metadata.MetadataService myCrm = new CrmSdk.Metadata.MetadataService();
    myCrm.Url = GetCrmMetadataServiceForOrganization(organizationName);
    CrmSdk.Metadata.CrmAuthenticationToken myToken = new CrmSdk.Metadata.CrmAuthenticationToken();
    myToken.AuthenticationType = 0;
    myToken.OrganizationName = organizationName;
    myCrm.CrmAuthenticationTokenValue = myToken;
    myCrm.Credentials = System.Net.CredentialCache.DefaultCredentials;

    CrmSdk.Metadata.RetrieveAttributeRequest myRequest = new CrmSdk.Metadata.RetrieveAttributeRequest();
    myRequest.EntityLogicalName = CrmSdk.EntityName.account.ToString();
    myRequest.LogicalName = "address1_shippingmethodcode";

    CrmSdk.Metadata.RetrieveAttributeResponse myResponse;
    myResponse = (CrmSdk.Metadata.RetrieveAttributeResponse)
    myCrm.Execute(myRequest);
    foreach (CrmSdk.Metadata.Option myOption in ((CrmSdk.Metadata.PicklistAttributeMetadata)(myResponse.AttributeMetadata)).Options)
    {
        Console.WriteLine(myOption.Label.LocLabels[0].Label);
    }
}

Now if you want to test this method on the organization with the name Webfortis, you could use the following code:
static void Main(string[] args)
{
        GetShippingMethod("Webfortis");
        Console.ReadKey();
}

No comments:

Post a Comment