Wednesday, October 21, 2009

Notes and Attachments


Almost every Entity in CRM has support for Notes and Attachments.
A Note could be almost any piece of text which does not fall under any of the CRM Activity types.(phone,fax,email etc.)
Attachment lets to attach any kind of documents (doc,xls,pdf,image files etc) to a particular record in CRM.


The Notes tab in CRM, allows you to create just a note, however if you need to create a note with an attachment, you will need to browse to Actions->Attach a Note on the menubar of the particular record.


All Notes go into the annotationbase table on the CRM DB.
Even attachments if any, associated with a note are stored in this table.
This architecture allows the attachements to the accessed even via the Outlook Client in Offline mode.


Imp: Only 1 file can be attached per Note.


Create Notes using the CRM SDK:
//Create a simple note
annotation note = new annotation();
note.notetext = "This is a note";
EntityNameReference entRef = new EntityNameReference();
entRef.Value = "account";
note.objecttypecode = entRef;
note.objectid = [GUID of the account record];
crmService.Create(note);


//Create note with an attachment
annotation note = new annotation();
note.notetext = "This is a note";
EntityNameReference entRef = new EntityNameReference();
entRef.Value = "account";
note.objecttypecode = entRef;
note.objectid = [GUID of the account record];
Guid noteID = crmService.Create(note);


UploadFromBase64DataAnnotationRequest uploadFile = new UploadFromBase64DataAnnotationRequest();
uploadFile.AnnotationId = noteID;
uploadFile.FileName = "Example.txt";
uploadFile.MimeType = "text/plain"; //Other possible values 'application/msword' for word doc
//Since this file would be stored in the CRM DB, the file must be converted to a base64 encoded string
uploadFile.Base64Data = GetBase64StringFromFile("Example.txt");
crmService.Execute(uploadFile);


private static string GetBase64StringFromFile(string filename) {
using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read)) {
using (BinaryReader reader = new BinaryReader(fs)) {
byte[] fileContent = reader.ReadBytes((int) fs.Length);
return Convert.ToBase64String(fileContent);
  }
 }
}


//Retrieve Attachment from CRM
On the CRM domain one can use the below url to download an attachment directly from the CRM Server
http://[server:port]/[organization name]/Activities/Attachment/download.aspx?AttachmentType=5&AttachmentId=[Annotation ID]


The above url will prompt the user to either Open or Save the the particular attachment.


//The below SDK approach can also be used to download an attachment
Private byte[] GetAnnotationAttachment(Guid annotationId){
Guid attachid = annotationId;
//Pass the Annotation attachment OTC and the Annotation ID
http://[server:port]/[organization name]/Activities/Attachment/download.aspx?AttachmentType=5&AttachmentId=[Annotation ID]
System.Net.WebClient myWebClient = new System.Net.WebClient();
myWebClient.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
return myWebClient.DownloadData(url);
}


byte[] exampleByteArray1 = GetAnnotationAttachment(new Guid("D7D5E13B-E3B4-DE11-A647-00012E0B81A2"));
Response.ContentType = "application/octet-stream";
Response.AppendHeader("Content-Transfer-Encoding", "binary");
Response.AppendHeader("content-disposition", "attachment; filename=" + "Sample.xls");
Response.BinaryWrite(exampleByteArray1);

Thursday, October 15, 2009

Microsoft CRM 5.0 ..... On Your Way


CRM5 is currently on the way and most likely to be shipped sometime in early 2010.
(CodeName :  Microsoft Dynamics CRM “V.Next”)
So what can we expect...... read below for the answers

New Features for Users
========================

Enhanced Navigation
CRM5 uses the same "Fluent UI" (aka the Ribbon) as Office 2007. This new "command bar"
replaces the CRM 4.0 "tool bars" at the top of each page, and is
context sensitive. In addition, the "command bar" is fully
customizable and you can add your own buttons much like you can with ISV.Config
file today.


