Archive

Archive for February, 2008

High level explanation of how Windows Live ID works

February 27, 2008 Leave a comment

If you are using a web application that uses Windows Live, such as Microsoft Dynamics CRM Live, you might be wondering, how does authentication work.

The first step in the process is that the web application registers with the Windows Live ID service. This registration includes creating unique keys for the application and storing a URL that the Live ID service will use to redirect users after they sign into Windows Live ID.
The 2nd step is when the application wants to authenticate the user. The application will provide the ‘sign-in’ link on it’s web page. When clicking on the link, the user will be redirected to a sign-in page hosted by Windows Live ID. When this happens a token is also passed that identifies the application. By passing in a token that was given to the application at time of registration, the sign-in page understands who is calling it.
The 3rd step is that the user logins into Live ID. After logging into Live, the Live service redirects the user to the applications designated page that it registered with. The application can then redirect back to the original landing page the user came in on. Presto, you are authenticated to the Web application.

Windows Live does not store or pass any permissions ( or personal ) information to the application. It’s the applications responsibility to manage the permissions. Windows Live is used to handle the authentication. Authentication is validating that the user is who the user claims they are. Below is a high level architectural diagram of the Windows Live ID Service.

clip_image001

For client side applications it’s little different. On the client side, applications utilize a special component named MSIDCRL40.dll. This component handles a variety of services such as encryption. The client side application will need a to create or retrieve a key that is used. In a software+service model, this might include calling into a web service of a online application to retrieve a dynamically generated key that is used. After the call is made, a token is used that can be presented to the application that can be checked against the original key to ensure that the authentication was not compromised. After that the user is authenticated and again the application handles permissions internally. In both scenarios, the authentication is time stamped to be valid only for a specific time. The time stamped token can be  ‘cached’ just like cookies are used in web application.

Jon White

Advertisements
Categories: Microsoft

White paper: maintaining and optimizing Microsoft Dynamics CRM 4.0

February 27, 2008 Leave a comment

The CRM Engineering for Enterprise (E2) team is pleased to announce the release of the white paper Optimizing and Maintaining Microsoft Dynamics CRM 4.0.

This document provides techniques, considerations, and best practices for optimizing and maintaining the performance of Microsoft Dynamics CRM 4.0 implementations. Structured to support a tier-based optimization methodology, the white paper includes a section dedicated to optimizing and maintaining each of the Client, Application, and Data tiers. For each tier, the document provides details about optimizing and maintaining the relevant components of the broader implementation. This paper also includes links to additional information and resources, such as performance enhancements, security updates, Knowledge Base articles, and related Microsoft Dynamics CRM documentation.

Please share this white paper with the broader Microsoft CRM Community and be sure to forward any comments about the document or suggestions for how we might improve it to entfeed@microsoft.com, the CRM Enterprise Content Feedback alias. The CRM E2 team intends to update this paper in coming months, the release schedule dependent in part on the nature and volume of the feedback we receive.

Jim Toland

Categories: Microsoft Dynamics

CRM 4.0 Relationships explained, many to many

February 17, 2008 6 comments

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 described here.

Relationships CRM 4.0

As you can see, the above gives you an enormous amount of flexibility on the types of relationships that you can model in CRM 4.0. Now let’s take a look at specific CRM 4.0 enhancements.

Backend

We performed a huge redesign of relationships in our 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.

UX

One of the biggest requests that we had for CRM 4 was to enable customization of the labels that get displayed as part of relationships; furthermore, sometimes relationship are only used as a logical construct for backend operations and aren’t meant to be displayed; hence the ability to “hide” portions of the UI related to relationships was also a requirement. To accomplish all the above we introduced several metadata attributes that control the display behaviors of relationships.

· This screencast walks you to the creation of a simple N:N relationship and describes how different pieces relate to the UI.

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 createManyToManyTest(MetadataService metadataService)

