Dynamics Light Seeing the (Silver)Light effect in Dynamics CRM

26Aug/100

Resources List from my TechEd Australia Talk

Just yesterday, I did a talk on xRM Ninja Secrets (#DEV342) at Microsoft Tech Ed Australia conference. Since this is my first TechEd presentation, I was really glad that it turned out pretty well. There was lots of excitement from the audience (thanks all for the feedback!).

So here is the list of tools / resources that I referenced in my talk. Note, there are also a lot of tips and tricks that I mentioned during the talk. Feel free to download the slide deck from here.

I’ll update the link to the recorded session once it’s published.

1. Stunnware Tools (www.stunnware.com)

2. Deletion Service Job Editor (http://code.msdn.microsoft.com/ScaleGroupJobEditor)

3. CRM Documentation Generator (http://crm4documentation.codeplex.com)

4. Google Closure – Javascript Minifier (http://closure-compiler.appspot.com/home)

5. CRM Web Service Toolkit (http://crmtoolkit.codeplex.com)

6. Auto Embed Javascript (http://www.xrmlinq.com/safely-add-script-references-to-dynamics-crm-pages)

7. Javascript Audit Add-On for Microsoft CRM (http://crmjavascriptaudit.codeplex.com)

8. External View for Microsoft CRM Online (http://crmexternalview.codeplex.com)

9. Javascript Intellisense Generator for Microsoft CRM (http://crm.vdsnickt.eu/ms-crm-javascript-intellisense)

10. View Layout Replicator (http://mscrmtools.blogspot.com)

11. Access Checker for Microsoft Dynamics CRM (http://mscrmtools.blogspot.com)

12. MSCRM Audit / Track Changes Add-On (http://crmaudit.codeplex.com)

13. Field Level Security for Microsoft CRM (http://www.thuta.info)

14. Microsoft Dynamics CRM Online (http://crm.dynamics.com)

15. MSCRM 4.0 SDK (http://www.microsoft.com/downloads/details.aspx?FamilyID=82e632a7-faf9-41e0-8ec1-a2662aae9dfb)

Shameless Plug

During the talk, I mentioned two of my Dynamics CRM open source projects. The Javascript Audit and External View. Feel free to download these and let me know your feedback. Would love to get some feedback from the community on what you would like to see on the vNext of these add-ons.

Getting Started

One of the delegates asked me a question on what’s the best way to get started with MSCRM if he isn’t a Microsoft CRM Partner. So I thought I’ll share my answer here so that everyone could benefit from it.

What I suggested is to first download the SDK and sign up for the Trial Account for Microsoft Dynamics CRM Online (http://crm.dynamics.com). If you are outside US and want to trial Dynamics CRM Online, ensure that you selected United States from the country dropdown list.

For the most part, the development experience will be similar to the CRM On-Premise version. On top of that, I highly encourage you to sign up for the CRM 2011 Online Public Beta. Once the Beta is released on September 2010, you will have access to it and start to experience the awesomeness of CRM 2011.

Filed under: Microsoft CRM No Comments
11Aug/103

Hear me speak at AU TechEd!

It’s less than two weeks before AU TechEd and I’m really pumped with all the buzz and excitements around it! There was also a rumour floating around that Windows Phone 7 will be launched at AU TechEd. Not sure how much of this is true, but would love to see some WP7 love.

Looking back few weeks ago, I wouldn’t have thought that I’ll come down to AU TechEd as a speaker. That’s until I received an email saying that my breakout session has been approved! Followed by another email few days ago congratulated me that my Interactive Theatre talk has been approved as well.

So, here are the sessions that I will be presenting:

- THGTU03 Dynamics CRM Online & Windows Phone 7: A duet made in the cloud
  Tuesday 24 August 19.00 – 19.30 | Green Theatre
Dimaz Pramudya will do a quick lap around building WP7 application that integrates with Dynamics CRM Online. The demo will show how easy it is to build a service that pulls down the data from CRM Online and automatically convert them to JSON format for consumption within the WP7 app. There will be few interesting UX tips and tricks shown during the demo.

- DEV342 xRM Ninja Secrets
  Wednesday 25 August 15.30 – 16.45 | Meeting Room 6
xRM has been quite a buzzword these days. Every time you hear about xRM, you'd think about building virtually any solution on top of the extensible Microsoft CRM platform. Having said that, there are a number of limitations that come with Microsoft CRM 4.0. In this session, we will have a look at ways to overcome these limitations as well as sharing some of the ninja tips and tricks aruond building xRM solution on top of Microsoft Dynamics CRM 4.0. The session will also cover a quick lap around the new Advanced Developer Extensions SDK feature.

So, if you haven't booked your ticket yet, do so right away! As of last night, there were 100 tickets left and they are selling fast!

Looking forward to see you all there.

EDIT: During TechEd, I will also be around the Dynamics Showcase booth. Come see me if you want to find out the things you can do with Dynamics CRM. (Thanks for the reminder Nick)

//D

Filed under: Microsoft CRM 3 Comments
13Jul/101

Windows Phone 7 Execution Model

MSDN has a great article explaining the Execution Model for Windows Phone 7. In a nutshell, Windows Phone 7 supports 5 different lifecycles (Launching, Running, Closing, Deactivated, and Activated).

The interesting ones are Deactivated and Activated. These events are provided to perceive user that the phone supports ‘multi-tasks’. Developers can take advantage of these events to store the transient data into the ‘State’ dictionary object during Deactivated event and read them back during Activated event.

Keep in mind that there is a time limit imposed on the Deactivated event. Any actions taken in the Deactivated event handler must be completed within ten seconds or the Operating System will automatically terminate the application. Therefore, if you want to persist a huge amount of data, you may want to save them incrementally by taking advantage of the Running event.

For more details, refer to the following diagram.

Ff817008.5e84773d-ae0d-43b8-a956-ffdac77b2922(en-us,VS.92).png

Filed under: Microsoft CRM 1 Comment
29Jun/105

Fuel My Car – Windows Phone 7 App

I attended Melbourne Bizspark Camp which was held last week at Microsoft Freshwater. The camp itself started with a workshop session on Friday followed by 2 days of hands-on stuff for building application for Windows Phone 7. Due to work commitment, I wasn’t able to make it to the workshop on Friday.

So I turned up on Saturday morning with one of my colleague from Oakton (Jonathan Hao) with expectation to learn new tips & tricks from Dave Glover and Nick Randolph. These guys are one of the best when it comes to Windows Phone 7.

Dave kicked off the hands-on day by announcing a competition for building a proof-of-concept application for Windows Phone 7. So I decided to team up with Jonathan and after a 5 minutes brainstorming, we came up with an idea to build Fuel My Car. After 2 days of very little sleep (and I blame World Cup for that) and a dreaded presentation on Sunday afternoon, we were awarded as the winner of the Melbourne WP7 Bizspark Camp. I was truly surprised and didn’t expect this coming. I would like to thank Dave and Nick for their great advice. Thanks a lot guys!

In a nutshell, Fuel My Car is a social mobile application that one can use to find nearby petrol stations. It uses the current user location to determine the closest petrol stations. The user can also mark petrol stations as their favourites and they will be displayed under the ‘favourites’ panorama item.

Once the user tap on one of the petrol station, they can see additional information for that petrol station such as the address / contact details as well as the pricing for different type of fuels available. The plan is to make this more social in a way that they can punch in the pricing into the app as they drop by the petrol station. When we were building this application, we want to make sure that the application still ‘works’ under all circumstances (including offline scenario).

disconnected-behavior favorite-stations nearby-stations station-detail

Here are some of the UX design decisions behind the user interface:

- For the home screen, we decided to use the Panorama control (http://phone.codeplex.com) as it provides a sleek and consistent user experience. The panorama items displayed on the home screen are not tightly related to each other, hence lend itself to the concept offered Panorama control.

- For the Petrol Station detail screen, we decided to use the Pivot control as it displays a more tightly related information for that particular petrol station. We used the Silverlight 3 Visifire (www.visifire.com) charting control to render the dynamic charting. Note: currently Visifire doesn’t have a supported version for WP7, however their Silverlight 3 version works fine with WP7. We also utilized the PhoneCallTask which will show the phone call popup when you tap on the phone number.

- The one effect that I really love is the offline effect. Took me a while to work out what’s the best way to show the offline status to the user. At first, with my developer hat, I was tempted to just put a label somewhere on the screen with a red-bolded text that says ‘Offline’. After further thoughts, this awesome idea came to me while I was having shower. Would it be cool to change the image saturation to gray-ish style when the app goes offline? Didn’t take me long to implement it and I was really impressed with it (and I think the judges too!)

I hope this inspire people to build more and more mobile application on WP7.

Filed under: Microsoft CRM 5 Comments
19Jun/101

MSCRM Javascript Audit

One of the biggest pain point from doing client-side customization in CRM 4 is not having auditing (track changes) capability each time you make changes to your Javascript. Normally, we have to get around this by storing all javascripts in source control so that we can see what’s changed / rollback if necessary. While this is ok for small customizations, this could lead into a tedious process in the long run.

So, I managed to develop this little plugin to do exactly that. It will log any javascript changes you made, being in the form level or field level. It will also work across standard CRM form and Mobile form. Due to the nature of plugin, it only works on MS CRM 4 On-Premise deployment.

For the technical side of things, this plugin only listens to the Publish event (not PublishAll) for performance reason. The way it works is pretty simple. It captures the Pre and Post-entity customization file and compare the javascript codes. Any changes detected will be written to the custom entity called Javascript Audit Log. This way, you could easily identify changes you made to the javascript code and enables you to rollback easily if something goes wrong.

You can find all the installation files and source code in http://crmjavascriptaudit.codeplex.com Hopefully this feature will be included in MSCRM vNext.

I will update this post with screencast on Getting Started soon (after the Socceroos soccer match) :)

Filed under: Microsoft CRM 1 Comment
19Jun/102

MSCRM Development Tips & Tricks #4 – etc VS etn

In Microsoft CRM 4, when you open up the custom entity CRM form in edit mode, you will see the URL looks something like edit.aspx?etc=10020.

The 10020 represents the object type code number for the custom entity that we created. Generally speaking all entities in MS CRM has objecttypecode associated with them. However, for built-in entities, we don’t generally see it popping up on the querystring.

So let’s say you built an xRM solution that has a magic button. When the user click on this magic button, it will open up a CRM form for one of your custom entities. Your application need to know how to construct the correct URL for the CRM form to render. There are a number of ways to do this.

First, you can pass in the objecttypecode in the querystring so that it looks like the above example (etc=10020). While this looks like a reasonable approach, there are few issues attached to it. In order to get the objecttypecode, you will need to query the metadata service, which means an extra call to the service and therefore have a reasonable impact on the performance of your application. The bigger issue is objecttypecode is NOT transferable across multiple environment. So if you are working with multiple environment (eg: DEV, SIT, PROD), chances are your custom entity will have different objecttypecode on different environment.

So what’s the better approach? Here comes etn to the rescue! Instead of passing objecttypecode, you can pass in the logical name of your custom entity to the querystring. Now your querystring will look like etn=new_myentity. MSCRM will automatically recognize the etn querystring and display the form accordingly. This approach saves you from having to query the metadata service to retrieve the objecttypecode. On top of that, this approach works across multiple environment without having to change anything.

Filed under: Microsoft CRM 2 Comments
11Apr/100

Investing your .NET Skill in Microsoft Dynamics CRM

Here are the three parts screencast from my recent talk at Melbourne xRM User Group on Investing Your .NET Skill in Microsoft Dynamics CRM.

The first part talks briefly about some of the key features of Microsoft Dynamics CRM and why would you want to invest your .NET skill on it.

Investing your .NET skill in Microsoft Dynamics CRM - Part 1 from Dimaz Pramudya on Vimeo.

The second part is where I do the demo of these key features using the XRM VPC which can be downloaded from the PartnerSource.

Investing your .NET skill in Microsoft Dynamics CRM - Part 2 from Dimaz Pramudya on Vimeo.

The last part contains a demo on how easy it is to enhance your existing application by harnessing the power of Microsoft Dynamics CRM. For the demo, I built a Car Rental Management (CRM) solution to demonstrate the xRM concept.

Investing your .NET skill in Microsoft Dynamics CRM - Part 3 from Dimaz Pramudya on Vimeo.

The code for the Car Rental Management solution can be downloaded from here. :)

Hope you enjoy the screencast. Feel free to contact me if you have any questions. :)

Filed under: Microsoft CRM No Comments
11Apr/106

MSCRM Development Tips & Tricks #3 – Connecting to MSCRM Online

Connecting to Microsoft CRM Online involves acquiring the Windows Live Id ticket which then used to authenticate against Microsoft CRM Online. As a result, Microsoft CRM will give you back a CrmTicket value which you can use throughout your session to query / modify CRM data.

There is a sample on how to achieve this using Passport authentication in MSCRM SDK. This approach uses the IdClrWrapper.dll to get the Windows Live Id ticket, which internally executes an unmanaged code. While this works great in our Full trust development machine, it failed miserably in shared hosting environment which runs Medium or High trust level.

What I wanted to share today is an alternative way to get the Windows Live Id ticket that works virtually on any environment. :) This method uses the RPS (Relying Party Suites) authentication option for Windows Live.

You are not just limited to use this LiveIdTicketAcquirer class for MSCRM Online, but you can also use it for other Windows Live Service offerings like Live Contacts, Live Mesh, etc.

using System;
using System.IO;
using System.Net;
using System.Xml;
 
namespace TTprotons.Crm.ExternalView.Service.Crm
{
    /// <summary>
    /// Handles the retrieval of Live Id ticket.
    /// </summary>
    public class LiveIdTicketAcquirer
    {
        #region SoapMarkUp
 
        private const string applicationId = "10"; // An arbitrary value that will be defined in the next non-alpha release
 
        private const string soapEnvelopeTemplate = @"<s:Envelope
            xmlns:s = ""http://www.w3.org/2003/05/soap-envelope""
            xmlns:wsse = ""http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd""
            xmlns:saml = ""urn:oasis:names:tc:SAML:1.0:assertion""
            xmlns:wsp = ""http://schemas.xmlsoap.org/ws/2004/09/policy""
            xmlns:wsu = ""http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd""
            xmlns:wsa = ""http://www.w3.org/2005/08/addressing""
            xmlns:wssc = ""http://schemas.xmlsoap.org/ws/2005/02/sc""
            xmlns:wst = ""http://schemas.xmlsoap.org/ws/2005/02/trust"">
            <s:Header>
                <wlid:ClientInfo xmlns:wlid = ""http://schemas.microsoft.com/wlid"">
                    <wlid:ApplicationID>" + applicationId + @"</wlid:ApplicationID>
                </wlid:ClientInfo>
                <wsa:Action s:mustUnderstand = ""1"">http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue</wsa:Action>
                <wsa:To s:mustUnderstand = ""1"">{4:url}</wsa:To>
                <wsse:Security>
                    <wsse:UsernameToken wsu:Id = ""user"">
                        <wsse:Username>{0:userName}</wsse:Username>
                        <wsse:Password>{1:passWord}</wsse:Password>
                    </wsse:UsernameToken>
                </wsse:Security>
            </s:Header>
            <s:Body>
            <!--
                <wst:RequestSecurityToken Id = ""RST0"">
                    <wst:RequestType>http://schemas.xmlsoap.org/ws/2005/02/trust/Issue</wst:RequestType>
                    <wsp:AppliesTo>
                        <wsa:EndpointReference>
                            <wsa:Address>http://live-int.com</wsa:Address>
                        </wsa:EndpointReference>
                    </wsp:AppliesTo>
                    <wsp:PolicyReference URI = ""MBI""></wsp:PolicyReference>
                </wst:RequestSecurityToken>
            -->
                <wst:RequestSecurityToken Id = ""RST1"">
                    <wst:RequestType>http://schemas.xmlsoap.org/ws/2005/02/trust/Issue</wst:RequestType>
                    <wsp:AppliesTo>
                        <wsa:EndpointReference>
                            <wsa:Address>{2:partner}</wsa:Address>
                        </wsa:EndpointReference>
                    </wsp:AppliesTo>
                    <wsp:PolicyReference URI = ""{3:policy}""></wsp:PolicyReference>
                </wst:RequestSecurityToken>
            </s:Body>
        </s:Envelope>";
 
        #endregion
 
        /// <summary>
        /// Gets a WLID ticket for a specified user
        /// </summary>
        /// <param name="userName"></param>
        /// <param name="password"></param>
        /// <param name="partner">sitename, i.e. crmapp.www.local-titan.com</param>
        /// <param name="policy">auth policy, i.e. MBI_SSL</param>
        /// <param name="environment">Wlid environment, i.e. INT</param>
        /// <param name="requestTimeoutSeconds">time in seconds the request waits for response</param>
        /// <returns></returns>
        public string GetWlidTicket(string userName, string password, string partner, string policy, string environment, int requestTimeoutSeconds)
        {
            string url;
            switch (environment)
            {
                case "INT":
                    url = @"https://dev.login.live-int.com/wstlogin.srf";
                    break;
                case "PPE":
                    url = @"https://dev.login.live-ppe.com/wstlogin.srf";
                    break;
                case "":
                case null:
                case "PROD":
                    url = @"https://dev.login.live.com/wstlogin.srf";
                    break;
                default:
                    throw new ArgumentException("environment is not valid", "environment");
            }
 
            var request = WebRequest.Create(url);
            request.Method = "POST";
            request.ContentType = "application/soap+xml; charset=UTF-8";
            request.Timeout = requestTimeoutSeconds * 1000;
 
            string soapEnvelope = string.Format(soapEnvelopeTemplate, userName, password, partner, policy, url);
            byte[] bytes = System.Text.Encoding.UTF8.GetBytes(soapEnvelope);
            using (var str = request.GetRequestStream())
            {
                str.Write(bytes, 0, bytes.Length);
                str.Close();
            }
 
            string xml;
            using (var response = request.GetResponse())
            {
                using (var reader = new StreamReader(response.GetResponseStream()))
                    xml = reader.ReadToEnd();
 
                response.Close();
            }
 
            var document = new XmlDocument();
            document.LoadXml(xml);
 
            var nsManager = new XmlNamespaceManager(document.NameTable);
            nsManager.AddNamespace("wsse", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
 
            var nodes = document.SelectNodes(@"//wsse:BinarySecurityToken/text()", nsManager);
            if (nodes != null && nodes.Count > 0 && nodes[0] != null)
                return nodes[0].Value;
 
            // The wsse:BinarySecurityToken element is missing. Examine the xml for error information
            throw new Exception("Failed to get Wlid ticket from WS-trust endpoint");
        }
 
        /// <summary>
        /// Gets a WLID ticket for a specified user
        /// </summary>
        /// <param name="userName"></param>
        /// <param name="password"></param>
        /// <param name="partner">sitename, i.e. crmapp.www.local-titan.com</param>
        /// <param name="policy">auth policy, i.e. MBI_SSL</param>
        /// <param name="environment">Wlid environment, i.e. INT</param>
        /// <returns></returns>
        public string GetWlidTicket(string userName, string password, string partner, string policy, string environment)
        {
            return GetWlidTicket(userName, password, partner, policy, environment, 10);
        }
    }
}

And here is the code that uses this LiveIdTicketAcquirer class to authenticate with MSCRM Online. You will need to add references to both Microsoft.Crm.Sdk and Microsoft.Crm.SdkTypeProxy dlls (specific for MSCRM Online) and add new Web Reference for CrmOnlineDiscovery.

Below is the cut-down version of CrmOnlineQueryManager that I use on CRM External View project. Feel free to download the full solution on codeplex and explore it yourself. :)

using System;
using System.Collections.Generic;
using System.Web;
using System.Web.Caching;
using System.Web.Services.Protocols;
using Microsoft.Crm.Sdk;
using Microsoft.Crm.Sdk.Query;
using Microsoft.Crm.SdkTypeProxy;
using TTprotons.Crm.ExternalView.Service.CrmOnlineDiscovery;
 
namespace TTprotons.Crm.ExternalView.Service.Crm
{
    /// <summary>
    /// Query Helper class specific for CRM Online.
    /// </summary>
    public class CrmOnlineQueryManager
    {
        private readonly LiveIdTicketAcquirer ticketAcquirer;
 
        #region Constants
 
        private const string CRMONLINE_PARTNER = "crm.dynamics.com";
        private const string CRMONLINE_ENVIRONMENT = "PROD";
 
        #endregion
 
        public CrmOnlineQueryManager()
        {
            ticketAcquirer = new LiveIdTicketAcquirer();
        }
 
        public void Connect(string username, string password, string organization)
        {
            try
            {
                var discoveryService = new CrmDiscoveryService();
 
                // Retrieve the policy for CRM Online Web Service.
                var policyRequest = new RetrievePolicyRequest();
                var policyResponse = (RetrievePolicyResponse)discoveryService.Execute(policyRequest);
 
                // Retrieve the WLID Ticket
                var wlidTicket = ticketAcquirer.GetWlidTicket(username, password, CRMONLINE_PARTNER, policyResponse.Policy, CRMONLINE_ENVIRONMENT);
 
                // Retrieve the CRM Ticket based on the WLID Ticket
                var crmTicketRequest = new RetrieveCrmTicketRequest
                {
                    OrganizationName = organization,
                    PassportTicket = wlidTicket
                };
 
                var crmTicketResponse = (RetrieveCrmTicketResponse)discoveryService.Execute(crmTicketRequest);
 
                // Retrieve the Ticket
                var crmTicket = crmTicketResponse.CrmTicket;
                var orgDetail = crmTicketResponse.OrganizationDetail;
            }
            catch (SoapException ex)
            { }
            catch (Exception ex)
            { }
        }
    }
}
Filed under: Microsoft CRM 6 Comments
26Mar/100

CRM External View v1.2 on Codeplex!

I’ve been working on this project for the last few weeks and did a silent-twitter-only release couple weeks ago just to get some feedback from the users. CRM External View is basically an extension to Microsoft CRM (at the moment only supports CRM Online) which allows you to expose the view data externally.

Throughout my CRM career, I’ve heard a lot of request to expose data like TOP 10 best-selling products of the month from CRM to their external facing website. Traditionally, to do this, we have to write a custom code specific for this and therefore, making it really hard to customize the logic in the future.

Microsoft CRM has a really great functionality out-of-the-box called View which does half of this requirement. The CRM user can create new views, customize the columns displayed, or even configure the filtering and sorting criteria. Now, what if we take the greatness of CRM views and expose it publicly? Wouldn’t it be awesome? That’s exactly what this CRM External View does!

Some of the cool features from v1.2 release:

- Ability to create password-protected views

- Filtering capabilities. The matching is done on a case-insensitive “CONTAINS”

- Transparent paging functionality. No need to worry about using paging-cookie externally

and many more.

Checkout the release at http://crmexternalview.codeplex.com for more details. Please leave your feedback or feature requests through the Codeplex discussion or in this blog.

Here are the Quick Get Started video for this extension.

CRM External View: Overview from Dimaz Pramudya on Vimeo.

Filed under: Microsoft CRM No Comments
11Mar/102

MSCRM Development Tips & Tricks #2 – Metadata Browser

Throughout your CRM development process, there are numerous times where you need to quickly find out a list of attributes for particular entity, inspect their relationships or check if the fields are valid for creation / update / delete. Yes, you can achieve this by going to Customization tab – Customize Entities and select the entities you want.

But this is just way too many clicks if I want to quickly find out these sort of information. This is where the Metadata Browser comes in handy. To open this Metadata Browser, you can just browse to http://[crmserver]:[portno]/[orgname]/sdk/list.aspx in your favorite browser. :)

You will see a list of entities and their relevant description as per the picture below.

image

To see the list of attributes and relationships, click on the Definition icon imagefor a particular entity. On this screen, you can inspect a number of things such as the attribute list, its type, length, valid for advanced find, valid for form, whether the field is a required field or not, relationships, etc.

image

Hopefully this simple trick can save you enormous time in your development. :)

Filed under: Microsoft CRM 2 Comments
Get Adobe Flash playerPlugin by wpburn.com wordpress themes