No more Tabs
The form model in CRM 4.0 made use of tabs to divide a form into multiple
pages.
In CRM5 tabs are displayed in the same way as section, with each form just
having a single, scrolling page.

Grid Filtering
Apart from sorting, CRM5 now allows filtering on any available column in
the Grid, much like Excel
Possibly there would be an option to save the filtered view as well.

In-line Visualizations
CRM5 allows you to visualize numeric data using in-line charts
within the form itself. This is not SQL Server Reporting Services, but looks
very much like the .NET charting solution from Dundas.
One can select a number of different chart formats such as Bar, Column, Funnel, Line, Pie & Scatter.

Team Ownership
CRM5 now also supports Team Ownership apart from the already existing ones (User owned and Organization owned). A good needed feature indeed.

Sharepoint Integration
Integration with Windows Sharepoint Service now comes Out of the Box
This includes document management, which includes site and document library
provisioning, document metadata, item security, and check-in/check-out
capabilities.

Queue
CRM5 now seems to support the "Add to Queue"
command, from which we believe the one should be able to add any entity
(including custom entities) to a Queue.

New Features for Administrators
=======================
 

Form  Layout
More flexibility has been added to Form Design, wherein Administrators can
now position sections side-by-side, field label can be positioned on the
top,left , right for any control
But the one below takes the icing on the cake.
Inline Child Grids are now supported OOB for related child entities. You now
don’t need custom coding to make this work.

Filtered Lookup
Finally one of the most desired feature since the 1.2 release, has made its
presence available in CRM5.
A lookup can now be customized to display data from any pre-defined view or
filter by related lookup on the same form.

Form Headers & Footers
Since all fields,sections,tabs now come on a single page,  a form could become quite long, and scrolling to find the required fields  could be a headache.
CRM5 now supports placing the commonly required fields on the header or footer, so that they will always be displayed regardless of the
scrolling.

Solution Management
With CRM 4.0, you had to implement a manual process when customizing your
solution, to make sure that you didn't overwrite previous customizations, or
disrupt any 3rd party ISV solutions. In CRM5 we had now added the concept of
solutions.

      A solution is a defined set of entity customizations, workflows, e-mail
      templates, security roles, plug-ins etc. that can be managed as a single
      unit. Each solution is version controlled so presumably your can have
      multiple versions of the same solution installed, and roll-back to a
      previous version if necessary.

      You can also define solution dependencies where one solution can only be
      installed if another solution is also installed. For example, you might
      have a base solution for your whole organisation, with a departmental
      specific solution built on top of it.

      Namespace collision is avoided by defining publishers, with each publisher
      having a unique namespace. This avoids the common issue where the
      default namespace "new_" is used for all customizations, leading to
      potential namespace conflicts.

      One final plus point is that you can now specify which attributes will be
      exported as part of a solution, rather than having no choice but to export
      the whole entity.

Global Picklists
With CRM5, you now have the option of defining a Global Picklist,
which can be used across multiple forms.

Drag & Drop Form Editor
One of the most time consuming customization tasks in CRM 4.0 is the form
design. Every time you want to add, remove or re-position tabs, sections and
attributes, you have to go through a multi-click process. With CRM5, you can
now drag and drop all elements of a form, speeding up the process considerably.

Audit
Audit functionality on attribute level, it seems now comes OOB.
An Auditing  field now appears within the
Attribute setting, which can be set to True or False.

New Features for Developers
====================


Custom Code Sandbox
There is a new server role for running custom plug-in code and custom
workflow activities without requiring full trust. This means that it will be
possible to run custom code in the CRM Online environment and achieve true
parity between On-Premise, Partner-Hosted and Microsoft-Hosted deployments.


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 right your own compensation logic in the event the CRM platform
operation failed. CRM5 addresses this limitation and you can now choose to
register you plug-in as part of the platform operation. The CRM5 plug-in
registration tool has been modified to support this.

Automatic Plug-In Profiling
CRM5 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.

Related Videos
BB08 Microsoft Dynamics CRM: The Appealing Business Application