{

ManyToManyMetadata manyToMany = new ManyToManyMetadata();

manyToMany.SchemaName = “new_relationship_name”;

manyToMany.IntersectEntityName = “new_intersect_name”;

//Side A

manyToMany.Entity1LogicalName = “account”;

manyToMany.Entity1AssociatedMenuBehavior = new CrmAssociatedMenuBehavior();

manyToMany.Entity1AssociatedMenuBehavior.Value = AssociatedMenuBehavior.UseLabel;

manyToMany.Entity1AssociatedMenuGroup = new CrmAssociatedMenuGroup();

manyToMany.Entity1AssociatedMenuGroup.Value = AssociatedMenuGroup.Details;

manyToMany.Entity1AssociatedMenuLabel = CrmUtils.CreateSingleLabel(“SIDE A pointing to Side B”, 1033);

manyToMany.Entity1AssociatedMenuOrder = new CrmNumber();

manyToMany.Entity1AssociatedMenuOrder.Value = 15001;

//Side B

manyToMany.Entity2LogicalName = “contact”;

manyToMany.Entity2AssociatedMenuBehavior = new CrmAssociatedMenuBehavior();

manyToMany.Entity2AssociatedMenuBehavior.Value = AssociatedMenuBehavior.UseLabel;

manyToMany.Entity2AssociatedMenuGroup = new CrmAssociatedMenuGroup();

manyToMany.Entity2AssociatedMenuGroup.Value = AssociatedMenuGroup.Details;

manyToMany.Entity2AssociatedMenuLabel = CrmUtils.CreateSingleLabel(“SIDE B pointing to Side A”, 1033);

manyToMany.Entity2AssociatedMenuOrder = new CrmNumber();

manyToMany.Entity2AssociatedMenuOrder.Value = 15001;

CreateManyToManyRequest manyToManyRequest = new CreateManyToManyRequest();

manyToManyRequest.IntersectEntitySchemaName = manyToMany.IntersectEntityName;

manyToManyRequest.ManyToManyRelationship = manyToMany;

metadataService.Execute(manyToManyRequest);

}

Adding records to 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 = @”<fetch version=””1.0″” output-format=””xml-platform”” mapping=””logical”” distinct=””true””>

<entity name=””lead””>

<attribute name=””fullname””/>

<order attribute=””fullname”” descending=””true””/>

<link-entity name=””new_account_lead_custom”” from=””leadid”” to=””leadid”” visible=””false”” intersect=””true””>

<link-entity name=””account”” from=””accountid”” to=””accountid”” alias=””aa””>

<filter type=””and””>

<condition attribute=””name”” operator=””eq”” value=””Foo””/>

</filter>

</link-entity>

</link-entity>

</entity>

</fetch>”;

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);

}

Cheers,

Humberto Lezama

Extending email integration

February 12, 2008 Leave a comment

The CRM 4.0 e-mail router provides an extensible framework based on the concept of e-mail providers and XML files. This article explains how you can extend the model to build your own highly specialized e-mail provider.

Out-of-the-box, the CRM 4.0 e-mail router includes different e-mail providers, each implementing a particular e-mail protocol. For example, the POP3 e-mail provider examines e-mails received by a POP3 mailbox, and calls into CRM to create e-mail activities. For example, the SMTP e-mail provider connects to CRM to download e-mail activities waiting to be sent, and composes then submits e-mails to an SMTP server.

For each type of e-mail provider, several instances may be activated. For example, at a given time, 5 instances of the POP3 e-mail provider may be running, each processing e-mails from one mailbox, and each delivering e-mail to a different CRM organization.

Any type of e-mail provider should accept configuration parameters (ex: name of the mailbox to connect to, name of the e-mail server to connect to, etc.). Some e-mail providers may also need to persist runtime state information as well (ex: time stamp of the last processed message, number of e-mails processed so far, etc.). Such state information should not be lost if, for example, the service is restarted.

Understanding E-mail Providers:

The following diagram describes the class hierarchy used to implement e-mail providers. The base-most class is called EmailProvider, and all e-mail providers derive from it. Intermediate classes provide additional behavior (ex: the PollingMailboxProvider implements a design pattern to connect to a mailbox using a configurable polling schedule). Derived-most classes correspond to actual e-mail providers (ex: the Pop3PollingMailboxProvider class is the POP3 e-mail router).

extendingEmail

Extending the Model:

There are two ways you can extend the model. You can:

  • Derive from existing e-mail provider classes to alter their behavior. For example, you may want to create a specialized POP3 e-mail provider which identifies certain keywords in the subject of processed e-mails, and creates alert records in CRM. In this case, starting an implementation from scratch could be expensive, because you will have to implement the entire POP3 client protocol. Using class derivation to provide partial specialization makes more sense.
  • Create new e-mail providers to provide totally new functionality. For example, you may want to create an e-mail provider which downloads RSS feeds, and creates e-mail activities in CRM. In this case, deriving from existing e-mail providers makes little sense, because none of them has anything to do with RSS technology or protocols.

In this post, we will focus on the second approach (the first approach will be discussed in a later post).

Analyzing Requirements:

You should start the design process by analyzing specific requirements:

  • What type of configuration parameters will each provider instance need?
  • What state information should each provider instance persist?
  • When should each provider instance run?
  • When should persisted state information be deleted?

Defining a Usage Scenario:

For illustrative purposes, we will discuss a hypothetical e-mail provider whose responsibility is to download RSS feed items and to create corresponding records in CRM. Each provider instance should know the name of the RSS feed to connect to, and whether a secure protocol should be used to connect.

Our provider state information should include the timestamp of the last processed RSS feed item. This will be used as a threshold date/time to incrementally download more recent RSS feed items. Note that this post will not provide an implementation of the code required to download RSS feed items. This exercise is left to the reader, because the key point is that you can decide to do about anything.

Designing Configuration XML:

We expect our configuration XML (which should be copied to Microsoft.Crm.Tools.EmailAgent.xml) to look as follows. For every <ProviderConfiguration> instance, an instance of the specified e-mail provider class will be instantiated. Each instance will be bound to one single XML fragment. Below, we assume that the class implementing our custom e-mail provider is called MyEmailNamespace.MyEmailProviderClass, and that it resides in assembly MyEmailAssembly.dll.

<ProviderConfiguration>

   <ProviderAssembly>MyEmailAssembly.dll</ProviderAssembly>

   <ProviderClass>MyEmailNamespace.MyEmailProviderClass</ProviderClass>

   <CrmServerUrl>http://MyCrmServer/MyOrg</CrmServerUrl&gt;

   <RssFeedName>cnn.newsalerts.com</RssFeedName>

   <RssUseSecureMode>true</RssUseSecureMode>

   <PollingPeriod>60000</PollingPeriod>

</ProviderConfiguration>

<ProviderConfiguration>

   <ProviderAssembly>MyEmailAssembly.dll</ProviderAssembly>

   <ProviderClass>MyEmailNamespace.MyEmailProviderClass</ProviderClass>

   <CrmServerUrl>http://MyCrmServer/MyOrg</CrmServerUrl&gt;

   <RssFeedName>msnbc.dailynews.com</RssFeedName>

   <RssUseSecureMode>true</RssUseSecureMode>

   <PollingPeriod>60000</PollingPeriod>

</ProviderConfiguration>

Starting a Project:

We recommend you follow these steps as a starting point:

a. Create a Visual Studio 2005 C# project

b. Add a reference to assembly Microsoft.Crm.Tools.EmailProviders.dll

c. Include a using statement for namespace Microsoft.Crm.Tools.Email.Providers

d. Create a new class called MyEmailProvider derived from EmailProvider

e. Implement a constructor

f. Override abstract methods and provide an implementation

e. Compile the assembly and place it under %program files%\ Microsoft CRM Email\Service

Here is what your implementation stub should look like at this point. The Check() method is not applicable to custom providers and can safely be ignored.

public class MyEmailProvider : EmailProvider

{

/// <summary>

/// Constructor.

/// </summary>

/// <param name=”providerConfiguration”>Provider configuration.</param>

/// <param name=”shutdownEvent”>Shutdown event.</param>

public MyEmailProvider(ProviderConfiguration providerConfiguration, ManualResetEvent shutdownEvent)

: base(providerConfiguration, shutdownEvent)

{

}

/// <summary>

/// Indicates if queuing should be accepted because the provider wants to perform some work.

/// </summary>

/// <returns>True if a work request should be queued, false otherwise.</returns>

public override bool AcceptQueuing()

{

}

/// <summary>

/// Executes an operation.

/// </summary>

public override void Run()

{

}

/// <summary>

/// Verifies that the provider works as expected.

/// </summary>

public override void Check()

{

}

}

Specifying Configuration Parameters:

The next step is to create class members which map to expected configuration XML parameters. For XML binding to work properly, we must use the supplied ProviderConfiguration.ConfigNodeReader member to access configuration parameters. Special functions are used to retrieve configuration parameters. The third argument indicates if an exception should be thrown when the XML node is missing. The second argument specifies a default value. In the example below, specifying parameter RssFeedName name is mandatory, while specifying parameter RssUseSecureMode is optional (the default being true).

/// <summary>

/// RSS feed name (read from the bound XML configuration node).

/// </summary>

public string RssFeedName

{

get

{

return this.ProviderConfiguration.ConfigNodeReader.GetCheckedStringValue( “RssFeedName”, null, true);

}

}

/// <summary>

/// RSS secure mode (read from the bound XML configuration node).

/// </summary>

public bool RssUseSecureMode

{

get

{

return this.ProviderConfiguration.ConfigNodeReader.GetCheckedBoolValue( “RssUseSecureMode”, true, false);

}

}

Specifying State Information:

The next step is to create members to manage persisted state information. For state persistence to work properly, we must use the supplied ProviderConfiguration.StateNodeReader member. Again, special functions must be used to retrieve and set state information.

