Wednesday, November 3, 2010

Displaying CRM emails using SSRS 2008

Email body in Dynamics CRM is stored in HTML format and when we try to display the data as is in the SRS report, it shows up with all the HTML tags.
Microsoft Dynamics CRM reports strip the HTML content and display it in Plain text format.
Now with SSRS 2008, you can display them with part of the HTML formatting. It does not support all the HTML tags as yet, but some basic tags are supported that help provide a presentable view of the email body.

Let’s take an example, we will create sample email as shown below.


To show same content in SSRS report 2008 we need to follow the below steps:

  1. Place a textbox control on report and within it place the PlaceHolder by right clicking inside textbox and choose PlaceHolder.

  2. Set the properties of the 'PlaceHolder', change Markup type to HTML.

  3. Extract description(body) of email by query eg. Select description from filteredemail where activityid='A0773451-3DE3-DF11-9EAB-0003FFD4167C'

  4. Set the expression value of the placeholder to description, from dataset fields.( For e.g. Fields!description.Value).

  5. Review the report to see the following result.



Hope this helps...Time to move on to SSRS 2008!

Tuesday, October 26, 2010

Field Level Security in CRM 2011

CRM 2011 will now allow to decide permissions not just at the record level but also “Field Level”. This means that you can decide if a user has the permission to that attribute at the time of Create or Update or simply view the data for that attribute.

Currently, this feature is only available for the custom attributes that you add. They are not available for the system attributes. When you create a new attribute you can enable “Field Level Security” for that attribute.



Once the attribute has been defined for Field Security, it becomes available for defining the security levels for different roles.

Similar to the Security roles, you can now create Field Security Profiles



The profile lists out all the attributes setup for Field Security and you can edit the permission to Read, Update and Create.

Note any security that you apply here is not just available/applicable on the CRM forms, but also programmatically. So if you try to edit a custom attribute of an entity for which you do not have permission to edit, field security will be enforced and you will not be allowed to update the record. You will receive an error.

Field security can also be specified at the time of sharing a record.



You can specify the permission to each user with which the record has been shared and the permission for the secured fields.

Friday, October 22, 2010

Issues with class level declaration in CRM 4 Plugins and Workflows

It is important that you avoid class level declaration and initialization of variables in Plugins and Workflows.

Let us discuss the issues that one can face with Plugins. Plugins as you know is executed synchronously. But if there happen to be multiple calls made to the same plugin assembly and class, a new object for the Plugin is not always created. Instead the same object is reused. So if you have initialized a class level variable at the start and not in the Execute method, it will be initialized only once at the start and there after for subsequent calls the plugin will reuse the last value stored in the variables much like the static variables.

An example of this would be

public class MyPlugIn : IPlugin
   {
      ICrmService _service = null;
      Bool _myBool = false;

public void Execute(IPluginExecutionContext context)
   {
       //Check if particular field contains data then set the _myBool as true
   {
       _myBool = true;
   }
      //Update record with _myBool Field.
   }
   }

_mybool is initialized to be false only once at the start. If for some execution the condition succeeds and the value is set to true. The next call to this plugin would use the _mybool value as true by default not initialize it to false.

This behavior can be replicated using the Bulk Edit feature of Dynamics CRM. If you have a plugin registered for the Update method and you use the Bulk Edit feature to update multiple records at one go, the plugin would fire for each of the records modified but the _mybool variable will only be initialized once.

It would be advisable to ensure that class level variables are initialized in the Execute method each time.

Workflow Issues:

If you happen to declare the ICrmService variable at class level in a workflow assembly and make a call to that assembly in step 1 of the workflow and have step 2 that performs another action in the same workflow, the workflow would go into Waiting and not close with a completed or failed status.

The Workflow error message will display the following error for the Workflow job.