BB32 Microsoft Dynamics CRM: Building Line-of-Business Applications

Courtesy :  http://blogs.msdn.com/ukcrm/archive/2008/11/10/what-s-new-in-crm5.aspx

















Thursday, September 3, 2009

Scripting (Update Currency Symbols) - MSCRM 4.0


Recently we had a scneario wherein the currency field on the opportunity was to be set dynamically with the currency of the associated contact/account.
This currency is automatically set to the currency of the account/contact if the opportunity has been opened from within an account/contact, however it does not reflect the associated currency when the customer is changed.

So had to make an ajax call on the onchange event of the customer field to retrieve its associated currency and set it on the opportunity entity.
However this does not change the currency symbol values on the money fields on the form.
There seems to be an internal script being fired to update the currency symbols  whenever the currency is changed.
The same is not fired when the currency value is populated via javascript.

Below is the javascript which can be used to update the symbols whenever the currency is set dynamically:

//loops thru all controls on the form and sets the currency symbol
var oCtrl;
for (var i = 0; i < crmForm.all.length; i++)
{
      oCtrl = crmForm.all[i];
      if(oCtrl.tagName == "INPUT" && oCtrl.className == "ms-crm-Money-CurrencySymbol")
      {   
        //currencySymbol contains the actual symbol                             

        oCtrl.value = currencySymbol;  
      }                                                         
}

Search a text within a Trigger


Suppose you need to do a search for all triggers within a DB which has the text (say ‘delete from trn_cashflow’)

SELECT sysobjects.name AS [Object Name], text , * FROM
sysobjects, syscomments
WHERE
       sysobjects.id = syscomments.id
       and sysobjects.type in ('TR')
       and text like 'delete from trn_cashflow%'


Friday, August 28, 2009

CRM Video Resources for Training Users


A variety of short videos for helping new users get comfortable with Microsoft Dynamics CRM are available in this Resource Center. The most recent, Create a personal view, walks through defining criteria and columns, and saving the view for reuse.

Many to Many Relationship


Many to Many relationships is not something new to CRM 4.0, they existed in CRM 3.0 as well,
however there was no ability to create new many to many relationships in the previous version, which is available in the current version.
When a Many to Many relationship is created between 2 entities, a custom table is created to maintain the relationship, which is called as the relationship table.This table stores the primary key values of both the entities.

Associating Records with a Many to Many Relationship:Assuming there are 2 entities named 'Student' and 'Book' which have a Many to Many relationship.Here's a sample code which associates multiple 'Book' entity records to the 'Student' Entity record.


Moniker Moniker1 = new Moniker();
Moniker1.Id = studentid;
Moniker1.Name = EntityName.student.ToString();
//BookList is a list which contains the guid of the 'Book' entity records.
for (int x = 0; x < BookList.Count; x++)
{
// Create a request.
AssociateEntitiesRequest request = new AssociateEntitiesRequest();
// Assign the request a moniker for both entities that need to be associated.
Moniker Moniker2 = new Moniker();

Moniker2.Id = new Guid(BookList[x][0].ToString());
Moniker2.Name = EntityName.book.ToString();

request.Moniker1 = Moniker1;
request.Moniker2 = Moniker2;
// Set the relationship name that associates the two entities.
//Refer relationship properties in CRMrequest.
RelationshipName = [Enter the name of the Relationship here];
// Execute the request.
AssociateEntitiesResponse response = (AssociateEntitiesResponse)myCrm.Execute(request);
}


Retrieving Associated Many to Many Relationships records:Note : RetriveMultiple method cannot be used to retrieve the records associated with a Many to Many relationship.
The sample code below shows how to retrieve records having a Many to Many Relationships using the LinkEntity class.Here we retrive the Books associated with a student record.