/// <summary>

/// Time stamp of the last processed RSS item.

/// </summary>

public string RssThresholdDateTime

{

get

{

return this.ProviderConfiguration.StateNodeReader.GetCheckedStringValue( “RssThresholdDateTime”, DateTime.MinValue.ToString(), false);

}

set

{

this.ProviderConfiguration.StateNodeReader.SetStringValue( “RssThresholdDateTime”, value);

}

}

Ensuring Proper Scheduling:

The next step allows provider instances to get scheduled for execution. Providers cannot indicate when they should execute. Instead, they indicate whether they are ready to execute. Unless the system is busy, execution will happen shortly after scheduling. To indicate it is ready, a provider instance should return true when method AcceptQueuing() is called. This method is called quite frequently, so minimize the amount of effort spent making a decision. In the example below, scheduling is requested every 15 minutes (ideally, this value should become a new configuration parameter).

/// <summary>

/// Remembers the last time we ran.

/// </summary>

private DateTime lastTimeRan = DateTime.MinValue;

/// <summary>

/// Executes an operation.

/// </summary>

public override void Run()

{

this.lastTimeRan = DateTime.Now; // remember the last time we ran

}

/// <summary>

/// Indicates if queuing should be accepted because the provider wants to perform some work.

/// </summary>

/// <returns>True if a work request should be queued, false otherwise.</returns>

public override bool AcceptQueuing()

{

return (DateTime.Now > this.lastTimeRan.AddMinutes(15));

}

Implementing the Execution Routine:

The next step consists in implementing the Run() method. In our case, we will connect to the specified RSS feed and download the first item past the specified threshold. This will allow our implementation to keep downloading new messages. To ensure a graceful shutdown behavior, we will often check the result of method ShutdownRequested(). Also, after doing a sufficient amount of work, we should exit and wait for the next scheduling cycle. E-mail providers which do not comply with these rules may see their Run() method forcefully aborted by the scheduling engine.

/// <summary>

/// Executes an operation.

/// </summary>

public override void Run()

{

// Keep reading RSS feed items

int i = 0;

while (true)

{

// Stop on shutdown

// Stop when enough work has been done for the current cycle

if (this.ShutdownRequested() || (10 < ++i))

break;

// Process the next item from the specified RSS feed

// This function should return the first item whose time stamp is

// past the specified threshold

RssFeed feed = DownloadFeedItemAndTrackInCrm(this.RssFeedName,

this.RssUseSecureMode, this.RssThresholdDateTime);

if (null == feed)

break; // empty feed

// Update the threshold (set it to the current item’s timestamp)

this.RssThresholdDateTime = feed.TimeStamp;

}

// Remember the last time we ran

this.lastTimeRan = DateTime.Now;

}

Managing State Information:

After completing the previous steps, your e-mail provider should be fully functional. But one important question remains: what if someone modifies the configuration XML file? The e-mail router implements a scheduling engine which automatically detects and accounts for such changes (ex: you do not need to restart the e-mail router service for them to take effect). If you add a new XML fragment, a new instance will automatically be created and scheduled. If you delete an existing fragment, the instance will be deleted from memory and stop executing (all associated persisted state information will be deleted as well).

Things become more complicated when an existing XML fragment is modified. Some changes may be significant enough that the change should be treated as a delete followed by an add (all associated persisted state information should be deleted). But some changes may be small enough to justify keeping persisted state information around.

For example, if you change the RssFeedName parameter of a <ProviderConfiguration> XML node, then persisted state information should be deleted, because it contains a threshold date which is now meaningless. But if you only change the RssUseSecureMode parameter, then the threshold date should be preserved, because otherwise processing for the same RSS feed will start from scratch.

In other terms, you need to define which parameters define a provider instance’s identity. As long as the identity remains unchanged, persisted state information will be preserved. By default, a cryptographic hash is applied to all configuration parameters to define the identity. But you can override this behavior. In the example below, the RssUseSecureMode parameter does not participate in the provider instance’s identity any more. So even if it changes, state information will be preserved.

/// <summary>

/// Identity hash.

/// </summary>

public override string IdentityHash

{

get

{

return String.Format(CultureInfo.InvariantCulture, “{0}/{1}”,

this.GetType(), this.RssFeedName);

}

}

Conclusion:

This article describes how you can create new e-mail providers. The framework allows developers to delegate configuration, instantiation, persistence, and scheduling responsibilities to the e-mail router. In the future, we will discuss other approaches to extending e-mail integration.

Dominic Pouzin

Categories: CRM, Microsoft Dynamics