Workflow paused due to error: Unhandled Exception: System.Workflow.Runtime.Hosting.PersistenceException: Type 'Inogic' in Assembly 'Inogic, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' is not marked as serializable. at System.Workflow.Runtime.WorkflowExecutor.Persist(Activity dynamicActivity, Boolean unlock, Boolean needsCompensation) at System.Workflow.Runtime.WorkflowExecutor.System.Workflow.ComponentModel.IWorkflowCoreRuntime.PersistInstanceState(Activity activity) at System.Workflow.ComponentModel.Activity.MarkClosed() at System.Workflow.ComponentModel.Activity.MarkCompleted() at System.Workflow.ComponentModel.ActivityExecutionContext.CloseActivity() at System.Workflow.ComponentModel.ActivityExecutorOperation.Run(IWorkflowCoreRuntime workflowCoreRuntime) at System.Workflow.Runtime.Scheduler.Run() Inner Exception: System.Runtime.Serialization.SerializationException: Type 'Inogic' in Assembly 'Inogic, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' is not marked as serializable. at System.Runtime.Serialization.FormatterServices.InternalGetSerializableMembers(RuntimeType type) at System.Runtime.Serialization.FormatterServices.GetSerializableMembers(Type type, StreamingContext context) at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitMemberInfo() at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitSerialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter) at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.Serialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter) at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Serialize(Object graph, Header[] inHeaders, __BinaryWriter serWriter, Boolean fCheck) at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph, Header[] headers, Boolean fCheck) at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph) at System.Workflow.ComponentModel.Activity.Save(Stream stream, IFormatter formatter) at System.Workflow.ComponentModel.Activity.Save(Stream stream) at System.Workflow.Runtime.Hosting.WorkflowPersistenceService.GetDefaultSerializedForm(Activity activity) at Microsoft.Crm.Workflow.CrmWorkflowPersistenceService.SaveWorkflowInstanceState(Activity rootActivity, Boolean unlock) at System.Workflow.Runtime.WorkflowExecutor.Persist(Activity dynamicActivity, Boolean unlock, Boolean needsCompensation)

This is again because of the declaration of the CRM service object at the class level. The variable is not released after the completion of job if the variable is defined at class level and hence conflicts with the steps that follow in the same workflow job.

[CrmWorkflowActivity("Customer Search")]
Public partial class CustomerSearch: Activity
{
public static ICrmService crmservice = null; // or make it as function level reference
…… Execute(…….) { }
………..
}

Moving the ICrmService object declaration from Class level to the Execute method ensure that the object is released upon the completion of the job.

protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
{
ICrmService crmservice = null;
Processing…..
}

hopefully this solution will help you to avoid custom WF error. Any feedback on this blog is commendable.

Wednesday, October 20, 2010

Multiple Form Layouts for a single entity in CRM 2011

Another of CRM 4 shortcomings covered in CRM 2011.

There is often a request to have certain fields available/shown to only a certain set of users based on their security role. CRM 2011 have brought in field level security but it has also added the concept of designing multiple forms for a single entity.

While in CRM 4.0 requests for hiding or displaying a field was taken care of through scripting, this is now available in CRM 2011 as a feature. You can create multiple forms and then assign a particular form to a certain security role.

You can create a new form by choosing the Main Form option


Design the form as required and then assign security role to the form


Note: You can notice the checkbox shown on this form at bottom “Enabled for fallback”. This notifies that the form will be shown to the users with roles which did not have any form explicitly assigned for them. There will always be one form that has this option enabled.


If a user has different roles as a result of which there are multiple forms for an entity that can be used by the user, the form that gets displayed by defult depends on the order provided for the forms.



The default form displayed can be changed by the user who has access to more than one form layout by choosing the appropriate form from the Form Navigator. The form last chosen is recorded as the form to be used by the user for the next time.


Note each individual form supports its layout and is independent of the other form layouts. Changes done to the form like left navigation, header, footer, body changes will get applied to individual form only.

Check back with us soon for more features to be explained…

Monday, October 18, 2010

How to Show address using Bing Map in CRM 2011?

CRM 2011 provides a different feature to use java script as compared to CRM 4. In CRM 2011 you cannot write script directly in form event. Here they have provided a facility to create form library where you can write your own java script function. Only after creating a form library user will be able to call the function on form or field event.

To use the script on field or form event you will need to add a event handler, where you can specify the web resource library file and function name.

Follow the steps to create a form library file as shown below in the Screen shot.

• Click on Add button to add new form library


• You can add existing web resource or can add new web resource. Fill the details as below screen shot. To add the script click on Text Editor button and write the script.


• To use this function on Form load event you need to add event Handler and write the function as below screen shot.

• Select the library name in which you have write the script function and function name as below screen shot.

• Now save and publish the entity.

Note: if user is doing any modification on form library file then you need to go to web resource and select file and Publish it.

When you will open records, the Bing map will plot location in map.

Hope this help to understand how to use Bing map in CRM 2011.