// Create a query expression.
QueryExpression qe = new QueryExpression();
qe.EntityName = EntityName.book.toString();
qe.ColumnSet = colSet;
// Create the link entity from book to student
LinkEntity leToRetrieve = new LinkEntity();
leToRetrieve.LinkFromEntityName = EntityName.book.toString();
leToRetrieve.LinkFromAttributeName = "bookid";
leToRetrieve.LinkToEntityName = [Enter the name of the Relationship table here];
leToRetrieve.LinkToAttributeName = "bookid";
LinkEntity leASFilter = new LinkEntity();
leASFilter.LinkFromEntityName = [Enter the name of the Relationship table here];
leASFilter.LinkFromAttributeName = "studentid";
leASFilter.LinkToEntityName = EntityName.student.toString();
leASFilter.LinkToAttributeName = "studentid";
// Create the condition to test the user ID.
ConditionExpression cExpression = new ConditionExpression();
cExpression.AttributeName = "studentid";
cExpression.Operator = ConditionOperator.Equal;
cExpression.Values = new object[] { [STUDENT GUID] };
// Add the condition to the link entity.
leASFilter.LinkCriteria = new FilterExpression();
leASFilter.LinkCriteria.Conditions = new ConditionExpression[] { cExpression };
// Add the from and to links to the query.
leToRetrieve.LinkEntities = new LinkEntity[] { leASFilter };
qe.LinkEntities = new LinkEntity[] { leToRetrieve };
RetrieveMultipleRequest request = new RetrieveMultipleRequest();
request.Query = qe;
request.ReturnDynamicEntities = true;
RetrieveMultipleResponse response = (RetrieveMultipleResponse)crmService.Execute(request);
bec = response.BusinessEntityCollection.BusinessEntities;

Refer the below link for an fetchXml solution by Ranjit Raghuwanshi.http://mscrm-developer.blogspot.com/2008/09/retrieve-associated-records-for-many-to.html

Relationship Mapping (CRM 4.0)


You might have noticed, how certain fields are automatically populated sometimes, whenever a new form is opened from the CRM UI.
Try creating a new Case from the Contract form. The customer and contract fields are automatically populated on the new Case form. Similar for various other entities too.
CRM provides an excellent functionality but often quite ignored of automatically mapping attribues from one entity to another within a 1:many relationship.

Open the CRM window and goto  Settings  -> Customization  ->  Contract  -> 1:N Relationships  -> contract_cases  -> Mappings


















There are 2 fields already mapped between the contract and case. It is this mapping which defines the fields to be populated when a new Case form is opened from its Parent Form (Contract)
You can use the ‘New’ button to define additional mappings. Mapping are not only related to system attributes, you can define them for custom attributes as well.

Note : Mappings can be defined only for entities having a 1:many relationship

Mapping can be defined for most Entities : Account to Contact, Opportunity to Quote, Quote to Order, Order to Invoice, Contract to Case etc.
So if you try converting a Quote to an Order, you will notice that all fields of the Quote and QuoteDetail are automatically pushed into the SalesOrder and SalesOrderDetail

However consider a scenario, where you need custom fields on QuoteDetail to be transferred to the custom Fields available on the OrderDetail. If you have a look at the QuoteDetail relationships, you will find that no relationship exists between the QuoteDetail and OrderDetail. So how do you go about mapping the custom fields.

Well, CRM definitely has a relationship between the QuoteDetail and OrderDetail Entities , however for some reason unknown, its hidden from the UI.

Here’s an UNSUPPORTED technique to unearth these relationships. So for the above example we need to transfer QuoteDetail custom attribute values to the  OrderDetail Entity.

Within SQL, run the below query:
Select * from entitymapbase where targetentityname = 'orderdetail'
This query should return 3 items, and we are concerned only  about the row with a SourceEntityName column value of  "quotedetail".
Copy the GUID value available in the EntityMapId column for the particular row
Paste the GUID at the end of the below URL
http://servername:port/orgname/Tools/SystemCustomization/Relationships/Mappings/mappingList.aspx?mappingId=

That opens up the secret mapping page ......  :-)  Happy Mapping
You can use this to map your custom fields as well.