<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-2187748539439547090</id><updated>2012-03-05T21:23:14.678+08:00</updated><category term='Silverlight 4'/><category term='LINQ'/><category term='MEF'/><category term='SharePoint 2007'/><category term='WCF Service'/><category term='Dynamics CRM 4.0'/><category term='Dynamics CRM 2011'/><category term='my piano songs'/><category term='.NET'/><category term='SSRS'/><title type='text'>Andreas Wijaya's Blog</title><subtitle type='html'>My blog containing my music and development journey!</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://andreaswijayablog.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://andreaswijayablog.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Andreas</name><uri>http://www.blogger.com/profile/07294319219169612936</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='23' src='http://2.bp.blogspot.com/_kEwj71YPhb8/TJiDclVlgOI/AAAAAAAAAEY/1Th4NMsgW_Q/S220/Andreas2.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>45</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-2187748539439547090.post-4027949372235112077</id><published>2012-03-05T21:20:00.004+08:00</published><updated>2012-03-05T21:23:14.694+08:00</updated><title type='text'>New Songs - Blooming Or Withering Flower</title><content type='html'>Which one suits your mood? :)&lt;br /&gt;&lt;br /&gt;&lt;iframe allowfullscreen="" frameborder="0" height="315" src="http://www.youtube.com/embed/is_v4PzmN_g" width="560"&gt;&lt;/iframe&gt;&lt;iframe allowfullscreen="" frameborder="0" height="315" src="http://www.youtube.com/embed/LzVfvC2obVQ" width="560"&gt;&lt;/iframe&gt;&lt;div&gt;&lt;p&gt; Enjoy, &lt;/p&gt;&lt;p&gt; Andreas &lt;/p&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2187748539439547090-4027949372235112077?l=andreaswijayablog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andreaswijayablog.blogspot.com/feeds/4027949372235112077/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://andreaswijayablog.blogspot.com/2012/03/new-songs-blooming-or-withering-flower.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/4027949372235112077'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/4027949372235112077'/><link rel='alternate' type='text/html' href='http://andreaswijayablog.blogspot.com/2012/03/new-songs-blooming-or-withering-flower.html' title='New Songs - Blooming Or Withering Flower'/><author><name>Andreas</name><uri>http://www.blogger.com/profile/07294319219169612936</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='23' src='http://2.bp.blogspot.com/_kEwj71YPhb8/TJiDclVlgOI/AAAAAAAAAEY/1Th4NMsgW_Q/S220/Andreas2.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://img.youtube.com/vi/is_v4PzmN_g/default.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2187748539439547090.post-1368119144840761771</id><published>2012-02-07T10:28:00.000+08:00</published><updated>2012-02-08T17:59:59.505+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='LINQ'/><category scheme='http://www.blogger.com/atom/ns#' term='Dynamics CRM 2011'/><title type='text'>CRM 2011 LINQ Left Join Through Entity Reference</title><content type='html'>Let's say we have a custom lookup field new_accountid on our phonecall activity (don't ask me why I don't just use from/to field :)) and that field is&amp;nbsp;NOT a required field.&lt;br /&gt;&lt;br /&gt;We want to get the account number using LINQ in our code somehow.&lt;br /&gt;&lt;br /&gt;This is the way to do it. The trick is that we have to check whether the new_accountid is null and combine those records with the ones that are null.&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: csharp" type="syntaxhighlighter"&gt;&lt;![CDATA[var retrievedCalls = (from c in Repository.PhoneCallSet                      join a in Repository.ActivityPartySet on c.Id equals a.ActivityId.Id                      where a.PartyId.Id == request.UserId                      &amp;&amp; a.ParticipationTypeMask.Value == (int)OptionSet.ActivityPartyType.ToRecipient                      where c.ActualStart &gt;= defaultDateFilter.Date &amp;&amp; c.DirectionCode == false                      select new                      {                          PhoneCall = c,                          AccountId = c.new_accountid == null ? Guid.Empty : c.new_accountid.Id                      });var retrievedCallsWithAccountNumber = (from c in retrievedCalls.ToList()                                       join acc in Repository.AccountSet on c.AccountId equals acc.Id into ca                                       from caa in ca.DefaultIfEmpty()                                       select new                                       {                                           PhoneCall = c.PhoneCall,                                           AccountNumber = caa == null ? null : caa.AccountNumber                                       }).ToList();]]&gt;&lt;/script&gt;Hope this helps,Andreas&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2187748539439547090-1368119144840761771?l=andreaswijayablog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andreaswijayablog.blogspot.com/feeds/1368119144840761771/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://andreaswijayablog.blogspot.com/2012/02/crm-2011-linq-left-join-through-entity.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/1368119144840761771'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/1368119144840761771'/><link rel='alternate' type='text/html' href='http://andreaswijayablog.blogspot.com/2012/02/crm-2011-linq-left-join-through-entity.html' title='CRM 2011 LINQ Left Join Through Entity Reference'/><author><name>Andreas</name><uri>http://www.blogger.com/profile/07294319219169612936</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='23' src='http://2.bp.blogspot.com/_kEwj71YPhb8/TJiDclVlgOI/AAAAAAAAAEY/1Th4NMsgW_Q/S220/Andreas2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2187748539439547090.post-2784145856951000432</id><published>2012-01-24T08:46:00.007+08:00</published><updated>2012-01-24T20:06:01.426+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Dynamics CRM 2011'/><title type='text'>CRM 2011 Get OptionSetValue Value through Label</title><content type='html'>Sometimes we want to be able to get the OptionSetValue value from the label itself. One way is to use the metadata request and loop through it but this is a cumbersome way.&lt;br /&gt;&lt;br /&gt;The easier way is to put those OptionSetValue data into an enum like this:&lt;br /&gt;&lt;script class="brush: csharp" type="syntaxhighlighter"&gt;&lt;![CDATA[        public enum Approach        {            [Description("Value Marketing")]            ValueMarketing = 100000000,            [Description("Communications &amp; Events")]            CommEvents = 100000001,            [Description("Investigate")]            Investigate = 100000002,            [Description("Key Account Management")]            KeyAccManagement = 100000003,            [Description("Pro-Active Price &amp; Product")]            ProActivePriceProduct = 100000004        }]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;We use Description Attribute for the Label so that it supports string format.&lt;br /&gt;&lt;br /&gt;Then we use this helper method:&lt;br /&gt;&lt;script class="brush: csharp" type="syntaxhighlighter"&gt;&lt;![CDATA[    public static class EnumHelper    {        public static T GetValueFromDescription&lt;t&gt;(string description)        {            var type = typeof(T);            if (!type.IsEnum) throw new InvalidOperationException();            foreach (var field in type.GetFields())            {                var attribute = Attribute.GetCustomAttribute(field,                    typeof(DescriptionAttribute)) as DescriptionAttribute;                if (attribute != null)                {                    if (attribute.Description == description)                        return (T)field.GetValue(null);                }                else                {                    if (field.Name == description)                        return (T)field.GetValue(null);                }            }            throw new ArgumentException("Not found.", "description");        }     }]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;And there you go. You can easily get the value like this:&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: csharp" type="syntaxhighlighter"&gt;&lt;![CDATA[new_entity entity = new new_entity();entity.new_approach = new OptionSetValue((int)EnumHelper.GetValueFromDescription&lt;OptionSet.Approach&gt;("Value Marketing"));]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Hope this helps,&lt;br /&gt;Andreas&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2187748539439547090-2784145856951000432?l=andreaswijayablog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andreaswijayablog.blogspot.com/feeds/2784145856951000432/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://andreaswijayablog.blogspot.com/2012/01/crm-2011-get-optionsetvalue-value.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/2784145856951000432'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/2784145856951000432'/><link rel='alternate' type='text/html' href='http://andreaswijayablog.blogspot.com/2012/01/crm-2011-get-optionsetvalue-value.html' title='CRM 2011 Get OptionSetValue Value through Label'/><author><name>Andreas</name><uri>http://www.blogger.com/profile/07294319219169612936</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='23' src='http://2.bp.blogspot.com/_kEwj71YPhb8/TJiDclVlgOI/AAAAAAAAAEY/1Th4NMsgW_Q/S220/Andreas2.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2187748539439547090.post-5096960551742583328</id><published>2012-01-05T23:11:00.002+08:00</published><updated>2012-01-05T23:11:46.151+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='my piano songs'/><title type='text'>Happy New Year 2012!</title><content type='html'>Happy New Year everyone!&lt;br /&gt;&lt;br /&gt;&lt;iframe width="560" height="315" src="http://www.youtube.com/embed/Zn5VZrJEonc" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;br /&gt;&lt;br /&gt;May this year bring you good things and happiness!&lt;br /&gt;&lt;br /&gt;Take care,&lt;br /&gt;Andreas&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2187748539439547090-5096960551742583328?l=andreaswijayablog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andreaswijayablog.blogspot.com/feeds/5096960551742583328/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://andreaswijayablog.blogspot.com/2012/01/happy-new-year-2012.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/5096960551742583328'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/5096960551742583328'/><link rel='alternate' type='text/html' href='http://andreaswijayablog.blogspot.com/2012/01/happy-new-year-2012.html' title='Happy New Year 2012!'/><author><name>Andreas</name><uri>http://www.blogger.com/profile/07294319219169612936</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='23' src='http://2.bp.blogspot.com/_kEwj71YPhb8/TJiDclVlgOI/AAAAAAAAAEY/1Th4NMsgW_Q/S220/Andreas2.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://img.youtube.com/vi/Zn5VZrJEonc/default.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2187748539439547090.post-6174938300835160723</id><published>2011-11-21T13:28:00.002+08:00</published><updated>2011-11-22T15:47:49.491+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Dynamics CRM 2011'/><title type='text'>CRM 2011 Activity Party Add, Remove, Delete from code</title><content type='html'>Sometimes we want to append the activity party list, update particular item in the existing activity party list, or remove specific activity party from the list.&lt;br /&gt;&lt;br /&gt;Below is what I discovered on how to do this. Since we can't use the Create/Update/Delete method from the service context on ActivityParty entity, we need to alter the content of the list before attaching to the Activity Field.&lt;br /&gt;&lt;br /&gt;In my case I have an ActivityRecipient custom entity that have N:1 to Email entity. Whenever the user add/update/delete this custom entity, the corresponding 'To' recipients gets updated as well.&lt;br /&gt;&lt;br /&gt;I use this function in my pre create/update/delete message of my ActivityRecipient entity.&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: csharp" type="syntaxhighlighter"&gt;&lt;![CDATA[        /// &lt;summary&gt;        /// Populate related activity parties        /// &lt;/summary&gt;        private static void PopulateParties(IOrganizationService service, OrgServiceContext serviceContext, new_activityrecipient activityRecipient, string message)        {            if (message == "create")            {                //Email                if (activityRecipient.new_emailid != null)                {                    var email = serviceContext.EmailSet.Where(e =&gt; e.ActivityId == activityRecipient.new_emailid.Id).SingleOrDefault();                    ActivityParty toParty = new ActivityParty { PartyId = activityRecipient.new_contactid };                    email.To = email.To.Concat(new ActivityParty[] { toParty });                    serviceContext.UpdateObject(email);                    serviceContext.SaveChangesWithErrorCheck();                }                //Appointment                if (activityRecipient.new_appointmentid != null)                {                    var appointment = serviceContext.AppointmentSet.Where(a =&gt; a.ActivityId == activityRecipient.new_appointmentid.Id).SingleOrDefault();                    ActivityParty reqAttendees = new ActivityParty { PartyId = activityRecipient.new_contactid };                    appointment.RequiredAttendees = appointment.RequiredAttendees.Concat(new ActivityParty[] { reqAttendees });                    serviceContext.UpdateObject(appointment);                    serviceContext.SaveChangesWithErrorCheck();                }                //Recurring Appointment                if (activityRecipient.new_recurringappoinmentid != null)                {                    RecurringAppointmentMaster appointment = (RecurringAppointmentMaster)service.Retrieve(RecurringAppointmentMaster.EntityLogicalName, activityRecipient.new_recurringappoinmentid.Id, new ColumnSet("subject", "requiredattendees"));                    ActivityParty reqAttendees = new ActivityParty { PartyId = activityRecipient.new_contactid };                    appointment.RequiredAttendees = appointment.RequiredAttendees.Concat(new ActivityParty[] { reqAttendees });                    service.Update(appointment);                }            }            if (message == "update")            {                var retrievedActivityRecipient = serviceContext.new_activityrecipientSet.Where(x =&gt; x.Id == activityRecipient.Id).SingleOrDefault();                //Email                if (retrievedActivityRecipient.new_emailid != null)                {                    var email = serviceContext.EmailSet.Where(e =&gt; e.ActivityId == retrievedActivityRecipient.new_emailid.Id).SingleOrDefault();                    ActivityParty toParty = serviceContext.ActivityPartySet.Where(ap =&gt; ap.ActivityId.Id == email.ActivityId &amp;&amp; ap.PartyId == retrievedActivityRecipient.new_contactid).SingleOrDefault();                    ActivityParty toNewParty = new ActivityParty { PartyId = activityRecipient.new_contactid };                    List&lt;ActivityParty&gt; recipients = email.To.ToList();                    int oldIndex = recipients.FindIndex(ap =&gt; ap.ActivityPartyId == toParty.ActivityPartyId);                    recipients[oldIndex] = toNewParty;                    email.To = recipients;                    serviceContext.UpdateObject(email);                    serviceContext.SaveChangesWithErrorCheck();                }                //Appoinment                if (retrievedActivityRecipient.new_appointmentid != null)                {                    var appointment = serviceContext.AppointmentSet.Where(a =&gt; a.ActivityId == retrievedActivityRecipient.new_appointmentid.Id).SingleOrDefault();                    ActivityParty reqAttendees = serviceContext.ActivityPartySet.Where(ap =&gt; ap.ActivityId.Id == appointment.ActivityId &amp;&amp; ap.PartyId == retrievedActivityRecipient.new_contactid).SingleOrDefault();                    ActivityParty reqNewAttendees = new ActivityParty { PartyId = activityRecipient.new_contactid };                    List&lt;ActivityParty&gt; recipients = appointment.RequiredAttendees.ToList();                    int oldIndex = recipients.FindIndex(ap =&gt; ap.ActivityPartyId == reqAttendees.ActivityPartyId);                    recipients[oldIndex] = reqNewAttendees;                    appointment.RequiredAttendees = recipients;                    serviceContext.UpdateObject(appointment);                    serviceContext.SaveChangesWithErrorCheck();                }                //Recurring Appoinment                if (retrievedActivityRecipient.new_recurringappoinmentid != null)                {                    RecurringAppointmentMaster appointment = (RecurringAppointmentMaster)service.Retrieve(RecurringAppointmentMaster.EntityLogicalName, retrievedActivityRecipient.new_recurringappoinmentid.Id, new ColumnSet("subject", "requiredattendees"));                    ActivityParty reqAttendees = serviceContext.ActivityPartySet.Where(ap =&gt; ap.ActivityId.Id == appointment.ActivityId &amp;&amp; ap.PartyId == retrievedActivityRecipient.new_contactid).SingleOrDefault();                    ActivityParty reqNewAttendees = new ActivityParty { PartyId = activityRecipient.new_contactid };                    List&lt;ActivityParty&gt; recipients = appointment.RequiredAttendees.ToList();                    int oldIndex = recipients.FindIndex(ap =&gt; ap.ActivityPartyId == reqAttendees.ActivityPartyId);                    recipients[oldIndex] = reqNewAttendees;                    appointment.RequiredAttendees = recipients;                    service.Update(appointment);                }            }            if (message == "delete")            {                //Email                if (activityRecipient.new_emailid != null)                {                    var email = serviceContext.EmailSet.Where(e =&gt; e.ActivityId == activityRecipient.new_emailid.Id).SingleOrDefault();                    ActivityParty toParty = serviceContext.ActivityPartySet.Where(ap =&gt; ap.ActivityId.Id == email.ActivityId &amp;&amp; ap.PartyId == activityRecipient.new_contactid).SingleOrDefault();                              List&lt;ActivityParty&gt; recipients = email.To.ToList();                    email.To = recipients.Where(ap =&gt; ap.ActivityPartyId != toParty.ActivityPartyId);                    serviceContext.UpdateObject(email);                    serviceContext.SaveChangesWithErrorCheck();                }                //Appointment                if (activityRecipient.new_appointmentid != null)                {                    var appointment = serviceContext.AppointmentSet.Where(a =&gt; a.ActivityId == activityRecipient.new_appointmentid.Id).SingleOrDefault();                    ActivityParty reqAttendees = serviceContext.ActivityPartySet.Where(ap =&gt; ap.ActivityId.Id == appointment.ActivityId &amp;&amp; ap.PartyId == activityRecipient.new_contactid).SingleOrDefault();                    List&lt;ActivityParty&gt; recipients = appointment.RequiredAttendees.ToList();                    appointment.RequiredAttendees = recipients.Where(ap =&gt; ap.ActivityPartyId != reqAttendees.ActivityPartyId);                    serviceContext.UpdateObject(appointment);                    serviceContext.SaveChangesWithErrorCheck();                }                //Recurring Appointment                if (activityRecipient.new_recurringappoinmentid != null)                {                    RecurringAppointmentMaster appointment = (RecurringAppointmentMaster)service.Retrieve(RecurringAppointmentMaster.EntityLogicalName, activityRecipient.new_recurringappoinmentid.Id, new ColumnSet("subject", "requiredattendees"));                    ActivityParty reqAttendees = serviceContext.ActivityPartySet.Where(ap =&gt; ap.ActivityId.Id == appointment.ActivityId &amp;&amp; ap.PartyId == activityRecipient.new_contactid).SingleOrDefault();                    List&lt;ActivityParty&gt; recipients = appointment.RequiredAttendees.ToList();                    appointment.RequiredAttendees = recipients.Where(ap =&gt; ap.ActivityPartyId != reqAttendees.ActivityPartyId);                   service.Update(appointment);                }            }        }]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Note: for some reason Recurring Appointment doesn't like Organization Service Context (early bound), therefore we have to use IOrganizationService with Retrieve Request.&lt;br /&gt;&lt;br /&gt;Hope this helps,&lt;br /&gt;Andreas&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2187748539439547090-6174938300835160723?l=andreaswijayablog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andreaswijayablog.blogspot.com/feeds/6174938300835160723/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://andreaswijayablog.blogspot.com/2011/11/crm-2011-activity-party-add-remove.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/6174938300835160723'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/6174938300835160723'/><link rel='alternate' type='text/html' href='http://andreaswijayablog.blogspot.com/2011/11/crm-2011-activity-party-add-remove.html' title='CRM 2011 Activity Party Add, Remove, Delete from code'/><author><name>Andreas</name><uri>http://www.blogger.com/profile/07294319219169612936</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='23' src='http://2.bp.blogspot.com/_kEwj71YPhb8/TJiDclVlgOI/AAAAAAAAAEY/1Th4NMsgW_Q/S220/Andreas2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2187748539439547090.post-5156414288625415432</id><published>2011-10-12T15:59:00.002+08:00</published><updated>2011-11-21T13:41:42.279+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Dynamics CRM 2011'/><title type='text'>CRM 2011 SMS custom activity Characters Remaining field</title><content type='html'>Paul Nieuwelaar in his &lt;a href="http://paulnieuwelaar.wordpress.com/2011/05/22/dynamics-crm-2011-calling-onkeydown-with-javascript/"&gt;blog&lt;/a&gt; has implemented some javascript for the characters remaining field.&lt;br /&gt;&lt;br /&gt;This saves me a lot of time from reinventing the wheel. All I then did was to set the default value to the field (160 characters for SMS).&lt;br /&gt;&lt;br /&gt;Also make sure that you put the 160 limit on the multiline textbox, but leave the minimum value for the charactersremaining field to be -20000000 to avoid the annoying message box.&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: js" type="syntaxhighlighter"&gt;&lt;![CDATA[function Form_onload() {    //set max characters    keyPress();    document.getElementById("description").onkeyup = keyPress;    document.getElementById("description").onkeydown = keyPress;}function keyPress() {    var maxLength = 160;    var charRemaining = Xrm.Page.getAttribute("new_charactersremaining");    var message = document.getElementById("description");    var messageVal = message.value;    if (messageVal != null) {        var msgLength = messageVal.length;        var remaining = maxLength - msgLength;        charRemaining.setValue(remaining);    }    else {        charRemaining.setValue(maxLength);    }}]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Hope this helps,&lt;br /&gt;Andreas&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2187748539439547090-5156414288625415432?l=andreaswijayablog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andreaswijayablog.blogspot.com/feeds/5156414288625415432/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://andreaswijayablog.blogspot.com/2011/10/crm-2011-sms-custom-activity-characters.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/5156414288625415432'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/5156414288625415432'/><link rel='alternate' type='text/html' href='http://andreaswijayablog.blogspot.com/2011/10/crm-2011-sms-custom-activity-characters.html' title='CRM 2011 SMS custom activity Characters Remaining field'/><author><name>Andreas</name><uri>http://www.blogger.com/profile/07294319219169612936</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='23' src='http://2.bp.blogspot.com/_kEwj71YPhb8/TJiDclVlgOI/AAAAAAAAAEY/1Th4NMsgW_Q/S220/Andreas2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2187748539439547090.post-2854416984965571342</id><published>2011-10-12T15:49:00.001+08:00</published><updated>2011-10-12T19:29:56.777+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Dynamics CRM 2011'/><title type='text'>CRM 2011 disable lookup type for customer field or partylist</title><content type='html'>Sometimes we want to lock the lookup type for customer field type or partylist type. To do this, use the javascript (e.g. Account Type only):&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: js" type="syntaxhighlighter"&gt;&lt;![CDATA[function ConfigureCustomerIdField() {    document.getElementById("customerid").setAttribute("defaulttype", "1");    Xrm.Page.getControl("customerid").setDefaultView("D79FA02E-27D9-E011-ADBA-005056A10003");    document.getElementById("customerid").setAttribute("lookuptypenames", "account:1:Account");    document.getElementById("customerid").setAttribute("lookuptypes", "1");    document.getElementById("customerid").setAttribute("lookuptypeIcons", "/_imgs/ico_16_1.gif");}]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Hope this helps,&lt;br /&gt;Andreas&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2187748539439547090-2854416984965571342?l=andreaswijayablog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andreaswijayablog.blogspot.com/feeds/2854416984965571342/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://andreaswijayablog.blogspot.com/2011/10/crm-2011-disable-lookup-type-for.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/2854416984965571342'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/2854416984965571342'/><link rel='alternate' type='text/html' href='http://andreaswijayablog.blogspot.com/2011/10/crm-2011-disable-lookup-type-for.html' title='CRM 2011 disable lookup type for customer field or partylist'/><author><name>Andreas</name><uri>http://www.blogger.com/profile/07294319219169612936</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='23' src='http://2.bp.blogspot.com/_kEwj71YPhb8/TJiDclVlgOI/AAAAAAAAAEY/1Th4NMsgW_Q/S220/Andreas2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2187748539439547090.post-8853927314825769051</id><published>2011-10-12T15:45:00.001+08:00</published><updated>2011-10-12T19:30:17.606+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Dynamics CRM 2011'/><title type='text'>CRM 2011 Export Entities Tabs and Sections Name</title><content type='html'>CRM does not provide a functionality to list all your tab and section names. With the help of SQL XML parsing feature, I managed to create an sql script to read the FormXML of the entities and parse out the tabs and sections name.&lt;br /&gt;&lt;br /&gt;This is useful if you want to see all the tabs and sections that you have added. Enough said, this is the script:&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: sql" type="syntaxhighlighter"&gt;&lt;![CDATA[CREATE TABLE #MyResult(EntityName NVARCHAR(200),Tab nvarchar(100),Section nvarchar(100) )SELECT    RowNum = ROW_NUMBER() OVER(ORDER BY e.Name)    , e.OriginalLocalizedName, e.ObjectTypeCode, f.FormXmlINTO #TabsAndSectionsfrom EntityView e Left Join   FilteredSystemForm f ON e.ObjectTypeCode = f.objecttypecode--Filter your entity below  --Where e.SolutionId = 'FD140AAE-4DF4-11DD-BD17-0019B9312238' AND (e.IsManaged = 0 OR e.CanModifyAdditionalSettings = 1)AND e.OriginalLocalizedName NOT IN ('Address', 'Article', 'Lead', 'Product', 'Quote', 'SalesLiterature')AND f.typename = 'Main' AND f.name = 'Information'ORDER BY e.Name ASC--Iterate through each entity's FormXmlDECLARE @MaxRownum intSET @MaxRownum = (SELECT MAX(RowNum) FROM #TabsAndSections)DECLARE @Iter intSET @Iter = (SELECT MIN(RowNum) FROM #TabsAndSections)WHILE @Iter &lt;= @MaxRownumBEGIN DECLARE @entityName NVARCHAR(200)  DECLARE @t NVARCHAR(MAX)  DECLARE @x XML DECLARE @idoc int SET @entityName = (SELECT OriginalLocalizedName from #TabsAndSections WHERE RowNum = @Iter) SET @t = (SELECT FormXml from #TabsAndSections WHERE RowNum = @Iter) SET @x = (SELECT CAST(@t AS XML)) --Create an internal representation of the XML document. EXEC sp_xml_preparedocument @idoc OUTPUT, @x INSERT INTO #MyResult SELECT @entityName AS entityName, * FROM   OPENXML (@idoc, '//sections/section',2)    WITH (Tab         nvarchar(100)         '../../../../@name',       Section    nvarchar(100)   '@name')               SET @Iter = @Iter + 1ENDSELECT * FROM #MyResult--Filter your tab and section results below--WHERE Tab IS NOT NULL AND Section IS NOT NULLORDER BY EntityName ASCDROP TABLE #TabsAndSectionsDROP TABLE #MyResult]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Hope this helps,&lt;br /&gt;Andreas&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2187748539439547090-8853927314825769051?l=andreaswijayablog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andreaswijayablog.blogspot.com/feeds/8853927314825769051/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://andreaswijayablog.blogspot.com/2011/10/crm-2011-export-entities-tabs-and.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/8853927314825769051'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/8853927314825769051'/><link rel='alternate' type='text/html' href='http://andreaswijayablog.blogspot.com/2011/10/crm-2011-export-entities-tabs-and.html' title='CRM 2011 Export Entities Tabs and Sections Name'/><author><name>Andreas</name><uri>http://www.blogger.com/profile/07294319219169612936</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='23' src='http://2.bp.blogspot.com/_kEwj71YPhb8/TJiDclVlgOI/AAAAAAAAAEY/1Th4NMsgW_Q/S220/Andreas2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2187748539439547090.post-679381546135667644</id><published>2011-09-21T11:50:00.002+08:00</published><updated>2011-09-21T11:52:19.897+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Dynamics CRM 2011'/><title type='text'>CRM 2011 Ajax Loading Message Screen with JQuery</title><content type='html'>When you use ajax request in CRM2011 (for example, the OData call), the user is not notified when this process happens in the background. Although this call is relatively fast, sometimes you can't predict the performance of it and you want some kind of notification that lets the user know what's happening.&lt;br /&gt;&lt;br /&gt;Fortunately with the power of JQuery you can easily make this happen. In my case, I have a custom 'Create Opportunity' button on my custom entity form that gets the data from that entity (and related entity) and create opportunity with those data. &lt;br /&gt;&lt;br /&gt;When creating the opportunity using the OData way, I will show the loading message popup with the animated OOTB CRM progress gif image. &lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-LrZ8-6mNYMg/TnleFhscv6I/AAAAAAAAAIg/oCv4RGOIsk8/s1600/AjaxLoad.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="285" src="http://2.bp.blogspot.com/-LrZ8-6mNYMg/TnleFhscv6I/AAAAAAAAAIg/oCv4RGOIsk8/s320/AjaxLoad.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;To make this happen, it's simple. Just put this function into your onLoad form:&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: js" type="syntaxhighlighter"&gt;&lt;![CDATA[function Form_onload() {ConfigureAjaxLoading('Creating Opportunity');}function ConfigureAjaxLoading(text) {    $('body').append('&lt;div id="loadingDiv"&gt;&lt;/div&gt;');    $('#loadingDiv').append('&lt;p id="loadingText"&gt;' + text + '&lt;/p&gt;')                    .css('background', 'url(/_imgs/AdvFind/progress.gif) no-repeat center')                    .css('background-color', '#CCCCCC')                    .css('height', '100px')                    .css('width', '300px')                    .center()                    .hide()  // hide it initially                     .ajaxStart(function () {                        $(this).show();                    })                    .ajaxStop(function () {                        $(this).hide();                    });    $('#loadingText').css('text-align', 'center')                     .css('font', '20px bolder')                     .css('font-family', 'Segoe UI, Tahoma, Arial');}]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;You notice the center() method above. This is an add-on to the jQuery method that you can safely put on your jQuery file:&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: js" type="syntaxhighlighter"&gt;&lt;![CDATA[jQuery.fn.center = function () { this.css("position", "absolute"); this.css("top", (($(window).height() - this.outerHeight()) / 2) + $(window).scrollTop() + "px"); this.css("left", (($(window).width() - this.outerWidth()) / 2) + $(window).scrollLeft() + "px"); return this; } ]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;That's it. Now whenever there is an Ajax call on the form, you will get this message shown up.&lt;br /&gt;&lt;br /&gt;Hope this helps,&lt;br /&gt;Andreas&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2187748539439547090-679381546135667644?l=andreaswijayablog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andreaswijayablog.blogspot.com/feeds/679381546135667644/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://andreaswijayablog.blogspot.com/2011/09/crm-2011-ajax-loading-message-screen.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/679381546135667644'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/679381546135667644'/><link rel='alternate' type='text/html' href='http://andreaswijayablog.blogspot.com/2011/09/crm-2011-ajax-loading-message-screen.html' title='CRM 2011 Ajax Loading Message Screen with JQuery'/><author><name>Andreas</name><uri>http://www.blogger.com/profile/07294319219169612936</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='23' src='http://2.bp.blogspot.com/_kEwj71YPhb8/TJiDclVlgOI/AAAAAAAAAEY/1Th4NMsgW_Q/S220/Andreas2.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-LrZ8-6mNYMg/TnleFhscv6I/AAAAAAAAAIg/oCv4RGOIsk8/s72-c/AjaxLoad.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2187748539439547090.post-5225541968284560379</id><published>2011-09-21T11:38:00.000+08:00</published><updated>2011-09-21T11:38:31.323+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Dynamics CRM 2011'/><title type='text'>CRM 2011 JQuery OData REST Endpoints Create Record</title><content type='html'>In CRM 2011, we can create record easily using JQuery and OData. This will get triggered asynchronously using the ajax functionality.&lt;br /&gt;&lt;br /&gt;Create Record function from the SDK:&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: js" type="syntaxhighlighter"&gt;&lt;![CDATA[function createRecord(entityObject, odataSetName, successCallback, errorCallback) {    var serverUrl = Xrm.Page.context.getServerUrl();    var ODATA_ENDPOINT = "/XRMServices/2011/OrganizationData.svc";    //entityObject is required    if (!entityObject) {        alert("entityObject is required.");        return;    }    //odataSetName is required, i.e. "AccountSet"    if (!odataSetName) {        alert("odataSetName is required.");        return;    }    //Parse the entity object into JSON    var jsonEntity = window.JSON.stringify(entityObject);    //Asynchronous AJAX function to Create a CRM record using OData    $.ajax({        type: "POST",        contentType: "application/json; charset=utf-8",        datatype: "json",        url: serverUrl + ODATA_ENDPOINT + "/" + odataSetName,        data: jsonEntity,        beforeSend: function (XMLHttpRequest) {            //Specifying this header ensures that the results will be returned as JSON.                         XMLHttpRequest.setRequestHeader("Accept", "application/json");        },        success: function (data, textStatus, XmlHttpRequest) {            if (successCallback) {                successCallback(data.d, textStatus, XmlHttpRequest);            }        },        error: function (XmlHttpRequest, textStatus, errorThrown) {            if (errorCallback)                errorCallback(XmlHttpRequest, textStatus, errorThrown);            else                errorHandler(XmlHttpRequest, textStatus, errorThrown);        }    });}function errorHandler(xmlHttpRequest, textStatus, errorThrow) {    alert("Error : " + textStatus + ": " + xmlHttpRequest.statusText);}]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;To create new record, you just need to instantiate your object and call the function. The tricky part is when you want to assign Lookup field or OptionSetValue. You can get more info on this from the SDK itself. Here is an example:&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: js" type="syntaxhighlighter"&gt;&lt;![CDATA[var opportunity = {     CustomerId: {        __metadata: { type: "Microsoft.Crm.Sdk.Data.Services.EntityReference" },        Id: &lt;lookup record id&gt;,        LogicalName: &lt;lookup record logical name&gt;    },    new_tonnageloss: "0",    new_originaltonnage: "100"};    createRecord(opportunity, "OpportunitySet", createOpportunityCompleted, null);]]&gt;&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2187748539439547090-5225541968284560379?l=andreaswijayablog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andreaswijayablog.blogspot.com/feeds/5225541968284560379/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://andreaswijayablog.blogspot.com/2011/09/crm-2011-jquery-odata-rest-endpoints.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/5225541968284560379'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/5225541968284560379'/><link rel='alternate' type='text/html' href='http://andreaswijayablog.blogspot.com/2011/09/crm-2011-jquery-odata-rest-endpoints.html' title='CRM 2011 JQuery OData REST Endpoints Create Record'/><author><name>Andreas</name><uri>http://www.blogger.com/profile/07294319219169612936</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='23' src='http://2.bp.blogspot.com/_kEwj71YPhb8/TJiDclVlgOI/AAAAAAAAAEY/1Th4NMsgW_Q/S220/Andreas2.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2187748539439547090.post-9032755070633524808</id><published>2011-09-21T11:32:00.001+08:00</published><updated>2011-11-17T08:09:29.403+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Dynamics CRM 2011'/><title type='text'>CRM 2011 Javascript Fetch XML synchronous or asynchronous call</title><content type='html'>Using helper function to execute FetchXML request is great. &lt;br /&gt;&lt;br /&gt;The code below is retrieved from &lt;a href="http://www.crmsoftwareblog.com/2011/07/using-the-fetchxml-crm-2011-service-within-a-javascript-web-resource/"&gt;this blog&lt;/a&gt;, and all I had to do is to add extra logic when parsing the XML result because I want to grab the attributes from the related entity as well.&lt;br /&gt;&lt;br /&gt;Modified FetchUtil.js:&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: js" type="syntaxhighlighter"&gt;&lt;![CDATA[/// &lt;summary&gt;FetchUtil.js&lt;/summary&gt; var XMLHTTPSUCCESS = 200;var XMLHTTPREADY = 4;function FetchUtil(sOrg, sServer) {    this.org = sOrg;    this.server = sServer;    if (sOrg == null) {        if (typeof (ORG_UNIQUE_NAME) != "undefined") {            this.org = ORG_UNIQUE_NAME;        }    }    if (sServer == null) {        this.server = window.location.protocol + "//" + window.location.host;    }}FetchUtil.prototype._ExecuteRequest = function (sXml, sMessage, fInternalCallback, fUserCallback) {    var xmlhttp = new XMLHttpRequest();    xmlhttp.open("POST", this.server + "/XRMServices/2011/Organization.svc/web", (fUserCallback != null));    xmlhttp.setRequestHeader("Accept", "application/xml, text/xml, */*");    xmlhttp.setRequestHeader("Content-Type", "text/xml; charset=utf-8");    xmlhttp.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/Execute");    if (fUserCallback != null) {        //asynchronous: register callback function, then send the request.         var crmServiceObject = this;        xmlhttp.onreadystatechange = function () { fInternalCallback.call(crmServiceObject, xmlhttp, fUserCallback) };        xmlhttp.send(sXml);    }    else {        //synchronous: send request, then call the callback function directly         xmlhttp.send(sXml);        return fInternalCallback.call(this, xmlhttp, null);    }}FetchUtil.prototype._HandleErrors = function (xmlhttp) {    /// &lt;summary&gt;(private) Handles xmlhttp errors&lt;/summary&gt;     if (xmlhttp.status != XMLHTTPSUCCESS) {        var sError = "Error: " + xmlhttp.responseText + " " + xmlhttp.statusText;        alert(sError);        return true;    } else {        return false;    }}FetchUtil.prototype.Fetch = function (sFetchXml, fCallback) {    /// &lt;summary&gt;Execute a FetchXml request. (result is the response XML)&lt;/summary&gt;     /// &lt;param name="sFetchXml"&gt;fetchxml string&lt;/param&gt;    /// &lt;param name="fCallback" optional="true" type="function"&gt;(Optional) Async callback function if specified. If left null, function is synchronous &lt;/param&gt;    var request = "&lt;s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\"&gt;";    request += "&lt;s:Body&gt;";    request += '&lt;Execute xmlns="http://schemas.microsoft.com/xrm/2011/Contracts/Services"&gt;' +'&lt;request i:type="b:RetrieveMultipleRequest" ' +' xmlns:b="http://schemas.microsoft.com/xrm/2011/Contracts" ' +' xmlns:i="http://www.w3.org/2001/XMLSchema-instance"&gt;' +'&lt;b:Parameters xmlns:c="http://schemas.datacontract.org/2004/07/System.Collections.Generic"&gt;' +'&lt;b:KeyValuePairOfstringanyType&gt;' +'&lt;c:key&gt;Query&lt;/c:key&gt;' +'&lt;c:value i:type="b:FetchExpression"&gt;' +'&lt;b:Query&gt;';    request += CrmEncodeDecode.CrmXmlEncode(sFetchXml);    request += '&lt;/b:Query&gt;' +'&lt;/c:value&gt;' +'&lt;/b:KeyValuePairOfstringanyType&gt;' +'&lt;/b:Parameters&gt;' +'&lt;b:RequestId i:nil="true"/&gt;' +'&lt;b:RequestName&gt;RetrieveMultiple&lt;/b:RequestName&gt;' +'&lt;/request&gt;' +'&lt;/Execute&gt;';    request += '&lt;/s:Body&gt;&lt;/s:Envelope&gt;';    return this._ExecuteRequest(request, "Fetch", this._FetchCallback, fCallback);}FetchUtil.prototype._FetchCallback = function (xmlhttp, callback) {    ///&lt;summary&gt;(private) Fetch message callback.&lt;/summary&gt;    //xmlhttp must be completed    if (xmlhttp.readyState != XMLHTTPREADY) {        return;    }    //check for server errors    if (this._HandleErrors(xmlhttp)) {        return;    }    var sFetchResult = xmlhttp.responseXML.selectSingleNode("//a:Entities").xml;    var resultDoc = new ActiveXObject("Microsoft.XMLDOM");    resultDoc.async = false;    resultDoc.loadXML(sFetchResult);    //parse result xml into array of jsDynamicEntity objects    var results = new Array(resultDoc.firstChild.childNodes.length);    for (var i = 0; i &lt; resultDoc.firstChild.childNodes.length; i++) {        var oResultNode = resultDoc.firstChild.childNodes[i];        var jDE = new jsDynamicEntity();        var obj = new Object();        for (var j = 0; j &lt; oResultNode.childNodes.length; j++) {            switch (oResultNode.childNodes[j].baseName) {                case "Attributes":                    var attr = oResultNode.childNodes[j];                    for (var k = 0; k &lt; attr.childNodes.length; k++) {                        // Establish the Key for the Attribute                        var sKey = attr.childNodes[k].firstChild.text;                        var sType = '';                        // Determine the Type of Attribute value we should expect                        for (var l = 0; l &lt; attr.childNodes[k].childNodes[1].attributes.length; l++) {                            if (attr.childNodes[k].childNodes[1].attributes[l].baseName == 'type') {                                sType = attr.childNodes[k].childNodes[1].attributes[l].text;                            }                        }                        switch (sType) {                            case "a:OptionSetValue":                                var entOSV = new jsOptionSetValue();                                entOSV.type = sType;                                entOSV.value = attr.childNodes[k].childNodes[1].text;                                obj[sKey] = entOSV;                                break;                            case "a:AliasedValue":                                var entRef = new jsEntityReference();                                entRef.guid = attr.childNodes[k].childNodes[1].childNodes[2].childNodes[0].text;                                entRef.logicalName = attr.childNodes[k].childNodes[1].childNodes[2].childNodes[1].text;                                entRef.name = attr.childNodes[k].childNodes[1].childNodes[2].childNodes[2].text;                                obj[attr.childNodes[k].childNodes[1].childNodes[0].text] = entRef;                                break;                            case "a:EntityReference":                                var entRef = new jsEntityReference();                                entRef.type = sType;                                entRef.guid = attr.childNodes[k].childNodes[1].childNodes[0].text;                                entRef.logicalName = attr.childNodes[k].childNodes[1].childNodes[1].text;                                entRef.name = attr.childNodes[k].childNodes[1].childNodes[2].text;                                obj[sKey] = entRef;                                break;                            default:                                var entCV = new jsCrmValue();                                entCV.type = sType;                                entCV.value = attr.childNodes[k].childNodes[1].text;                                obj[sKey] = entCV;                                break;                        }                    }                    jDE.attributes = obj;                    break;                case "Id":                    jDE.guid = oResultNode.childNodes[j].text;                    break;                case "LogicalName":                    jDE.logicalName = oResultNode.childNodes[j].text;                    break;                case "FormattedValues":                    var foVal = oResultNode.childNodes[j];                    for (var k = 0; k &lt; foVal.childNodes.length; k++) {                        // Establish the Key, we are going to fill in the formatted value of the already found attribute                        var sKey = foVal.childNodes[k].firstChild.text;                        jDE.attributes[sKey].formattedValue = foVal.childNodes[k].childNodes[1].text;                    }                    break;            }        }        results[i] = jDE;    }    //return entities    if (callback != null) callback(results);    else return results;}function jsDynamicEntity(gID, sLogicalName) {    this.guid = gID;    this.logicalName = sLogicalName;    this.attributes = new Object();}function jsCrmValue(sType, sValue) {    this.type = sType;    this.value = sValue;}function jsEntityReference(gID, sLogicalName, sName) {    this.guid = gID;    this.logicalName = sLogicalName;    this.name = sName;    this.type = 'EntityReference';}function jsOptionSetValue(iValue, sFormattedValue) {    this.value = iValue;    this.formattedValue = sFormattedValue;    this.type = 'OptionSetValue';}//setting CRM fieldsfunction SetLookupField(res, fieldName) {    if (res[0].attributes[fieldName] != null) {        SetLookupValue(fieldName, res[0].attributes[fieldName].id, res[0].attributes[fieldName].name, res[0].attributes[fieldName].logicalName);    }}function SetNumberField(res, fieldName) {    if (res[0].attributes[fieldName] != null) {        Xrm.Page.getAttribute(fieldName).setValue(parseFloat(res[0].attributes[fieldName].value));    }}function SetLookupValue(fieldName, id, name, entityType) {    if (fieldName != null) {        var lookupValue = new Array();        lookupValue[0] = new Object();        lookupValue[0].id = id;        lookupValue[0].name = name;        lookupValue[0].entityType = entityType;        Xrm.Page.getAttribute(fieldName).setValue(lookupValue);    }} ]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;To use it you just need to do it like this (synchronous)&lt;br /&gt;&lt;script class="brush: js" type="syntaxhighlighter"&gt;&lt;![CDATA[function FetchData(guid) {    var _oService;    var _sOrgName = "";    var _sServerUrl = Xrm.Page.context.getServerUrl();    var sFetch = "&lt;fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='false'&gt;" +  "&lt;entity name='new_productiongrowerforecast'&gt;" +  "&lt;attribute name='new_name' /&gt;" +   "&lt;attribute name='new_commodityid' /&gt;" +   "&lt;attribute name='new_potentialtonnage' /&gt;" +   "&lt;attribute name='new_productiongrowerforecastid' /&gt;" +   "&lt;order attribute='new_name' descending='false' /&gt;" +   "&lt;filter type='and'&gt;" +  "&lt;condition attribute='new_productiongrowerforecastid' operator='eq'   value='" + guid + "' /&gt;" +   "&lt;/filter&gt;" +  "&lt;link-entity name='new_productionforecast' from='new_productionforecastid' to='new_productionforecastid' visible='false' link-type='outer' alias='pfdpf'&gt;" +  "&lt;attribute name='new_seasonid' /&gt;" +   "&lt;attribute name='new_growerid' /&gt;" +   "&lt;/link-entity&gt;" +  "&lt;/entity&gt;" +  "&lt;/fetch&gt;"    _oService = new FetchUtil(_sOrgName, _sServerUrl);    var res = _oService.Fetch(sFetch);}]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;If it's asynchronous the last bit will be:&lt;br /&gt;&lt;script class="brush: js" type="syntaxhighlighter"&gt;&lt;![CDATA[var res = _oService.Fetch(sFetch, callBackFunction);//implement your own callBackFunction here]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;The parsed result object can be queried like this:&lt;br /&gt;&lt;script class="brush: js" type="syntaxhighlighter"&gt;&lt;![CDATA[var seasonId = res[0].attributes["new_seasonid"].guid;var originalTonnage = res[0].attributes["new_potentialtonnage"].value;]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Hope this helps,&lt;br /&gt;Andreas&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2187748539439547090-9032755070633524808?l=andreaswijayablog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andreaswijayablog.blogspot.com/feeds/9032755070633524808/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://andreaswijayablog.blogspot.com/2011/09/crm-2011-javascript-fetch-xml.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/9032755070633524808'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/9032755070633524808'/><link rel='alternate' type='text/html' href='http://andreaswijayablog.blogspot.com/2011/09/crm-2011-javascript-fetch-xml.html' title='CRM 2011 Javascript Fetch XML synchronous or asynchronous call'/><author><name>Andreas</name><uri>http://www.blogger.com/profile/07294319219169612936</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='23' src='http://2.bp.blogspot.com/_kEwj71YPhb8/TJiDclVlgOI/AAAAAAAAAEY/1Th4NMsgW_Q/S220/Andreas2.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2187748539439547090.post-728068810754767006</id><published>2011-09-08T14:33:00.000+08:00</published><updated>2011-09-08T14:33:03.706+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Dynamics CRM 2011'/><title type='text'>CRM 2011 Import Custom Workflow Error - Assembly must be registered in isolation</title><content type='html'>This error does not tell much, but I fixed it by adding myself as a Deployment Administrator.&lt;br /&gt;&lt;br /&gt;Hope this helps,&lt;br /&gt;Andreas&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2187748539439547090-728068810754767006?l=andreaswijayablog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andreaswijayablog.blogspot.com/feeds/728068810754767006/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://andreaswijayablog.blogspot.com/2011/09/crm-2011-import-custom-workflow-error.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/728068810754767006'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/728068810754767006'/><link rel='alternate' type='text/html' href='http://andreaswijayablog.blogspot.com/2011/09/crm-2011-import-custom-workflow-error.html' title='CRM 2011 Import Custom Workflow Error - Assembly must be registered in isolation'/><author><name>Andreas</name><uri>http://www.blogger.com/profile/07294319219169612936</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='23' src='http://2.bp.blogspot.com/_kEwj71YPhb8/TJiDclVlgOI/AAAAAAAAAEY/1Th4NMsgW_Q/S220/Andreas2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2187748539439547090.post-6362528285676921692</id><published>2011-09-08T14:16:00.003+08:00</published><updated>2011-09-08T19:36:28.193+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Dynamics CRM 2011'/><title type='text'>CRM 2011 Partial Refresh with jQuery</title><content type='html'>This post is a little update on my &lt;a href="http://andreaswijayablog.blogspot.com/2011/08/refresh-form-after-subgrid-changes-or.html"&gt;previous post&lt;/a&gt; regarding the Form Refresh after Sub-grid changes.&lt;br /&gt;&lt;br /&gt;I find the previous solution annoying in the way that when the user click 'Save' or 'Save and New' , the parent form that got refreshed would get the focus. Also, if the sub-grid had paging on it, the form would get refreshed when you move to the next page - thus you will always get the first page of the sub-grid.&lt;br /&gt;&lt;br /&gt;In order to avoid this I found a way to do a partial form element refresh using jQuery load function. The only tricky part is that you have to move your subgrid out of the tab that you want to do partial refresh on. (i.e. partial refresh does not work on sub-grid element).&lt;br /&gt;&lt;br /&gt;In my case, my fields that I want to update is on General Tab:&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: js" type="syntaxhighlighter"&gt;&lt;![CDATA[function ReLoadForm() {    $("#tab0").load(location.href + " #tab0&gt;*", "");}]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;hope this helps,&lt;br /&gt;Andreas&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2187748539439547090-6362528285676921692?l=andreaswijayablog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andreaswijayablog.blogspot.com/feeds/6362528285676921692/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://andreaswijayablog.blogspot.com/2011/09/crm-2011-partial-refresh-with-jquery.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/6362528285676921692'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/6362528285676921692'/><link rel='alternate' type='text/html' href='http://andreaswijayablog.blogspot.com/2011/09/crm-2011-partial-refresh-with-jquery.html' title='CRM 2011 Partial Refresh with jQuery'/><author><name>Andreas</name><uri>http://www.blogger.com/profile/07294319219169612936</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='23' src='http://2.bp.blogspot.com/_kEwj71YPhb8/TJiDclVlgOI/AAAAAAAAAEY/1Th4NMsgW_Q/S220/Andreas2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2187748539439547090.post-8667091957490644296</id><published>2011-09-06T12:27:00.002+08:00</published><updated>2011-09-06T12:46:37.327+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Dynamics CRM 2011'/><title type='text'>CRM 2011 Custom Workflow Activity - Send Email to Managers</title><content type='html'>In CRM 2011 (not online), you can create custom workflow activity for things that are not achievable using the OOTB workflow.&lt;br /&gt;&lt;br /&gt;In my scenario, I want to send Overdue Case Reminder to group of users (in this case - managers) when a case has reached the Follow Up By date. &lt;br /&gt;If you look at the SystemUser, it has a manager field by default. However, I need to be able to send the email to multiple managers.&lt;br /&gt;&lt;br /&gt;My idea is that we create a separate Security Role (e.g. Managers) and put all managers in that role. Then we create a custom workflow activity to get all the users in that role and construct an email to notify them when the case is overdue.&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: js" type="syntaxhighlighter"&gt;&lt;![CDATA[using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Activities;using Microsoft.Xrm.Sdk;using Microsoft.Xrm.Sdk.Metadata;using Microsoft.Xrm.Sdk.Workflow;using Microsoft.Xrm.Sdk.Query;using Microsoft.Xrm.Sdk.Messages;using Microsoft.Crm.Sdk.Messages;using Org.Entities.Crm;namespace My.Crm.WorkflowActivity{    /// &lt;summary&gt;    /// This custom workflow activity is intended to:    ///     Get Users from specific Security Role (e.g. Managers) and send the Case Overdue Reminder email to those users.    /// &lt;/summary&gt;       public class EmailCaseOverdueToSupervisors : CodeActivity    {        private Guid _emailId;        protected override void Execute(CodeActivityContext executionContext)        {            try            {                //Create the context and tracing service                IExecutionContext context = executionContext.GetExtension&lt;iexecutioncontext&gt;();                IOrganizationServiceFactory serviceFactory = executionContext.GetExtension&lt;iorganizationservicefactory&gt;();                IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);                ITracingService tracer = executionContext.GetExtension&lt;itracingservice&gt;();                         OrgServiceContext serviceContext = new OrgServiceContext(service);                Entity entity = service.Retrieve(context.PrimaryEntityName, context.PrimaryEntityId, new ColumnSet(true));                Incident caseEntity = entity.ToEntity&lt;incident&gt;();                                //get users from the security role input                tracer.Trace("Get users from the security role");                Guid secRoleId = SecurityRole.Get&lt;entityreference&gt;(executionContext).Id;                DataCollection&lt;entity&gt; users = GetUsersFromSecurityRole(secRoleId, service, tracer);                //construct emails for managers                if (users != null)                {                    var activityParties = new ActivityParty[users.Count];                    var activityParty = new List&lt;activityparty&gt;(); //used to add instances                    for (int i = 0; i &lt; users.Count; i++)                    {                        SystemUser user = users[i].ToEntity&lt;SystemUser&gt;();                        tracer.Trace("User FullName: " + user.FullName);                        //create an activity party and add it to the array if it's not the owner                        if (caseEntity.OwnerId.Id != user.Id)                        {                            activityParty.Add(new ActivityParty                                                {                                                    PartyId = new EntityReference(user.LogicalName, user.Id)                                                });                        }                    }                    activityParty.CopyTo(activityParties);                    SendOverdueCaseReminder(activityParties, caseEntity, serviceContext, service, executionContext);                }                tracer.Trace("Workflow finished");            }            catch (Exception ex)            {               Helpers.Throw(String.Format("An error occurred in the {0} plug-in.",                       this.GetType().ToString()),                     ex);            }            return;        }        private void SendOverdueCaseReminder(ActivityParty[] activityParties, Incident caseEntity, OrgServiceContext serviceContext, IOrganizationService service, CodeActivityContext context)        {            //get Admin account - LastName : Admin            var adminUser = serviceContext.SystemUserSet.Where(u =&gt; u.LastName == "Administrator").SingleOrDefault();            ActivityParty fromParty = new ActivityParty            {                PartyId = new EntityReference(adminUser.LogicalName, adminUser.Id)            };                  //construct Email            Email email = new Email            {                To = activityParties,                From = new ActivityParty[] { fromParty },                Subject = "Case Overdue Reminder for Supervisors",                Description = "Case details here",                DirectionCode = true            };            _emailId = service.Create(email);            // Use the SendEmail message to send an e-mail message.            SendEmailRequest sendEmailreq = new SendEmailRequest            {                EmailId = _emailId,                TrackingToken = "",                IssueSend = true            };            SendEmailResponse sendEmailresp = (SendEmailResponse)service.Execute(sendEmailreq);        }        private DataCollection&lt;entity&gt; GetUsersFromSecurityRole(Guid secRoleId, IOrganizationService service, ITracingService tracer)        {                QueryExpression query = new QueryExpression();                query.EntityName = "systemuser";                query.ColumnSet = new ColumnSet("systemuserid", "fullname", "internalemailaddress");                query.Criteria = new FilterExpression();                query.Criteria.AddCondition(new ConditionExpression("isdisabled", ConditionOperator.Equal, false));                Relationship relationship = new Relationship();                relationship.SchemaName = "systemuserroles_association";                RelationshipQueryCollection relatedEntity = new RelationshipQueryCollection();                relatedEntity.Add(relationship, query);                RetrieveRequest request = new RetrieveRequest();                request.RelatedEntitiesQuery = relatedEntity;                request.ColumnSet = new ColumnSet("roleid");                request.Target = new EntityReference {                    Id = secRoleId,                    LogicalName = "role"                };                RetrieveResponse response = (RetrieveResponse)service.Execute(request);                if (((DataCollection&lt;Relationship,EntityCollection&gt;)                    (((RelatedEntityCollection)(response.Entity.RelatedEntities)))).Contains(new Relationship("systemuserroles_association"))                     &amp;&amp; ((DataCollection&lt;Relationship,EntityCollection&gt;)                    (((RelatedEntityCollection)(response.Entity.RelatedEntities))))[new Relationship("systemuserroles_association")].Entities.Count &gt; 0)                {                    return response.Entity.RelatedEntities[new Relationship("systemuserroles_association")].Entities;                }                else                {                    return null;                }        }        #region Input Parameter        [RequiredArgument]        [Input("Case Link")]        public InArgument&lt;string&gt; CaseLink { get; set; }        [RequiredArgument]        [Input("EntityReference input")]        [ReferenceTarget("role")]        public InArgument&lt;entityreference&gt; SecurityRole { get; set; }        #endregion        #region Output Parameters        #endregion    }}]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Note: for the CaseLink input, I'm using the &lt;a href="http://crm2011workflowutils.codeplex.com/"&gt;CRM 2011 Workflow Utilities&lt;/a&gt; to generate the Case Link and put it into the Email Description field.&lt;br /&gt;&lt;br /&gt;Hope this helps,&lt;br /&gt;Andreas&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2187748539439547090-8667091957490644296?l=andreaswijayablog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andreaswijayablog.blogspot.com/feeds/8667091957490644296/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://andreaswijayablog.blogspot.com/2011/09/crm-2011-custom-workflow-activity-send.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/8667091957490644296'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/8667091957490644296'/><link rel='alternate' type='text/html' href='http://andreaswijayablog.blogspot.com/2011/09/crm-2011-custom-workflow-activity-send.html' title='CRM 2011 Custom Workflow Activity - Send Email to Managers'/><author><name>Andreas</name><uri>http://www.blogger.com/profile/07294319219169612936</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='23' src='http://2.bp.blogspot.com/_kEwj71YPhb8/TJiDclVlgOI/AAAAAAAAAEY/1Th4NMsgW_Q/S220/Andreas2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2187748539439547090.post-2177654046873384480</id><published>2011-09-06T11:23:00.000+08:00</published><updated>2011-09-06T11:23:47.127+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Dynamics CRM 2011'/><title type='text'>CRM 2011 Get OptionSetValue Label Text</title><content type='html'>In CRM 2011, when you try to get the value of an OptionSet, you will always get an Integer value instead of the label value.&lt;br /&gt;&lt;br /&gt;I found out that you have to use RetrieveAttributeRequest and get the OptionMetadata in order to get the label text of a given value. This is intended so that it supports multiple languages. &lt;br /&gt;&lt;br /&gt;Therefore I created a service extension method in order to get the label from the OptionSet:&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: csharp" type="syntaxhighlighter"&gt;&lt;![CDATA[        public static string GetOptionSetValueLabel(this IOrganizationService service, Entity entity, string attribute, OptionSetValue option)        {            string optionLabel = String.Empty;            RetrieveAttributeRequest attributeRequest = new RetrieveAttributeRequest            {                EntityLogicalName = entity.LogicalName,                LogicalName = attribute,                RetrieveAsIfPublished = true            };            RetrieveAttributeResponse attributeResponse = (RetrieveAttributeResponse)service.Execute(attributeRequest);            AttributeMetadata attrMetadata = (AttributeMetadata)attributeResponse.AttributeMetadata;            PicklistAttributeMetadata picklistMetadata = (PicklistAttributeMetadata)attrMetadata;            // For every status code value within all of our status codes values            //  (all of the values in the drop down list)            foreach (OptionMetadata optionMeta in                picklistMetadata.OptionSet.Options)            {                // Check to see if our current value matches                if (optionMeta.Value == option.Value)                {                    // If our numeric value matches, set the string to our status code                    //  label                    optionLabel = optionMeta.Label.UserLocalizedLabel.Label;                }            }            return optionLabel;        }]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;To use this you just need to pass in the Entity, the OptionSet attribute you're looking for, and the Option Value you want to get the label from:&lt;br /&gt;&lt;br /&gt;Example (early bound):&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: csharp" type="syntaxhighlighter"&gt;&lt;![CDATA[service.GetOptionSetValueLabel(caseEntity, "casetypecode", caseEntity.CaseTypeCode)]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Hope this helps,&lt;br /&gt;Andreas&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2187748539439547090-2177654046873384480?l=andreaswijayablog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andreaswijayablog.blogspot.com/feeds/2177654046873384480/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://andreaswijayablog.blogspot.com/2011/09/crm-2011-get-optionsetvalue-label-text.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/2177654046873384480'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/2177654046873384480'/><link rel='alternate' type='text/html' href='http://andreaswijayablog.blogspot.com/2011/09/crm-2011-get-optionsetvalue-label-text.html' title='CRM 2011 Get OptionSetValue Label Text'/><author><name>Andreas</name><uri>http://www.blogger.com/profile/07294319219169612936</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='23' src='http://2.bp.blogspot.com/_kEwj71YPhb8/TJiDclVlgOI/AAAAAAAAAEY/1Th4NMsgW_Q/S220/Andreas2.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2187748539439547090.post-3913998347874382365</id><published>2011-08-25T14:44:00.005+08:00</published><updated>2011-08-28T22:58:23.206+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Dynamics CRM 2011'/><title type='text'>CRM 2011 Convert Activity to Case - Populate Case Details</title><content type='html'>When converting an activity (such as Phone Call) to case, we can only specify the Customer and the Subject on the popup dialog. What if we want to auto-populate the case details with the information from the activity?&lt;br /&gt;&lt;br /&gt;At first I thought we can write a plugin that triggers on the post-create of a case. However this is not possible since CRM creates the Case before it sets the Regarding field on the Activity.&lt;br /&gt;&lt;br /&gt;The workaround for this is to create the post-update plugin on the Activity itself. This way when the Regarding field is assigned by CRM, it will look for the Case and update its details. &lt;br /&gt;&lt;br /&gt;&lt;script class="brush: csharp" type="syntaxhighlighter"&gt;&lt;![CDATA[using System;using System.Collections.Generic;using System.Linq;using System.Text;using Microsoft.Xrm.Sdk;using Microsoft.Xrm.Sdk.Messages;using System.ServiceModel;using Org.Entities.Crm;namespace Org.Crm.Plugins{    /// &lt;summary&gt;    /// This plugin is intended to:    /// 1. Hook up to post-update message of phone call entity.    ///    Update Case Details if any    /// &lt;/summary&gt;    public class PhoneCallUpdateCaseDetails : IPlugin    {        ITracingService tracingService = null;        public void Execute(IServiceProvider serviceProvider)        {            // Extract the tracing service.            tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));            if (tracingService == null)                throw new InvalidPluginExecutionException("Failed to retrieve the tracing service.");            // Obtain the execution context from the service provider.            IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));            // The InputParameters collection contains all the data passed in the message request.            if (context.InputParameters.Contains("Target") &amp;&amp; context.InputParameters["Target"] is Entity)            {                // Obtain the target entity from the input parameters.                Entity entity = (Entity)context.InputParameters["Target"];                // Get a reference to the Organization service.                IOrganizationServiceFactory factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));                IOrganizationService service = factory.CreateOrganizationService(context.UserId);                try                {                    // Plug-in business logic goes below this line.                    // Invoke organization service methods.#if DEBUG                    tracingService.Trace("{0} Plugin started.", this.GetType().Name);#endif                    OrgServiceContext serviceContext = new OrgServiceContext (service);                    PhoneCall retrievedPhoneCall = serviceContext.PhoneCallSet.Where(x =&gt; x.Id == entity.Id).SingleOrDefault();                    if (retrievedPhoneCall.RegardingObjectId != null)                    {                        PopulateDetails(retrievedPhoneCall, serviceContext, tracingService);                    }#if DEBUG                    tracingService.Trace("{0} Plugin completed.", this.GetType().Name);#endif                }                catch (InvalidPluginExecutionException iex)                {                    tracingService.Trace(iex.Message);                    tracingService.Trace(iex.StackTrace);                    throw iex;                }                catch (FaultException&lt;organizationservicefault&gt; ex)                {                    tracingService.Trace(ex.Message);                    tracingService.Trace(ex.StackTrace);                    throw new InvalidPluginExecutionException(string.Format("An error occurred in the {0} plug-in.", this.GetType().Name), ex);                }                catch (Exception e)                {                    tracingService.Trace(e.Message);                    tracingService.Trace(e.StackTrace);                    throw new InvalidPluginExecutionException(string.Format("An error occurred in the {0} plug-in.", this.GetType().Name), e);                }            }        }        /// &lt;summary&gt;        /// Populate Details        /// &lt;/summary&gt;private void PopulateDetails(PhoneCall retrievedPhoneCall, OrgServiceContext serviceContext, ITracingService tracingService)        {            Incident incident = serviceContext.IncidentSet.Where(c =&gt; c.Id == retrievedPhoneCall.RegardingObjectId.Id).SingleOrDefault();            if (incident != null)            {                var phoneCalls = serviceContext.PhoneCallSet.Where(p =&gt; p.RegardingObjectId == new EntityReference(incident.LogicalName, incident.Id)).ToList();                //check if this is the first time creation                if (phoneCalls.Count &lt;= 1)                {                    incident.Title = retrievedPhoneCall.Subject;                    incident.new_accountid = retrievedPhoneCall.new_accountid == null ? null : retrievedPhoneCall.new_accountid;                    incident.new_accountnumber = String.IsNullOrEmpty(retrievedPhoneCall.new_accountnumber) ? null : retrievedPhoneCall.new_accountnumber;                    incident.CustomerId = retrievedPhoneCall.From.FirstOrDefault().PartyId;                    incident.CaseOriginCode = new OptionSetValue(1);                    serviceContext.UpdateObject(incident);                    serviceContext.SaveChanges();                }            }        }    }}]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Be careful though because this might not work when converting Activity to Case from Outlook. I read somewhere that when converting Email to Outlook, the Regarding field is set to the Parent Customer of the Case rather than the Case itself.&lt;br /&gt;&lt;br /&gt;Hope this helps,&lt;br /&gt;Andreas&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2187748539439547090-3913998347874382365?l=andreaswijayablog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andreaswijayablog.blogspot.com/feeds/3913998347874382365/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://andreaswijayablog.blogspot.com/2011/08/crm-2011-convert-activity-to-case.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/3913998347874382365'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/3913998347874382365'/><link rel='alternate' type='text/html' href='http://andreaswijayablog.blogspot.com/2011/08/crm-2011-convert-activity-to-case.html' title='CRM 2011 Convert Activity to Case - Populate Case Details'/><author><name>Andreas</name><uri>http://www.blogger.com/profile/07294319219169612936</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='23' src='http://2.bp.blogspot.com/_kEwj71YPhb8/TJiDclVlgOI/AAAAAAAAAEY/1Th4NMsgW_Q/S220/Andreas2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2187748539439547090.post-3735295738292345942</id><published>2011-08-23T14:59:00.002+08:00</published><updated>2011-08-25T14:36:51.341+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Dynamics CRM 2011'/><title type='text'>CRM 2011 Custom Filtered Lookup</title><content type='html'>Sometimes the filtered lookup functionality provided by CRM 2011 doesn't fit your requirement. However Microsoft provides a function for us to add our own custom view for the lookup field. &lt;br /&gt;&lt;br /&gt;Example: In a 'Case' form we have customer field. I use this field only for 'Contacts', and I have created a relationship to the 'Account' so that we can see both on the form. I want the Accounts to only show Contacts that have 'Connections To' and vice versa (Only show Contacts that have 'Connections From' if I specified the Account first). If nothing is specified then I want both to show just Active Contacts/Accounts.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-6AXDwwzsF2I/TlXteFUf1xI/AAAAAAAAAIQ/Lm9bd4AGf6s/s1600/case.jpg" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="210" width="320" src="http://3.bp.blogspot.com/-6AXDwwzsF2I/TlXteFUf1xI/AAAAAAAAAIQ/Lm9bd4AGf6s/s320/case.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;The script:&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: js" type="syntaxhighlighter"&gt;&lt;![CDATA[/////////////////////////////////Account Filtered Lookup /////////////////////////////////function setAccountLookup(contactFieldName, lookupFieldName, resetSelection) {    var defaultViewId = "00000000-0000-0000-00AA-000010001002";    // Get the selected Contact Id in the [accountFieldName] indicated control    var contact = Xrm.Page.getAttribute(contactFieldName).getValue();    if (contact != null) {        var contactId = contact[0].id;        var contactName = contact[0].name;        if (resetSelection == true) {            resetAccountSelection(lookupFieldName);        }        // use randomly generated GUID Id for our new view        var viewId = "{1DFB2B35-B07C-44D1-868D-258DEEAB88E2}";        var entityName = "account";        // give the custom view a name        var viewDisplayName = "Active Accounts for " + contactName + "";        // find all accounts where [Primary Contact Id] = [Contact indicated by ContactId]        // AND where [Statecode] = Active        var fetchXml = "&lt;fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='false'&gt;" +                     "&lt;entity name='account'&gt;" +                     "&lt;attribute name='name' /&gt;" +                     "&lt;attribute name='accountnumber' /&gt;" +                     "&lt;attribute name='address1_city' /&gt;" +                     "&lt;attribute name='telephone1' /&gt;" +                     "&lt;attribute name='emailaddress1' /&gt;" +                     "&lt;attribute name='accountid' /&gt;" +                     "&lt;order attribute='accountnumber' descending='false' /&gt;" +                     "&lt;filter type='and'&gt;" +                     "&lt;condition attribute='statecode' operator='eq' value='0' /&gt;" +                     "&lt;/filter&gt;" +                     "&lt;link-entity name='connection' alias='aa' to='accountid' from='record2id'&gt;" +                     "&lt;filter type='and'&gt;" +                     "&lt;condition attribute='record1id' operator='eq' value='" + contactId + "' /&gt;" +                     "&lt;/filter&gt;" +                     "&lt;/link-entity&gt;" +                     "&lt;/entity&gt;" +                     "&lt;/fetch&gt;";        // build Grid Layout        var layoutXml = "&lt;grid name='resultset' " +                               "object='1' " +                               "jump='accountid' " +                               "select='1' " +                               "icon='1' " +                               "preview='1'&gt;" +                           "&lt;row name='result' " +                                "id='accountid'&gt;" +                             "&lt;cell name='name' " +                                   "width='200' /&gt;" +                             "&lt;cell name='accountnumber' " +                                   "width='200' /&gt;" +                             "&lt;cell name='address1_city' " +                                   "width='200' /&gt;" +                             "&lt;cell name='telephone1' " +                                   "width='200' /&gt;" +                             "&lt;cell name='emailaddress1' " +                                   "width='200' /&gt;" +                           "&lt;/row&gt;" +                         "&lt;/grid&gt;";        // add the Custom View to the indicated [lookupFieldName] Control        Xrm.Page.getControl(lookupFieldName).addCustomView(viewId, entityName, viewDisplayName, fetchXml, layoutXml, true);    }    else {        // no Contact selected, reset Account Lookup View to the default view such that all Accounts are displayed for selection        if (resetSelection == true) {            resetAccountSelection(lookupFieldName);        }        Xrm.Page.getControl(lookupFieldName).setDefaultView(defaultViewId);    }}function resetAccountSelection(lookupFieldName) {    // reset old selection for Account    Xrm.Page.getAttribute(lookupFieldName).setValue(null);    Xrm.Page.getAttribute("new_accountnumber").setValue(null);}/////////////////////////////////Contact Filtered Lookup /////////////////////////////////function setContactLookup(accountFieldName, lookupFieldName, resetSelection) {    var defaultViewId = "00000000-0000-0000-00AA-000010001004";    // Get the selected Contact Id in the [accountFieldName] indicated control    var account = Xrm.Page.getAttribute(accountFieldName).getValue();    if (account != null) {        var accountId = account[0].id;        var accountName = account[0].name;        if (resetSelection == true) {            resetContactSelection(lookupFieldName);        }        // use randomly generated GUID Id for our new view        var viewId = "{1DFB2B35-B07C-44D1-868D-258DEEAB88E3}";        var entityName = "contact";        // give the custom view a name        var viewDisplayName = "Active Contacts for " + accountName + "";        // find all accounts where [Primary Contact Id] = [Contact indicated by ContactId]        // AND where [Statecode] = Active        var fetchXml = "&lt;fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='false'&gt;" +                     "&lt;entity name='contact'&gt;" +                     "&lt;attribute name='fullname' /&gt;" +                     "&lt;attribute name='telephone1' /&gt;" +                     "&lt;attribute name='contactid' /&gt;" +                     "&lt;attribute name='address1_line1' /&gt;" +                     "&lt;attribute name='address1_city' /&gt;" +                     "&lt;attribute name='address1_postalcode' /&gt;" +                     "&lt;attribute name='address1_stateorprovince' /&gt;" +                     "&lt;attribute name='emailaddress1' /&gt;" +                     "&lt;order attribute='fullname' descending='false' /&gt;" +                     "&lt;filter type='and'&gt;" +                     "&lt;condition attribute='statecode' operator='eq' value='0' /&gt;" +                     "&lt;/filter&gt;" +                     "&lt;link-entity name='connection' alias='aa' to='contactid' from='record1id'&gt;" +                     "&lt;filter type='and'&gt;" +                     "&lt;condition attribute='record2id' operator='eq' value='" + accountId + "' /&gt;" +                     "&lt;/filter&gt;" +                     "&lt;/link-entity&gt;" +                     "&lt;/entity&gt;" +                     "&lt;/fetch&gt;";        // build Grid Layout        var layoutXml = "&lt;grid name='resultset' " +                               "object='1' " +                               "jump='contactid' " +                               "select='1' " +                               "icon='1' " +                               "preview='1'&gt;" +                           "&lt;row name='result' " +                                "id='contactid'&gt;" +                             "&lt;cell name='fullname' " +                                   "width='200' /&gt;" +                             "&lt;cell name='telephone1' " +                                   "width='200' /&gt;" +                             "&lt;cell name='address1_line1' " +                                   "width='200' /&gt;" +                             "&lt;cell name='address1_city' " +                                   "width='200' /&gt;" +                             "&lt;cell name='address1_postalcode' " +                                   "width='200' /&gt;" +                             "&lt;cell name='address1_stateorprovince' " +                                   "width='200' /&gt;" +                             "&lt;cell name='emailaddress1' " +                                   "width='200' /&gt;" +                           "&lt;/row&gt;" +                         "&lt;/grid&gt;";        // add the Custom View to the indicated [lookupFieldName] Control        Xrm.Page.getControl(lookupFieldName).addCustomView(viewId, entityName, viewDisplayName, fetchXml, layoutXml, true);    }    else {        // no Contact selected, reset Account Lookup View to the default view such that all Accounts are displayed for selection        if (resetSelection == true) {            resetContactSelection(lookupFieldName);        }        Xrm.Page.getControl(lookupFieldName).setDefaultView(defaultViewId);    }}function resetContactSelection(lookupFieldName) {    // reset old selection for Account    Xrm.Page.getAttribute(lookupFieldName).setValue(null);}]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Then you can use it like this:&lt;br /&gt;&lt;script class="brush: js" type="syntaxhighlighter"&gt;&lt;![CDATA[function Form_onload() {    setAccountLookup("customerid", "new_accountid", false);}function Contact_onchange() {    setAccountLookup("customerid", "new_accountid", false);    setContactLookup("new_accountid", "customerid", false);}function Account_onchange() {    retrieveAccountNumber("new_accountnumber", "new_accountid");    setContactLookup("new_accountid", "customerid", false);    setAccountLookup("customerid", "new_accountid", false);}]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;However there is still a major limitation of FetchXML that you cannot use UNION clause (or something similar). So If you want to show the primarycontact/parentcustomer along with the connections, you're out of luck as you can only do one of them.&lt;br /&gt;&lt;br /&gt;Hope this helps,&lt;br /&gt;Andreas&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2187748539439547090-3735295738292345942?l=andreaswijayablog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andreaswijayablog.blogspot.com/feeds/3735295738292345942/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://andreaswijayablog.blogspot.com/2011/08/crm-2011-custom-filtered-lookup.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/3735295738292345942'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/3735295738292345942'/><link rel='alternate' type='text/html' href='http://andreaswijayablog.blogspot.com/2011/08/crm-2011-custom-filtered-lookup.html' title='CRM 2011 Custom Filtered Lookup'/><author><name>Andreas</name><uri>http://www.blogger.com/profile/07294319219169612936</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='23' src='http://2.bp.blogspot.com/_kEwj71YPhb8/TJiDclVlgOI/AAAAAAAAAEY/1Th4NMsgW_Q/S220/Andreas2.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-6AXDwwzsF2I/TlXteFUf1xI/AAAAAAAAAIQ/Lm9bd4AGf6s/s72-c/case.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2187748539439547090.post-8454580522927416080</id><published>2011-08-23T12:23:00.001+08:00</published><updated>2011-08-23T15:00:00.526+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Dynamics CRM 2011'/><title type='text'>CRM 2011 Javascript Retrieve Record using jQuery REST Endpoints.</title><content type='html'>Using jQuery and REST Endpoints is one of the easiest way to get record details in CRM 2011. &lt;br /&gt;&lt;br /&gt;To do this you just need to include:&lt;br /&gt;1. jquery-1.6.2.min.js (or just get the latest version)&lt;br /&gt;2. json2.js &lt;br /&gt;&lt;br /&gt;The SDK provides some functions for retrieving records:&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: js" type="syntaxhighlighter"&gt;&lt;![CDATA[function retrieveRecord(id, odataSetName, successCallback, errorCallback) {    var context = Xrm.Page.context;    var serverUrl = context.getServerUrl();    var ODATA_ENDPOINT = "/XRMServices/2011/OrganizationData.svc";    //id is required    if (!id) {        alert("record id is required.");        return;    }    //odataSetName is required, i.e. "AccountSet"    if (!odataSetName) {        alert("odataSetName is required.");        return;    }    //Asynchronous AJAX function to Retrieve a CRM record using OData    $.ajax({        type: "GET",        contentType: "application/json; charset=utf-8",        datatype: "json",        url: serverUrl + ODATA_ENDPOINT + "/" + odataSetName + "(guid'" + id + "')",        beforeSend: function (XMLHttpRequest) {            //Specifying this header ensures that the results will be returned as JSON.                         XMLHttpRequest.setRequestHeader("Accept", "application/json");        },        success: function (data, textStatus, XmlHttpRequest) {            if (successCallback) {                successCallback(data.d, textStatus, XmlHttpRequest);            }        },        error: function (XmlHttpRequest, textStatus, errorThrown) {            if (errorCallback)                errorCallback(XmlHttpRequest, textStatus, errorThrown);            else                errorHandler(XmlHttpRequest, textStatus, errorThrown);        }    });}function retrieveMultiple(odataSetName, filter, successCallback, errorCallback) {    var context = Xrm.Page.context;    var serverUrl = context.getServerUrl();    var ODATA_ENDPOINT = "/XRMServices/2011/OrganizationData.svc";    //odataSetName is required, i.e. "AccountSet"    if (!odataSetName) {        alert("odataSetName is required.");        return;    }    //Build the URI    var odataUri = serverUrl + ODATA_ENDPOINT + "/" + odataSetName;    //If a filter is supplied, append it to the OData URI    if (filter) {        odataUri += filter;    }    //Asynchronous AJAX function to Retrieve CRM records using OData    $.ajax({        type: "GET",        contentType: "application/json; charset=utf-8",        datatype: "json",        url: odataUri,        beforeSend: function (XMLHttpRequest) {            //Specifying this header ensures that the results will be returned as JSON.                         XMLHttpRequest.setRequestHeader("Accept", "application/json");        },        success: function (data, textStatus, XmlHttpRequest) {            if (successCallback) {                if (data &amp;&amp; data.d &amp;&amp; data.d.results) {                    successCallback(data.d.results, textStatus, XmlHttpRequest);                }                else if (data &amp;&amp; data.d) {                    successCallback(data.d, textStatus, XmlHttpRequest);                }                else {                    successCallback(data, textStatus, XmlHttpRequest);                }            }        },        error: function (XmlHttpRequest, textStatus, errorThrown) {            if (errorCallback)                errorCallback(XmlHttpRequest, textStatus, errorThrown);            else                errorHandler(XmlHttpRequest, textStatus, errorThrown);        }    });}function errorHandler(xmlHttpRequest, textStatus, errorThrow) {    alert("Error : " + textStatus + ": " + xmlHttpRequest.statusText);}]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Use retrieveRecord if you know the ID of the record. Otherwise, use retrieveMultiple if you want to get the record(s) based on some filters as it will return an array of result objects.&lt;br /&gt;&lt;br /&gt;Example:&lt;br /&gt;In a custom entity form, I have an Account lookup field and an Account Number field. I want to auto-populate one of the field based on the other field and vice versa. Therefore:&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: js" type="syntaxhighlighter"&gt;&lt;![CDATA[function Account_onchange() {    retrieveAccountNumber();}function AccountNumber_onchange() {    retrieveAccountByAccountNumber();}function retrieveAccountByAccountNumber() {    var accountNumber = Xrm.Page.getAttribute("new_accountnumber").getValue();    if (accountNumber != null) {        retrieveMultiple("AccountSet", "?$filter=AccountNumber eq '" + accountNumber + "'", retrieveAccountCompleted, null);    }    else {        Xrm.Page.getAttribute("new_accountid").setValue(null);    }}function retrieveAccountNumber() {    var accountLookup = new Array();    accountLookup = Xrm.Page.getAttribute("new_accountid").getValue();    if (accountLookup == null) {        Xrm.Page.getAttribute("new_accountnumber").setValue(null);    }    else {        var accountId = accountLookup[0].id;        retrieveRecord(accountId, "AccountSet", retrieveAccountNumberCompleted, null);    }}function retrieveAccountNumberCompleted(data, textStatus, XmlHttpRequest) {    //Get back the Account JSON object    var account = data;    Xrm.Page.getAttribute("new_accountnumber").setValue(account.AccountNumber);}function retrieveAccountCompleted(data, textStatus, XmlHttpRequest) {    //Get back the Account JSON object    var account = data;    if (account.length == 1 &amp;&amp; account[0].AccountId != null) {        var accountLookup = [{ entityType: "account", id: account[0].AccountId, name: account[0].Name}];        Xrm.Page.getAttribute("new_accountid").setValue(accountLookup);    }    else {        alert("No account matches this account number");        Xrm.Page.getAttribute("new_accountid").setValue(null);    }}]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Hope this helps,&lt;br /&gt;Andreas&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2187748539439547090-8454580522927416080?l=andreaswijayablog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andreaswijayablog.blogspot.com/feeds/8454580522927416080/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://andreaswijayablog.blogspot.com/2011/08/crm-2011-javascript-retrieve-record.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/8454580522927416080'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/8454580522927416080'/><link rel='alternate' type='text/html' href='http://andreaswijayablog.blogspot.com/2011/08/crm-2011-javascript-retrieve-record.html' title='CRM 2011 Javascript Retrieve Record using jQuery REST Endpoints.'/><author><name>Andreas</name><uri>http://www.blogger.com/profile/07294319219169612936</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='23' src='http://2.bp.blogspot.com/_kEwj71YPhb8/TJiDclVlgOI/AAAAAAAAAEY/1Th4NMsgW_Q/S220/Andreas2.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2187748539439547090.post-7863110329348528996</id><published>2011-08-16T15:09:00.010+08:00</published><updated>2011-09-27T16:54:39.500+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Dynamics CRM 2011'/><title type='text'>CRM 2011 Auto-populate Name from Fields or Attributes</title><content type='html'>Are you tired of thinking about what to put into the name field when creating records and want a way to populate that name automatically? &lt;br /&gt;&lt;br /&gt;I have created a service extension method to make my life easier. The goal of this is to autopopulate name field using the format like [field1] - [field2] - [field3] through pre-plugin:&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: csharp" type="syntaxhighlighter"&gt;&lt;![CDATA[using System;using System.Collections.Generic;using System.Linq;using System.Text;using Microsoft.Xrm.Sdk;using Microsoft.Xrm.Sdk.Query;using Microsoft.Xrm.Sdk.Messages;using Microsoft.Xrm.Sdk.Metadata;using System.ServiceModel;namespace My.Plugins{    public static class ServiceExtensions    {        public static string GenerateNameByFields(this IOrganizationService service, Entity entity, ColumnSet colSet, string message)        {            var list = new List&lt;string&gt;();            foreach (string fieldName in colSet.Columns)            {                //fields changed                if (entity.Contains(fieldName))                {                    if (entity[fieldName] != null)                    {                        //check if lookup field                        if (entity.Attributes[fieldName].GetType().Equals(typeof(Microsoft.Xrm.Sdk.EntityReference)))                        {                            string primaryNameAttribute = service.GetPrimaryNameAttributeByLookupField(entity, fieldName);                            //needs to use retrieve to get the lookup entity first                            string lookupEntityName = ((EntityReference)entity.Attributes[fieldName]).LogicalName;                            Entity lookupEntity = service.Retrieve(lookupEntityName, ((EntityReference)entity[fieldName]).Id, new ColumnSet(true));                            if (lookupEntity.Attributes.Contains(primaryNameAttribute))                            {                                list.Add(lookupEntity.Attributes[primaryNameAttribute].ToString());                            }                        }                        //for boolean other than yes/no                        else if (fieldName == "new_type")                        {                            string type = ((bool?)entity.Attributes[fieldName]).Value == false ? "Win" : "Loss";                            list.Add(type);                        }                        else                        {                            list.Add(entity.Attributes[fieldName].ToString());                        }                    }                }                //fields unchanged - use retrievedEntity                else                 {                    if (message == "update")                    {                        Entity retrievedEntity = service.Retrieve(entity.LogicalName, entity.Id, colSet);                        if (retrievedEntity != null &amp;&amp; retrievedEntity.Contains(fieldName))                        {                            //check if lookup field                            if (retrievedEntity.Attributes[fieldName].GetType().Equals(typeof(Microsoft.Xrm.Sdk.EntityReference)))                            {                                list.Add(((EntityReference)retrievedEntity.Attributes[fieldName]).Name);                            }                            else if (fieldName == "new_type")                            {                                string type = ((bool?)retrievedEntity.Attributes[fieldName]).Value == false ? "Win" : "Loss";                                list.Add(type);                            }                            else                            {                                //check if it's a decimal value                                decimal decimalNumber = 0;                                bool canConvert = decimal.TryParse(retrievedEntity.Attributes[fieldName].ToString(), out decimalNumber);                                if (canConvert == true)                                    list.Add(String.Format("{0:0.##}", decimalNumber));                                else                                    list.Add(retrievedEntity.Attributes[fieldName].ToString());                            }                        }                    }                }            }            //join the string with the delimiter            string generatedName = string.Join(" - ", list);            return generatedName;        }        public static string GetPrimaryNameAttributeByLookupField(this IOrganizationService service, Entity entity, string fieldName)        {            RetrieveEntityRequest retrieveRequest = new RetrieveEntityRequest            {                EntityFilters = EntityFilters.Entity,                LogicalName = ((EntityReference)entity[fieldName]).LogicalName            };            RetrieveEntityResponse retrieveResponse = (RetrieveEntityResponse)service.Execute(retrieveRequest);            return retrieveResponse.EntityMetadata.PrimaryNameAttribute;        }    }}]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;To use this you just need to construct the column set and pass in the entity from the plugin context:&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: csharp" type="syntaxhighlighter"&gt;&lt;![CDATA[                    //Generate Name                    ColumnSet colSet = new ColumnSet("new_field1", "new_field2", "new_field3");                    string generatedName = service.GenerateNameByFields(entity, colSet);                    entity["new_name"] = generatedName;       ]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;We also need a javascript to disable this name field when the form load:&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: js" type="syntaxhighlighter"&gt;&lt;![CDATA[// JScript source codefunction Form_onload() {    setAutoName("new_name");}function setAutoName(fieldname) {    var nameField = Xrm.Page.getAttribute(fieldname).getValue();    if (nameField != null) {        SetDisableField(fieldname, true);    }    else {        Xrm.Page.getAttribute(fieldname).setValue("&lt;System Generated&gt;");        SetDisableField(fieldname, true);    }}]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Hope this helps,&lt;br /&gt;Andreas&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2187748539439547090-7863110329348528996?l=andreaswijayablog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andreaswijayablog.blogspot.com/feeds/7863110329348528996/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://andreaswijayablog.blogspot.com/2011/08/crm-2011-auto-populate-name-from-fields.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/7863110329348528996'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/7863110329348528996'/><link rel='alternate' type='text/html' href='http://andreaswijayablog.blogspot.com/2011/08/crm-2011-auto-populate-name-from-fields.html' title='CRM 2011 Auto-populate Name from Fields or Attributes'/><author><name>Andreas</name><uri>http://www.blogger.com/profile/07294319219169612936</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='23' src='http://2.bp.blogspot.com/_kEwj71YPhb8/TJiDclVlgOI/AAAAAAAAAEY/1Th4NMsgW_Q/S220/Andreas2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2187748539439547090.post-2268863401425138561</id><published>2011-08-12T08:48:00.001+08:00</published><updated>2011-08-12T08:48:31.373+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Dynamics CRM 2011'/><title type='text'>CRM 2011 Refresh Form after Subgrid Changes or Refresh</title><content type='html'>I found on some articles that to be able to do this you need to attach an OnRefresh event to the element that then calls the function to load the parent window again:&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: js" type="syntaxhighlighter"&gt;&lt;![CDATA[var grid = document.getElementById("MySubGrid");grid.attachEvent("onrefresh", ReLoadForm);]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;When I deployed to CRM 2011 Rollup 3, I found some issues that throw error like null object (document not ready) and in some IE versions the form keeps refreshing for eternity... &lt;br /&gt;&lt;br /&gt;After spending some time investigating this annoying issue, I found out that we have to wait for the subgrid to finish loading its contents for this to work properly. The final javascript is as follows:&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: js" type="syntaxhighlighter"&gt;&lt;![CDATA[function Form_onload() {    setTimeout("SubGridRefresh();", 2500);}function SubGridRefresh() {    var grid = document.getElementById("MySubGrid");    if (grid) {        grid.attachEvent("onrefresh", ReLoadForm);    }}function ReLoadForm() {    window.location.reload(true);}]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Hope this helps,&lt;br /&gt;Andreas&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2187748539439547090-2268863401425138561?l=andreaswijayablog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andreaswijayablog.blogspot.com/feeds/2268863401425138561/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://andreaswijayablog.blogspot.com/2011/08/refresh-form-after-subgrid-changes-or.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/2268863401425138561'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/2268863401425138561'/><link rel='alternate' type='text/html' href='http://andreaswijayablog.blogspot.com/2011/08/refresh-form-after-subgrid-changes-or.html' title='CRM 2011 Refresh Form after Subgrid Changes or Refresh'/><author><name>Andreas</name><uri>http://www.blogger.com/profile/07294319219169612936</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='23' src='http://2.bp.blogspot.com/_kEwj71YPhb8/TJiDclVlgOI/AAAAAAAAAEY/1Th4NMsgW_Q/S220/Andreas2.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2187748539439547090.post-6333962747597975656</id><published>2011-08-10T08:45:00.001+08:00</published><updated>2011-08-10T08:49:27.676+08:00</updated><title type='text'>CRM Report Pre-Filtering with Multiple Datasets</title><content type='html'>As you know there are two ways of doing pre-filtering with CRM Reports (SQL and not FetchXML). The first one is using the CRMAF_ prefix alias like this:&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: js" type="syntaxhighlighter"&gt;&lt;![CDATA[SELECT AccountName, AccountNumberFROM FilteredAccount AS CRMAF_FilteredAccount;]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;I soon found limitation using this method. You can't use the &lt;b&gt;same &lt;/b&gt;CRMAF_Filtered&lt;entity&gt;&lt;/entity&gt; multiple times because it only filters on the first instance.&lt;br /&gt;&lt;br /&gt;Therefore if you have multiple datasets or UNION query that are using that filter more than once, it will not work. To avoid this issue, we can use the Explicit pre-filtering - the second method that CRM provides.&lt;br /&gt;&lt;br /&gt;Let's say that you want to have a report that display single Account details and the associated related records information. However rather than building complex single query you want to break it down into multiple datasets. &lt;br /&gt;&lt;br /&gt;The Steps:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Create a parameter called @CRM_FilteredAccount. You can set the default value to just:&lt;br /&gt;&lt;script class="brush: js" type="syntaxhighlighter"&gt;&lt;![CDATA[SELECT * FROM FilteredAccount]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Build your datasets using this parameter. Use the SQL Dynamic Query so that CRM will replace the parameter with the Advanced Find instance that you specify when running the report. &lt;br /&gt;&lt;br /&gt;These are two of the dataset examples:&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: js" type="syntaxhighlighter"&gt;&lt;![CDATA[DECLARE @SQL as nVarchar(max)SET @sql = ' SELECT accountnumber, name FROM (' + @CRM_FilteredAccount + ') AS AFFA'EXEC(@SQL)]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: js" type="syntaxhighlighter"&gt;&lt;![CDATA[DECLARE @SQL nvarchar(max)SET @SQL = 'SELECT FA.accountid AS AccountId,        FA.name AS Name,        O.new_seasonidname AS Season,        O.new_commodityidname AS Commodity,       CI.new_zonename AS Zone,       CI.new_gradeidname AS Grade,       CI.new_tonnes AS Tonnes,       CI.new_targetprice AS TargetPrice,       CI.new_productidname AS ProductFROM FilteredOpportunity O LEFT JOIN     Filterednew_commodityinformation CI ON CI.new_opportunityid = O.opportunityid LEFT JOIN 	 FilteredAccount FA ON O.accountid = FA.accountid INNER JOIN ('+@CRM_FilteredAccount+') AS AFFA ON FA.parentaccountid = AFFA.accountid WHERE O.statecodename = ''Open'''EXEC(@SQL)]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;Hope this helps,&lt;br /&gt;Andreas&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2187748539439547090-6333962747597975656?l=andreaswijayablog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andreaswijayablog.blogspot.com/feeds/6333962747597975656/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://andreaswijayablog.blogspot.com/2011/08/crm-report-pre-filtering-with-multiple.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/6333962747597975656'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/6333962747597975656'/><link rel='alternate' type='text/html' href='http://andreaswijayablog.blogspot.com/2011/08/crm-report-pre-filtering-with-multiple.html' title='CRM Report Pre-Filtering with Multiple Datasets'/><author><name>Andreas</name><uri>http://www.blogger.com/profile/07294319219169612936</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='23' src='http://2.bp.blogspot.com/_kEwj71YPhb8/TJiDclVlgOI/AAAAAAAAAEY/1Th4NMsgW_Q/S220/Andreas2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2187748539439547090.post-8614963309627269350</id><published>2011-08-09T10:07:00.000+08:00</published><updated>2011-08-09T10:07:24.520+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Dynamics CRM 2011'/><title type='text'>CRM 2011 Embed Report in IFrame and Pass Parameters from the Form</title><content type='html'>In CRM you can insert SubGrid and Chart. However this functionality is limited in a way that it can only grab the related entities that have direct relationship to that entity. If we want to get the other related entities from the related entity, it's not possible using the OOTB Subgrid and Chart.&lt;br /&gt;&lt;br /&gt;In my case I want to display a chart in an Engagement Plan entity. This Engagement Plan is associated with an Account (N:1). The Account has 1:N relationships with Production History and Contract History entities that have information about commodity and tonnes produced. I want that chart to be shown on the Engagement Plan form. The parameters for this chart will be the Account Id and the Season Id located on the form.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-HqRc3MKwv6U/TkCTlTjPd6I/AAAAAAAAAII/aEW1RLvHEN8/s1600/EngPlan.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="249" src="http://2.bp.blogspot.com/-HqRc3MKwv6U/TkCTlTjPd6I/AAAAAAAAAII/aEW1RLvHEN8/s320/EngPlan.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;The Steps:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Create a custom SSRS Report to display this chart, taking @CRM_AccountId and @CRM_SeasonId as parameters.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Insert an IFRAME on the form and give dummy Url. Also uncheck 'Restrict Cross Site Scripting' to allow cross scripting between servers. &lt;br /&gt;&lt;/li&gt;&lt;li&gt;Create a javascript that is triggered in Form_OnLoad, Account_OnChange, and Season_OnChange:&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: js" type="syntaxhighlighter"&gt;&lt;![CDATA[// JScript source codefunction Form_onload() {    loadChart();}function loadChart() {    var growerLookupItem = new Array();    growerLookupItem = Xrm.Page.getAttribute("new_growerentityid").getValue();    var seasonLookupItem = new Array();    seasonLookupItem = Xrm.Page.getAttribute("new_seasonid").getValue();    var serverUrl = Xrm.Page.context.getServerUrl();    var url = serverUrl + "/crmreports/viewer/viewer.aspx?action=filter&amp;helpID=CommodityTonnes.rdl&amp;id=%7bB135D3F7-65C1-E011-A653-005056A10003%7d";    SetReportUrl(url, "IFRAME_CommodityTonnes", growerLookupItem, seasonLookupItem);}function SetReportUrl(reportUrl, iFrame, growerLookupItem, seasonLookupItem) {    if (growerLookupItem == null || seasonLookupItem == null) {        Xrm.Page.getControl(iFrame).setVisible(false);    }    else {        Xrm.Page.getControl(iFrame).setVisible(true);        var growerId = growerLookupItem[0].id;        var seasonId = seasonLookupItem[0].id;        Xrm.Page.getControl(iFrame).setSrc(reportUrl + "&amp;p:CRM_AccountId=" + growerId + "&amp;p:CRM_SeasonId=" + seasonId);    }}]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;The method for the form OnLoad is 'Form_onload'&lt;br /&gt;The method for the field Onchange is 'loadChart'&lt;br /&gt;&lt;br /&gt;Hope this helps,&lt;br /&gt;Andreas&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2187748539439547090-8614963309627269350?l=andreaswijayablog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andreaswijayablog.blogspot.com/feeds/8614963309627269350/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://andreaswijayablog.blogspot.com/2011/08/crm-2011-embed-report-in-iframe-and.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/8614963309627269350'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/8614963309627269350'/><link rel='alternate' type='text/html' href='http://andreaswijayablog.blogspot.com/2011/08/crm-2011-embed-report-in-iframe-and.html' title='CRM 2011 Embed Report in IFrame and Pass Parameters from the Form'/><author><name>Andreas</name><uri>http://www.blogger.com/profile/07294319219169612936</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='23' src='http://2.bp.blogspot.com/_kEwj71YPhb8/TJiDclVlgOI/AAAAAAAAAEY/1Th4NMsgW_Q/S220/Andreas2.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-HqRc3MKwv6U/TkCTlTjPd6I/AAAAAAAAAII/aEW1RLvHEN8/s72-c/EngPlan.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2187748539439547090.post-1772631958873255617</id><published>2011-08-09T09:39:00.003+08:00</published><updated>2011-08-09T09:43:53.142+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Dynamics CRM 2011'/><title type='text'>CRM 2011 Report Error - rsProcessingAborted</title><content type='html'>I encountered this error in my project when trying to run CRM reports within CRM (including the default reports). In the reportservice logs it says:&lt;br /&gt;&lt;br /&gt;Cannot create a connection to data source 'CRM'. ---&amp;gt; &lt;em&gt;Microsoft.Crm.Reporting.DataExtensionShim.Common.ReportExecutionException: Immediate caller Domain\SqlService has insufficient privilege to run report as user S-1-5-21-1162093662-620106126-315576832-39399.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;The CRM is installed on the application server and the SSRS is installed on different server. After futher investigation it turns out that it's caused by double hopping issue regarding the authentication and&amp;nbsp;we just need to set the correct SPN on the machines.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;setspn -a http/your-crm-server-name domain\crm-user&amp;nbsp;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;setspn -a http/your-crm-server-name(FQDN) domain\crm-user&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Other things to check to make sure your reports work:&lt;br /&gt;1. Make sure your SRS connector has the same RollUp&amp;nbsp;version as the CRM Server RollUp&lt;br /&gt;2. In Reporting Service Configuration Manager, uncheck the 'Specify an Execution Account' &lt;br /&gt;3.&amp;nbsp;Browse to both&amp;nbsp;SharedReports\5.0.xxxx\ and &lt;org&gt;_MSCRM&amp;nbsp;report folder and&amp;nbsp;check the MSCRM_DataSource connection.&amp;nbsp;The connection string should be empty, &amp;nbsp;DataSource Type should be Microsoft Dynamics CRM SQL, and the connection should be Credentials supplied by the user running the  report (uncheck the Windows Credentials box)&lt;/org&gt;&lt;br /&gt;&lt;br /&gt;---&lt;br /&gt;To run the report from the report server Url, you might find that if you are using normal domain account for username/password you will get the following error:&lt;br /&gt;&lt;br /&gt;&lt;em&gt;An error has occurred during report processing  (rsProcessingAborted)  Cannot create a connection to data source  ‘CRM.’ (rsErrorOpeningConnection)  Guid should contain 32 digits  with 4 dashes (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx).&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;This is because the Username should be 'systemuserid' and the Password should be 'organizationid'. You can get this by running the query against the CRM database:&lt;br /&gt;&lt;br /&gt;&lt;span style="color: blue; font-size: x-small;"&gt;&lt;span style="color: blue; font-size: x-small;"&gt;&lt;span style="font-size: small;"&gt;SELECT &lt;span style="color: black;"&gt;fullname, systemuserid, organizationid&lt;/span&gt; FROM&lt;span style="color: black;"&gt; FilteredSystemUser&lt;/span&gt;&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: blue; font-size: x-small;"&gt;&lt;span style="color: blue; font-size: x-small;"&gt;&lt;br /&gt;&lt;span style="color: black; font-size: small;"&gt;Hope this helps,&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black; font-size: small;"&gt;Andreas&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-small;"&gt;&lt;/span&gt;&lt;span style="color: blue; font-size: x-small;"&gt;&lt;span style="color: blue; font-size: x-small;"&gt;&lt;br /&gt;&lt;span style="font-size: x-small;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: x-small;"&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2187748539439547090-1772631958873255617?l=andreaswijayablog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andreaswijayablog.blogspot.com/feeds/1772631958873255617/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://andreaswijayablog.blogspot.com/2011/08/crm-2011-report-error.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/1772631958873255617'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/1772631958873255617'/><link rel='alternate' type='text/html' href='http://andreaswijayablog.blogspot.com/2011/08/crm-2011-report-error.html' title='CRM 2011 Report Error - rsProcessingAborted'/><author><name>Andreas</name><uri>http://www.blogger.com/profile/07294319219169612936</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='23' src='http://2.bp.blogspot.com/_kEwj71YPhb8/TJiDclVlgOI/AAAAAAAAAEY/1Th4NMsgW_Q/S220/Andreas2.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2187748539439547090.post-3249459446053513351</id><published>2011-08-03T14:49:00.001+08:00</published><updated>2011-08-03T14:50:51.715+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Dynamics CRM 2011'/><title type='text'>CRM 2011 Plugin Template</title><content type='html'>Here is the template to get you started on plugin development in CRM 2011:&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: csharp" type="syntaxhighlighter"&gt;&lt;![CDATA[using System;using System.Collections.Generic;using System.Linq;using System.Text;using Microsoft.Xrm.Sdk;using Microsoft.Xrm.Sdk.Messages;using System.ServiceModel;using Org.Entities.Crm; //this is the generated entities.cs for early boundnamespace My.Plugins{    //insert plugin comment     public class AccountPlugin: IPlugin    {        ITracingService tracingService = null;        public void Execute(IServiceProvider serviceProvider)        {            // Extract the tracing service.            tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));            if (tracingService == null)                throw new InvalidPluginExecutionException("Failed to retrieve the tracing service.");            // Obtain the execution context from the service provider.            IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));            // The InputParameters collection contains all the data passed in the message request.            if (context.InputParameters.Contains("Target") &amp;&amp; context.InputParameters["Target"] is Entity)            {                // Obtain the target entity from the input parameters.                Entity entity = (Entity)context.InputParameters["Target"];                // Get a reference to the Organization service.                IOrganizationServiceFactory factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));                IOrganizationService service = factory.CreateOrganizationService(context.UserId);                try                {                    // Plug-in business logic goes below this line.                    // Invoke organization service methods..                    // do whatever you have to do..                   }                catch (InvalidPluginExecutionException iex)                {                    tracingService.Trace(iex.Message);                    tracingService.Trace(iex.StackTrace);                    throw iex;                }                catch (FaultException&lt;organizationservicefault&gt; ex)                {                    tracingService.Trace(ex.Message);                    tracingService.Trace(ex.StackTrace);                    throw new InvalidPluginExecutionException(string.Format("An error occurred in the {0} plug-in.", this.GetType().Name), ex);                }                catch (Exception e)                {                    tracingService.Trace(e.Message);                    tracingService.Trace(e.StackTrace);                    throw new InvalidPluginExecutionException(string.Format("An error occurred in the {0} plug-in.", this.GetType().Name), e);                }            }        }    }}]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;To get the service context of your organisation :&lt;br /&gt;&lt;script class="brush: csharp" type="syntaxhighlighter"&gt;&lt;![CDATA[OrgServiceContext serviceContext = new OrgServiceContext(service);]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;span style="font-size: large;"&gt;Important Notes:&lt;/span&gt;&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;PRE PLUGINS&lt;/u&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;You don't need to call SaveChanges because the entity can be updated before it is saved into database.&lt;/li&gt;&lt;li&gt;For pre-update, entity will only have attributes that are changed. To get the other attributes that don't change, you can query those attributes using the service context.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;u&gt;POST PLUGINS&lt;/u&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;You don't need to call SaveChanges because the entity can be updated before it is saved into database.&lt;/li&gt;&lt;li&gt;For pre-update, entity will only have attributes that are changed. To get the other attributes that don't change, you can query those attributes using the service context.&lt;/li&gt;&lt;li&gt;When doing the post update of an entity that update the same entity attributes, loop will occur. To avoid this you can use context.Depth to check the loop count.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;u&gt;OTHERS&lt;/u&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;For delete message, the context.InputParameters["Target"] is an EntityReference instead of Entity.&lt;/li&gt;&lt;li&gt;You can check the context message using context.MessageName &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Hope this helps,&lt;br /&gt;Andreas&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2187748539439547090-3249459446053513351?l=andreaswijayablog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andreaswijayablog.blogspot.com/feeds/3249459446053513351/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://andreaswijayablog.blogspot.com/2011/08/crm-2011-plugin-template.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/3249459446053513351'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/3249459446053513351'/><link rel='alternate' type='text/html' href='http://andreaswijayablog.blogspot.com/2011/08/crm-2011-plugin-template.html' title='CRM 2011 Plugin Template'/><author><name>Andreas</name><uri>http://www.blogger.com/profile/07294319219169612936</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='23' src='http://2.bp.blogspot.com/_kEwj71YPhb8/TJiDclVlgOI/AAAAAAAAAEY/1Th4NMsgW_Q/S220/Andreas2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2187748539439547090.post-5651934536534025757</id><published>2011-07-28T21:34:00.005+08:00</published><updated>2011-07-28T21:41:37.734+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Dynamics CRM 2011'/><title type='text'>CRM 2011 Custom Button on Custom Entity to trigger Workflow through JavaScript</title><content type='html'>I will provide detailed step on what I did to do this. The objective of my example is to have a custom button 'Create Opportunity' on my custom entity that triggers a workflow to create an Opportunity. This way the users don't have to click 'Run Workflow' and choose which workflow they want to run. You can also alter the JavaScript to do other stuff as well.&lt;br /&gt;&lt;br /&gt;There are three places where we should put the button mainly:&lt;br /&gt;1. Custom Entity Form&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-ryXyHzpNNZQ/TjFm7TeKwOI/AAAAAAAAAHs/U8gheNxG0RQ/s1600/Form.jpg" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="256" width="320" src="http://3.bp.blogspot.com/-ryXyHzpNNZQ/TjFm7TeKwOI/AAAAAAAAAHs/U8gheNxG0RQ/s320/Form.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;2. Homepage Grid&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-kFSjE4kFTM4/TjFm03fW88I/AAAAAAAAAHk/TZPHkVuhye8/s1600/HomeGrid.jpg" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="256" width="320" src="http://1.bp.blogspot.com/-kFSjE4kFTM4/TjFm03fW88I/AAAAAAAAAHk/TZPHkVuhye8/s320/HomeGrid.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;3. Sub Grid&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-sU4AlHJOvt0/TjFnB23_uXI/AAAAAAAAAH0/BjhSaVXIY_0/s1600/SubGrid.jpg" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="256" width="320" src="http://2.bp.blogspot.com/-sU4AlHJOvt0/TjFnB23_uXI/AAAAAAAAAH0/BjhSaVXIY_0/s320/SubGrid.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;b&gt; THE STEPS:&lt;/b&gt;&lt;br /&gt;1. In order to inspect the correct sequence number of where the button will be placed on each section, you can first run the tool provided from the sdk &lt;b&gt;\sdk\samplecode\cs\client\ribbon\exportribbonxml&lt;/b&gt;. Just modify the&lt;i&gt; exportribbonxml.cs&lt;/i&gt; to only generate the entity you are interested in:&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: csharp" type="syntaxhighlighter"&gt;&lt;![CDATA[public System.String[] entitiesWithRibbons = { "new_productiongrowerforecast" };]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Run the tool program, specify your server connection and it should give you the XML in the output folder with the name &lt;i&gt;&lt;entity&gt;Ribbon.xml&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;Open the xml, search for the sections and write down the sequence numbers of where you want to put them in. In this case I want to put it after 'Start Dialog' button:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: xml" type="syntaxhighlighter"&gt;&lt;![CDATA[&lt;button Id="Mscrm.Form.new_productiongrowerforecast.RunScript" ToolTipTitle="$Resources:Ribbon.HomepageGrid.Data.InteractiveWorkflow.RunScript" ToolTipDescription="$Resources(EntityDisplayName):Ribbon.Tooltip.RunScript" Command="Mscrm.RunInteractiveWorkflowPrimary" Sequence="25" LabelText="$Resources:Ribbon.HomepageGrid.Data.InteractiveWorkflow.RunScript" Alt="$Resources:Ribbon.HomepageGrid.Data.InteractiveWorkflow.RunScript" Image16by16="/_imgs/ribbon/startdialog_16.png" Image32by32="/_imgs/ribbon/startdialog_32.png" TemplateAlias="o1" /&gt;&lt;button Id="Mscrm.HomepageGrid.new_productiongrowerforecast.RunScript" ToolTipTitle="$Resources:Ribbon.HomepageGrid.Data.InteractiveWorkflow.RunScript" ToolTipDescription="$Resources(EntityDisplayName):Ribbon.Tooltip.RunScript" Command="Mscrm.RunInteractiveWorkflowSelected" Sequence="50" LabelText="$Resources:Ribbon.HomepageGrid.Data.InteractiveWorkflow.RunScript" Alt="$Resources:Ribbon.HomepageGrid.Data.InteractiveWorkflow.RunScript" Image16by16="/_imgs/ribbon/startdialog_16.png" Image32by32="/_imgs/ribbon/startdialog_32.png" TemplateAlias="o1" /&gt;&lt;button Id="Mscrm.SubGrid.new_productiongrowerforecast.RunScript" ToolTipTitle="$Resources:Ribbon.HomepageGrid.Data.InteractiveWorkflow.RunScript" ToolTipDescription="$Resources(EntityDisplayName):Ribbon.Tooltip.RunScript" Command="Mscrm.RunInteractiveWorkflowSelected" Sequence="40" LabelText="$Resources:Ribbon.HomepageGrid.Data.InteractiveWorkflow.RunScript" Alt="$Resources:Ribbon.HomepageGrid.Data.InteractiveWorkflow.RunScript" Image16by16="/_imgs/ribbon/StartDialog_16.png" Image32by32="/_imgs/ribbon/StartDialog_32.png" TemplateAlias="o1" /&gt;]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Sequence is 25, 50, 40&lt;br /&gt;&lt;br /&gt;2. Export your solution with the custom entity you want. Open the customisations.xml and inside the &lt;i&gt;RibbonDiffXml&lt;/i&gt; tag, specify all the contents of the child tags that describe the rules, custom actions, commands, etc. (Look at the SDK for more information). This is the section that I wrote:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: xml" type="syntaxhighlighter"&gt;&lt;![CDATA[      &lt;ribbondiffxml&gt;        &lt;customactions&gt;          &lt;customaction Id="Insight.new_productiongrowerforecast.form.CreateOpportunity.CustomAction" Location="Mscrm.Form.new_productiongrowerforecast.MainTab.Workflow.Controls._children" Sequence="26"&gt;            &lt;commanduidefinition&gt;              &lt;button Id="Insight.new_productiongrowerforecast.form.CreateOpportunity.Button" Command="Insight.new_productiongrowerforecast.form.CreateOpportunity.Command" LabelText="$LocLabels:Insight.new_productiongrowerforecast.CreateOpportunity.LabelText" ToolTipTitle="$LocLabels:Insight.new_productiongrowerforecast.CreateOpportunity.LabelText" ToolTipDescription="$LocLabels:Insight.new_productiongrowerforecast.CreateOpportunity.ToolTip" TemplateAlias="o1" Image16by16="/_imgs/ribbon/AddNote_16.png" Image32by32="/_imgs/ribbon/noteyellowadd32.png" /&gt;            &lt;/CommandUIDefinition&gt;          &lt;/CustomAction&gt;          &lt;customaction Id="Insight.new_productiongrowerforecast.grid.CreateOpportunity.CustomAction" Location="Mscrm.HomepageGrid.new_productiongrowerforecast.MainTab.Workflow.Controls._children" Sequence="51"&gt;            &lt;commanduidefinition&gt;              &lt;button Id="Insight.new_productiongrowerforecast.grid.CreateOpportunity.Button" Command="Insight.new_productiongrowerforecast.grid.CreateOpportunity.Command" LabelText="$LocLabels:Insight.new_productiongrowerforecast.CreateOpportunity.LabelText" ToolTipTitle="$LocLabels:Insight.new_productiongrowerforecast.CreateOpportunity.LabelText" ToolTipDescription="$LocLabels:Insight.new_productiongrowerforecast.CreateOpportunity.ToolTip" TemplateAlias="o1" Image16by16="/_imgs/ribbon/AddNote_16.png" Image32by32="/_imgs/ribbon/noteyellowadd32.png" /&gt;            &lt;/CommandUIDefinition&gt;          &lt;/CustomAction&gt;          &lt;customaction Id="Insight.new_productiongrowerforecast.subgrid.CreateOpportunity.CustomAction" Location="Mscrm.SubGrid.new_productiongrowerforecast.MainTab.Workflow.Controls._children" Sequence="51"&gt;            &lt;commanduidefinition&gt;              &lt;button Id="Insight.new_productiongrowerforecast.subgrid.CreateOpportunity.Button" Command="Insight.new_productiongrowerforecast.grid.CreateOpportunity.Command" LabelText="$LocLabels:Insight.new_productiongrowerforecast.CreateOpportunity.LabelText" ToolTipTitle="$LocLabels:Insight.new_productiongrowerforecast.CreateOpportunity.LabelText" ToolTipDescription="$LocLabels:Insight.new_productiongrowerforecast.CreateOpportunity.ToolTip" TemplateAlias="o1" Image16by16="/_imgs/ribbon/AddNote_16.png" Image32by32="/_imgs/ribbon/noteyellowadd32.png" /&gt;            &lt;/CommandUIDefinition&gt;          &lt;/CustomAction&gt;        &lt;/CustomActions&gt;        &lt;templates&gt;          &lt;ribbontemplates Id="Mscrm.Templates"&gt;&lt;/RibbonTemplates&gt;        &lt;/Templates&gt;        &lt;commanddefinitions&gt;          &lt;commanddefinition Id="Insight.new_productiongrowerforecast.form.CreateOpportunity.Command"&gt;            &lt;enablerules&gt;              &lt;enablerule Id="Insight.new_productiongrowerforecast.WebClient.EnableRule" /&gt;              &lt;enablerule Id="Insight.new_productiongrowerforecast.form.NotNew.EnableRule" /&gt;            &lt;/EnableRules&gt;            &lt;displayrules&gt;              &lt;displayrule Id="Insight.new_productiongrowerforecast.form.FormStateNotNew.DisplayRule" /&gt;              &lt;displayrule Id="Insight.new_productiongrowerforecast.WebClient.DisplayRule" /&gt;            &lt;/DisplayRules&gt;            &lt;actions&gt;              &lt;javascriptfunction Library="$webresource:new_ForecastCreateOpportunity.js" FunctionName="CreateOpportunity"&gt;                &lt;crmparameter Value="SelectedControlSelectedItemReferences" /&gt;              &lt;/JavaScriptFunction&gt;            &lt;/Actions&gt;          &lt;/CommandDefinition&gt;          &lt;commanddefinition Id="Insight.new_productiongrowerforecast.grid.CreateOpportunity.Command"&gt;            &lt;enablerules&gt;              &lt;enablerule Id="Insight.new_productiongrowerforecast.WebClient.EnableRule" /&gt;              &lt;enablerule Id="Insight.new_productiongrowerforecast.grid.OneSelected.EnableRule" /&gt;            &lt;/EnableRules&gt;            &lt;displayrules&gt;              &lt;displayrule Id="Insight.new_productiongrowerforecast.WebClient.DisplayRule" /&gt;            &lt;/DisplayRules&gt;            &lt;actions&gt;              &lt;javascriptfunction Library="$webresource:new_ForecastCreateOpportunity.js" FunctionName="CreateOpportunity"&gt;                &lt;crmparameter Value="SelectedControlSelectedItemReferences" /&gt;              &lt;/JavaScriptFunction&gt;            &lt;/Actions&gt;          &lt;/CommandDefinition&gt;        &lt;/CommandDefinitions&gt;        &lt;ruledefinitions&gt;          &lt;tabdisplayrules /&gt;          &lt;displayrules&gt;            &lt;displayrule Id="Insight.new_productiongrowerforecast.form.FormStateNotNew.DisplayRule"&gt;              &lt;formstaterule State="Create" InvertResult="true" /&gt;            &lt;/DisplayRule&gt;            &lt;displayrule Id="Insight.new_productiongrowerforecast.WebClient.DisplayRule"&gt;              &lt;crmclienttyperule Type="Web" /&gt;            &lt;/DisplayRule&gt;          &lt;/DisplayRules&gt;          &lt;enablerules&gt;            &lt;enablerule Id="Insight.new_productiongrowerforecast.grid.OneSelected.EnableRule"&gt;              &lt;selectioncountrule AppliesTo="SelectedEntity" Minimum="1" /&gt;            &lt;/EnableRule&gt;            &lt;enablerule Id="Insight.new_productiongrowerforecast.WebClient.EnableRule"&gt;              &lt;crmclienttyperule Type="Web" /&gt;            &lt;/EnableRule&gt;            &lt;enablerule Id="Insight.new_productiongrowerforecast.form.NotNew.EnableRule"&gt;              &lt;formstaterule State="Create" InvertResult="true" /&gt;            &lt;/EnableRule&gt;          &lt;/EnableRules&gt;        &lt;/RuleDefinitions&gt;        &lt;loclabels&gt;          &lt;loclabel Id="Insight.new_productiongrowerforecast.CreateOpportunity.ToolTip"&gt;            &lt;titles&gt;              &lt;title languagecode="1033" description="Create Opportunity" /&gt;            &lt;/Titles&gt;          &lt;/LocLabel&gt;          &lt;loclabel Id="Insight.new_productiongrowerforecast.CreateOpportunity.LabelText"&gt;            &lt;titles&gt;              &lt;title languagecode="1033" description="Create Opportunity" /&gt;            &lt;/Titles&gt;          &lt;/LocLabel&gt;        &lt;/LocLabels&gt;      &lt;/RibbonDiffXml&gt;]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;3. For the JavaScript that triggers the workflow, there is a post that describes how to do that &lt;a href="http://dynamiccrm.blogspot.com/2011/02/from-ribbon-button-calling-on-demand.html"&gt;here &lt;/a&gt;and I just make use of that. The CRM Parameter passed from the above is iterated and the workflow is triggered for each of the selection.&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: js" type="syntaxhighlighter"&gt;&lt;![CDATA[function CreateOpportunity(SelectedControlSelectedItemReferences) {    var allItems = new Array    var allItems = SelectedControlSelectedItemReferences    var iTotal = allItems.length;    if (iTotal &gt; 0) {        for (var i = 0; i &lt; iTotal; i++) {            //    alert(allItems[i].Id)            callworkfow(allItems[i].Id);        }        alert("Success");    }    else        alert("Please select any record to perform required action");}function callworkfow(id) {    try {        var guid;        if (id == null) {            guid = Xrm.Page.data.entity.getId();        }        else            guid = id;        // assign workflow guid        var WorkflowId = "89BA3166-948E-4B12-8A55-4BE01DEDAB0B";        var xml = "" +    "&lt;?xml version=\"1.0\" encoding=\"utf-8\"?&gt;" +    "&lt;soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"&gt;" +    Xrm.Page.context.getAuthenticationHeader() +    "&lt;soap:Body&gt;" +    "&lt;execute xmlns=\"http://schemas.microsoft.com/crm/2007/WebServices\"&gt;" +    "&lt;request xsi:type=\"ExecuteWorkflowRequest\"&gt;" +    "&lt;entityid&gt;" + guid + "&lt;/EntityId&gt;" +    "&lt;workflowid&gt;" + WorkflowId + "&lt;/WorkflowId&gt;" + //WorkflowId = guid of the workflow    "&lt;/Request&gt;" +    "&lt;/Execute&gt;" +    "&lt;/soap:Body&gt;" +    "&lt;/soap:Envelope&gt;";        var xmlHttpRequest = new ActiveXObject("Msxml2.XMLHTTP");        xmlHttpRequest.Open("POST", "/mscrmservices/2007/CrmService.asmx", false);        xmlHttpRequest.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/crm/2007/WebServices/Execute");        xmlHttpRequest.setRequestHeader("Content-Type", "text/xml; charset=utf-8");        xmlHttpRequest.setRequestHeader("Content-Length", xml.length);        xmlHttpRequest.send(xml);        var resultXml = xmlHttpRequest.responseXML;        if (id == null)            alert("Success");        return (resultXml.xml);    }    catch (e) {        alert("Failed to Execute");    }} ]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Hope this helps :)&lt;br /&gt;&lt;br /&gt;Andreas&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2187748539439547090-5651934536534025757?l=andreaswijayablog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andreaswijayablog.blogspot.com/feeds/5651934536534025757/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://andreaswijayablog.blogspot.com/2011/07/crm-2011-custom-button-on-custom-entity.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/5651934536534025757'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/5651934536534025757'/><link rel='alternate' type='text/html' href='http://andreaswijayablog.blogspot.com/2011/07/crm-2011-custom-button-on-custom-entity.html' title='CRM 2011 Custom Button on Custom Entity to trigger Workflow through JavaScript'/><author><name>Andreas</name><uri>http://www.blogger.com/profile/07294319219169612936</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='23' src='http://2.bp.blogspot.com/_kEwj71YPhb8/TJiDclVlgOI/AAAAAAAAAEY/1Th4NMsgW_Q/S220/Andreas2.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-ryXyHzpNNZQ/TjFm7TeKwOI/AAAAAAAAAHs/U8gheNxG0RQ/s72-c/Form.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2187748539439547090.post-2496319725424363549</id><published>2011-07-21T16:18:00.003+08:00</published><updated>2012-01-05T11:09:24.343+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Dynamics CRM 2011'/><title type='text'>CRM 2011 Javascript Functions</title><content type='html'>Starting to use CRM 2011, here are some useful javascript reference (this list will get longer and longer as time goes):&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Hide/Show Field&lt;/b&gt;&lt;br /&gt;&lt;script class="brush: js" type="syntaxhighlighter"&gt;&lt;![CDATA[function HideShowField(fieldName, show) {    var field = Xrm.Page.ui.controls.get(fieldName);    if (field != null)        field.setVisible(show);}]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Hide/Show Field but removing white space&lt;/b&gt;&lt;br /&gt;&lt;script class="brush: js" type="syntaxhighlighter"&gt;&lt;![CDATA[function HideShowFieldRemoveSpace(fieldname, show) {    var displayStyle = show ? 'block' : 'none';    if (document.getElementById(fieldname + '_c') != null &amp;&amp; document.getElementById(fieldname + '_d') != null) {        document.getElementById(fieldname + '_c').style.display = displayStyle;        document.getElementById(fieldname + '_d').style.display = displayStyle;    }}]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Disable/Not Disable Field&lt;/b&gt;&lt;br /&gt;&lt;script class="brush: js" type="syntaxhighlighter"&gt;&lt;![CDATA[function SetDisableField(fieldName, disabled) {    var field = Xrm.Page.getControl(fieldName);    if (field != null)        field.setDisabled(disabled);}]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Set Requirement Level&lt;/b&gt;&lt;br /&gt;&lt;script class="brush: js" type="syntaxhighlighter"&gt;&lt;![CDATA[function SetRequirementLevel(fieldName, reqLevel) {    var field = Xrm.Page.getAttribute(fieldName);    if (field != null)        field.setRequiredLevel(reqLevel);}]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Set Required Level&lt;/b&gt;&lt;br /&gt;&lt;script class="brush: js" type="syntaxhighlighter"&gt;&lt;![CDATA[function SetRequirementLevel(fieldName, reqLevel) {    var field = Xrm.Page.getAttribute(fieldName);    if (field != null)        field.setRequiredLevel(reqLevel);}]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Validate Number Field and Character Limit&lt;/b&gt;&lt;br /&gt;&lt;script class="brush: js" type="syntaxhighlighter"&gt;&lt;![CDATA[function validateNumberField(context, limit) {    var value = context.getEventSource().getValue();    var fieldName = context.getEventSource().getName();    var labelName = Xrm.Page.ui.controls.get(fieldName).getLabel();    var valueRegex = new RegExp("^\\d{" + limit + "}$");    if (!value.match(valueRegex)) {        event.returnValue = false;        alert("The format of the " + labelName + " is incorrect");    }}]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Validate Future DateTime&lt;/b&gt;&lt;br /&gt;&lt;script class="brush: js" type="syntaxhighlighter"&gt;&lt;![CDATA[function ValidateFutureDate(fieldname) {    var today = new Date();    var dueDate = Xrm.Page.getAttribute(fieldname).getValue();    if (dueDate != null &amp;&amp; dueDate &lt; today) {        alert("Date value needs to be in the future");        Xrm.Page.getAttribute(fieldname).setValue(today);    }}]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Example function to hide left navigation item based on a condition&lt;/b&gt;&lt;br /&gt;&lt;script class="brush: js" type="syntaxhighlighter"&gt;&lt;![CDATA[function ShowBankDetails() {    var payeeRole = "new_rolepayee";    var payeeChkBox = Xrm.Page.ui.controls.get(payeeRole);    var payeeChkBoxValue = payeeChkBox.getAttribute().getValue();    if (payeeChkBoxValue == true) {        Xrm.Page.ui.navigation.items.get("nav_new_account_new_bankdetail").setVisible(true);    }    else {        Xrm.Page.ui.navigation.items.get("nav_new_account_new_bankdetail").setVisible(false);    }}]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Avoiding the checkbox OnChange bug so that it fires off immediately (put this in OnLoad event of the form)&lt;/b&gt;&lt;br /&gt;&lt;script class="brush: js" type="syntaxhighlighter"&gt;&lt;![CDATA[function TriggerCheckBoxClick() {    crmForm.all.new_checkbox.onclick = function () { crmForm.all.new_checkbox.FireOnChange(); };    }]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Set Lookup Value&lt;/b&gt;&lt;br /&gt;&lt;script class="brush: js" type="syntaxhighlighter"&gt;&lt;![CDATA[function SetLookupValue(fieldName, id, name, entityType) {    if (fieldName != null) {        var lookupValue = new Array();        lookupValue[0] = new Object();        lookupValue[0].id = id;        lookupValue[0].name = name;        lookupValue[0].entityType = entityType;        Xrm.Page.getAttribute(fieldName).setValue(lookupValue);    }} &lt;/script&gt;&lt;b&gt;Hide Picklist Item Text&lt;/b&gt;&lt;script class="brush: js" type="syntaxhighlighter"&gt;&lt;![CDATA[function HidePicklistItemWithText(fieldName, withText) {    var picklist = document.getElementById(fieldName);    for (var i = picklist.options.length - 1; i &gt;= 0; i--) {        var picklistItemText = picklist.options[i].text;        if (picklistItemText.match(withText) == withText &amp;&amp; picklist.selectedIndex != i) {            picklist.options.remove(i);        }    }}]]&gt;&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2187748539439547090-2496319725424363549?l=andreaswijayablog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andreaswijayablog.blogspot.com/feeds/2496319725424363549/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://andreaswijayablog.blogspot.com/2011/07/crm-2011-javascript-functions.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/2496319725424363549'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/2496319725424363549'/><link rel='alternate' type='text/html' href='http://andreaswijayablog.blogspot.com/2011/07/crm-2011-javascript-functions.html' title='CRM 2011 Javascript Functions'/><author><name>Andreas</name><uri>http://www.blogger.com/profile/07294319219169612936</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='23' src='http://2.bp.blogspot.com/_kEwj71YPhb8/TJiDclVlgOI/AAAAAAAAAEY/1Th4NMsgW_Q/S220/Andreas2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2187748539439547090.post-7431807674807412412</id><published>2011-05-24T22:49:00.001+08:00</published><updated>2011-05-24T22:49:44.034+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='my piano songs'/><title type='text'>Piano Song Composition (Song Of Life &amp; Smile)</title><content type='html'>Just check my YouTube channel for more information :) Hope you enjoy them.&lt;br /&gt;&lt;br /&gt;&lt;iframe width="560" height="349" src="http://www.youtube.com/embed/4aR7ePPu3Pk" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;br /&gt;&lt;br /&gt;&lt;iframe width="560" height="349" src="http://www.youtube.com/embed/dhYiL1JHJds" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;br /&gt;&lt;br /&gt;Andreas&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2187748539439547090-7431807674807412412?l=andreaswijayablog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andreaswijayablog.blogspot.com/feeds/7431807674807412412/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://andreaswijayablog.blogspot.com/2011/05/piano-song-composition-song-of-life.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/7431807674807412412'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/7431807674807412412'/><link rel='alternate' type='text/html' href='http://andreaswijayablog.blogspot.com/2011/05/piano-song-composition-song-of-life.html' title='Piano Song Composition (Song Of Life &amp; Smile)'/><author><name>Andreas</name><uri>http://www.blogger.com/profile/07294319219169612936</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='23' src='http://2.bp.blogspot.com/_kEwj71YPhb8/TJiDclVlgOI/AAAAAAAAAEY/1Th4NMsgW_Q/S220/Andreas2.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://img.youtube.com/vi/4aR7ePPu3Pk/default.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2187748539439547090.post-8173841878400405940</id><published>2011-04-19T11:30:00.001+08:00</published><updated>2011-04-19T17:41:34.433+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SSRS'/><title type='text'>SSRS Repeat Subreport with MultiValue parameter</title><content type='html'>When you want to print a report with a given ID for example, you would just pass that single ID into a report parameter and there you go. Simple.&lt;br /&gt;&lt;br /&gt;How about if let's say, the user wants to be able to do multiple selection of records from the UI (e.g. select multiple records in a grid) and click Print button to generate the report for each ID in one single report? It's not that hard either.&lt;br /&gt;&lt;br /&gt;For this example I have a Service Sheet report that takes assetID and display maintenance details for that asset. Then I went ahead and created another report, put a listbox and added that report as a subreport.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-cE8CsiIxAaA/Taz_sw0JrOI/AAAAAAAAAFM/pJwuYs9_VH8/s1600/subreport.jpg" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="82" width="320" src="http://3.bp.blogspot.com/-cE8CsiIxAaA/Taz_sw0JrOI/AAAAAAAAAFM/pJwuYs9_VH8/s320/subreport.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;I used list instead of table because SSRS2005 has a bug when exporting the report to excel.&lt;br /&gt;&lt;br /&gt;The next thing to do is to create the multi-value string parameter. This parameter will take comma separated values for the IDs.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-t2c5FuDIjps/Ta0AVXEbIQI/AAAAAAAAAFU/cJtnbnK54sU/s1600/multivalue.jpg" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="235" width="320" src="http://4.bp.blogspot.com/-t2c5FuDIjps/Ta0AVXEbIQI/AAAAAAAAAFU/cJtnbnK54sU/s320/multivalue.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;We need to set the dataset for the ListBox. I used a stored procedure for this one. The stored procedure will get that parameter and break each ID into its own row.&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: sql" type="syntaxhighlighter"&gt;&lt;![CDATA[ALTER PROCEDURE [dbo].[spReportServiceSheetGroup] @MaintenanceRequestId VARCHAR(1000)ASBEGIN   DECLARE @tempTbl TABLE (maintenanceRequestId int NOT NULL)   DECLARE @pos        int,           @nextpos    int,           @valuelen   int    SELECT @pos = 0, @nextpos = 1    WHILE @nextpos &gt; 0   BEGIN      SELECT @nextpos = charindex(',', @MaintenanceRequestId, @pos + 1)      SELECT @valuelen = CASE WHEN @nextpos &gt; 0                              THEN @nextpos                              ELSE len(@MaintenanceRequestId) + 1                         END - @pos - 1      INSERT @tempTbl(maintenanceRequestId)         VALUES (convert(int, substring(@MaintenanceRequestId, @pos + 1, @valuelen)))      SELECT @pos = @nextpos   END   select * from @tempTblEND]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;That's it. All you need to do is then set the dataset for the listbox. In the grouping field, set the field returned by the SP (in this case maintenanceRequestId). Also check 'Page break at end' so each ID report will start on the new page.&lt;br /&gt;&lt;br /&gt;Enjoy,&lt;br /&gt;Andreas&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2187748539439547090-8173841878400405940?l=andreaswijayablog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andreaswijayablog.blogspot.com/feeds/8173841878400405940/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://andreaswijayablog.blogspot.com/2011/04/ssrs-repeat-subreport-with-multivalue.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/8173841878400405940'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/8173841878400405940'/><link rel='alternate' type='text/html' href='http://andreaswijayablog.blogspot.com/2011/04/ssrs-repeat-subreport-with-multivalue.html' title='SSRS Repeat Subreport with MultiValue parameter'/><author><name>Andreas</name><uri>http://www.blogger.com/profile/07294319219169612936</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='23' src='http://2.bp.blogspot.com/_kEwj71YPhb8/TJiDclVlgOI/AAAAAAAAAEY/1Th4NMsgW_Q/S220/Andreas2.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-cE8CsiIxAaA/Taz_sw0JrOI/AAAAAAAAAFM/pJwuYs9_VH8/s72-c/subreport.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2187748539439547090.post-1567563183301206395</id><published>2011-03-02T21:37:00.001+08:00</published><updated>2011-03-02T21:41:10.828+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Dynamics CRM 4.0'/><title type='text'>CRM Javascript</title><content type='html'>&lt;u&gt;&lt;b&gt;Simple field validation using RegEx (e.g. ABN):&lt;/b&gt;&lt;/u&gt;&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: js" type="syntaxhighlighter"&gt;&lt;![CDATA[var abn = crmForm.all.new_abn;var abnRegEx = /^\d{11}$/;// Verify that the shortname field exists and is not null. if (abn != null &amp;&amp; abnRegEx.test(abn.DataValue) != true){    alert('ABN must be 11 digits characters length');    abn.DataValue = '';}]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;&lt;b&gt;Hiding fields:&lt;/b&gt;&lt;/u&gt;&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: js" type="syntaxhighlighter"&gt;&lt;![CDATA[crmForm.all.new_invoicenumber_d.style.display = 'none';crmForm.all.new_invoicenumber_c.style.display = 'none';]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;&lt;b&gt;Hiding tabs:&lt;/b&gt;&lt;/u&gt;&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: js" type="syntaxhighlighter"&gt;&lt;![CDATA[crmForm.all.tab1Tab.style.display = "inline";crmForm.all.tab2Tab.style.display = "none";]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;&lt;b&gt;Disabling fields within a section:&lt;/b&gt;&lt;/u&gt;&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: js" type="syntaxhighlighter"&gt;&lt;![CDATA[//enable fields if Enquiry Group is not null, disable otherwisevar section = crmForm.all.new_quotenumber_c.parentElement.parentElement.parentElement;for (i = 0; i &lt; section.all.length; i++) {    if (crmForm.all.new_enquirygroup.DataValue == null) {        section.all[i].Disabled = true;    }    else {        section.all[i].Disabled = false;    }}]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;br /&gt;&lt;u&gt;Get Potential Customer's Primary Contact and set it to Customer Contact field:&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: js" type="syntaxhighlighter"&gt;&lt;![CDATA[var primaryContactID = '';var primaryContactName = '';get_primarycontact();//Get shortname out of Potential Customer  function get_primarycontact() {    if (crmForm.all.customerid.DataValue != null) {        //Prepare variables for an enquiry to retrieve.        var lookupItem = new Array;        // Get the lookup attribute on the quality assurance checklist form.        lookupItem = crmForm.all.customerid.DataValue;        var potentialCustomer = lookupItem[0].id;        var authenticationHeader = GenerateAuthenticationHeader();        //Prepare the SOAP message.        var xml = "&lt;?xml version='1.0' encoding='utf-8'?&gt;" +                  "&lt;soap:Envelope xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'" +                  " xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'" +                  " xmlns:xsd='http://www.w3.org/2001/XMLSchema'&gt;" +                  authenticationHeader +                  "&lt;soap:Body&gt;" +                  "&lt;retrieve xmlns='http://schemas.microsoft.com/crm/2007/WebServices'&gt;" +                  "&lt;entityname&gt;account&lt;/entityName&gt;" +                  "&lt;id&gt;" + potentialCustomer + "&lt;/id&gt;" +                  "&lt;columnset xmlns:q1='http://schemas.microsoft.com/crm/2006/Query' xsi:type='q1:ColumnSet'&gt;" +                  "&lt;q1:Attributes&gt;" +                  "&lt;q1:Attribute&gt;primarycontactid&lt;/q1:Attribute&gt;" +                  "&lt;/q1:Attributes&gt;" +                  "&lt;/columnSet&gt;" +                  "&lt;/Retrieve&gt;" +                  "&lt;/soap:Body&gt;" +                  "&lt;/soap:Envelope&gt;";        //Prepare the xmlHttpObject and send the request.        var xHReq = new ActiveXObject("Msxml2.XMLHTTP");        xHReq.Open("POST", "/mscrmservices/2007/CrmService.asmx", false);        xHReq.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/crm/2007/WebServices/Retrieve");        xHReq.setRequestHeader("Content-Type", "text/xml; charset=utf-8");        xHReq.setRequestHeader("Content-Length", xml.length);        xHReq.send(xml);        //Capture the result.        var resultXml = xHReq.responseXML;        //Check for errors.        var errorCount = resultXml.selectNodes('//error').length;        if (errorCount != 0) {            var msg = resultXml.selectSingleNode('//description').nodeTypedValue;            alert(msg);        }        //Store the retrieved value.        else {            if (resultXml.selectSingleNode("//q1:primarycontactid") != null) {                primaryContactID = resultXml.selectSingleNode("//q1:primarycontactid").nodeTypedValue;                primaryContactName = resultXml.selectSingleNode("//q1:primarycontactid").getAttribute('name');                //Create an array to set as the DataValue for the lookup control.                var lookupData = new Array();                //Create an Object add to the array.                var lookupItem = new Object();                //Set the id, typename, and name properties to the object.                lookupItem.id = primaryContactID;                lookupItem.typename = 'contact';                lookupItem.name = primaryContactName;                // Add the object to the array.                lookupData[0] = lookupItem;                // Set the value of the lookup field to the value of the array.                crmForm.all.new_customercontact.DataValue = lookupData;            }        }    }}]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Lock Potential Customer to 'Account' Only:&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: js"&gt;&lt;![CDATA[//Javascript Helpervar LOGICAL_OPERATOR_AND = "And";var LOGICAL_OPERATOR_OR = "Or";var CONDITION_OPERATOR_LIKE = "Like";var CONDITION_OPERATOR_EQUAL = "Equal";var CONDITION_OPERATORNOT_EQUAL = "NotEqual";var JOINOPERATOR_INNER = "Inner";var JOINOPERATOR_LEFTOUTER = "LeftOuter";var JOINOPERATOR_NATURAL = "Natural";function CrmService(entityName, logicalOperator) {    // Double check in case you pass a variable that hasn't been set    // This error is hear to track down    if (logicalOperator == null) throw new Error("Must specify non-null value for logicalOperator");    if (entityName == null) throw new Error("Must specify non-null value for entityName");    this.entityName = entityName;    this.ColumnSet = new Array();    this.LogicalOperator = logicalOperator;    this.Conditions = new Array();    this.Orders = new Array();    this.LinkedEntities = new Array();}CrmService.prototype.getEntityName = function () {    return this.entityName;}function Condition(field, value, operator) {    this.Field = field;    // Not null can't have a value    if (operator != "NotNull" &amp;&amp; operator != "Null") this.Value = CrmEncodeDecode.CrmXmlEncode(value);    // Double check in case you pass a variable that hasn't been set    // This error is hear to track down    if (operator == null) throw new Error("Must specify non-null value for operator");    this.Operator = operator;}function Order(attributeName, orderType) {    this.AttributeName = attributeName;    this.OrderType = orderType;}CrmService.prototype.setEntityName = function () {    return this.entityName;}CrmService.prototype.AddColumn = function (columnName) {    this.ColumnSet[this.ColumnSet.length] = columnName;}CrmService.prototype.AddFilterCondition = function (field, value, conditionOperator) {    this.Conditions[this.Conditions.length] = new Condition(field, value, conditionOperator);}CrmService.prototype.AddOrder = function (attributeName, orderType) {    this.Orders[this.Orders.length] = new Order(attributeName, orderType);}/*for (orderNumber in this.Orders) {var order = this.Orders[orderNumber];if (order.OrderType == null)throw new Error("Must specify non-null value for order OrderType");if (order.AttributeName == null)throw new Error("Must specify non-null value for order AttributeName");xmlSoapBody += "&lt;q1:Order&gt;&lt;q1:AttributeName&gt;" + order.AttributeName + "&lt;/q1:AttributeName&gt;";xmlSoapBody += "&lt;q1:OrderType&gt;" + order.OrderType + "&lt;/q1:OrderType&gt;&lt;/q1:Order&gt;";}*/function LinkedEntity(linkFromEntityName, linkToEntityName, linkFromAttributeName, linkToAttributeName, joinOperator) {    this.LinkFromEntityName = linkFromEntityName;    this.LinkToEntityName = linkToEntityName;    this.LinkFromAttributeName = linkFromAttributeName;    this.LinkToAttributeName = linkToAttributeName;    if (joinOperator == null) throw new Error("Must specify non-null value for operator");    this.JoinOperator = joinOperator;    this.Conditions = new Array();    this.FilterOperator = LOGICAL_OPERATOR_AND;}LinkedEntity.prototype.AddFilterCondition = function (field, value, conditionOperator) {    this.Conditions[this.Conditions.length] = new Condition(field, value, conditionOperator);    return this.Conditions[this.Conditions.length - 1];}CrmService.prototype.AddLinkedEntityCondition = function (linkFromEntityName, linkToEntityName, linkFromAttributeName, linkToAttributeName, joinOperator) {    this.LinkedEntities[this.LinkedEntities.length] = new LinkedEntity(linkFromEntityName, linkToEntityName, linkFromAttributeName, linkToAttributeName, joinOperator);    return this.LinkedEntities[this.LinkedEntities.length - 1];}function RetrieveMultipleResult(crmService) {    this.Rows = new Array();    this.CrmService = crmService;}RetrieveMultipleResult.prototype.AddRow = function () {    this.Rows[this.Rows.length] = new Row();    return this.Rows[this.Rows.length - 1];}function Row() {    this.Columns = new Array();}function Column(columnName, value, dataType) {    this.ColumnName = columnName;    this.Value = value;    this.DataType = dataType;}Row.prototype.AddColumn = function (columnName, value) {    this.Columns[this.Columns.length] = new Column(columnName, value);}Row.prototype.GetColumn = function (columnName) {    for (columnNumber in this.Columns) {        var column = this.Columns[columnNumber];        if (columnName.toLowerCase() == column.ColumnName.toLowerCase()) return column;    }    throw new Error("Column " + columnName + " does not exist");}Row.prototype.GetValue = function (columnName) {    var column = this.GetColumn(columnName);    return column.Value;}CrmService.prototype.RetrieveMultiple = function () {    //create SOAP envelope    var xmlSoapHeader = "" + "&lt;?xml version=\"1.0\" encoding=\"utf-8\"?&gt;" + "&lt;soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"&gt;";    var xmlAuthHeader = GenerateAuthenticationHeader();    var xmlSoapBody = "&lt;soap:Body&gt;" + "      &lt;retrievemultiple xmlns=\"http://schemas.microsoft.com/crm/2007/WebServices\"&gt;  " + "&lt;query xmlns:q1=\"http://schemas.microsoft.com/crm/2006/Query\" xsi:type=\"q1:QueryExpression\"&gt;  " + "  &lt;q1:EntityName&gt;" + this.getEntityName() + "&lt;/q1:EntityName&gt;  " + "  &lt;q1:ColumnSet xsi:type=\"q1:ColumnSet\"&gt;  " + "    &lt;q1:Attributes&gt;  ";    for (columnNumber in this.ColumnSet) {        var column = this.ColumnSet[columnNumber];        xmlSoapBody = xmlSoapBody + "          &lt;q1:Attribute&gt;" + column + "&lt;/q1:Attribute&gt;";    }    xmlSoapBody = xmlSoapBody + "        &lt;/q1:Attributes&gt;" + "      &lt;/q1:ColumnSet&gt;" + "          &lt;q1:Distinct&gt;false&lt;/q1:Distinct&gt;  " + "          &lt;q1:PageInfo&gt;  " + "            &lt;q1:PageNumber&gt;0&lt;/q1:PageNumber&gt;  " + "            &lt;q1:Count&gt;0&lt;/q1:Count&gt;  " + "          &lt;/q1:PageInfo&gt;  " + "         &lt;q1:LinkEntities&gt;";    if (this.LinkedEntities.length &gt; 0) {        for (linkedEntityNumber in this.LinkedEntities) {            var linkedEntity = this.LinkedEntities[linkedEntityNumber];            xmlSoapBody += " &lt;q1:LinkEntity&gt; ";            xmlSoapBody += "                 &lt;q1:LinkFromAttributeName&gt;" + linkedEntity.LinkFromAttributeName + "&lt;/q1:LinkFromAttributeName&gt; ";            xmlSoapBody += "                 &lt;q1:LinkFromEntityName&gt;" + linkedEntity.LinkFromEntityName + "&lt;/q1:LinkFromEntityName&gt; ";            xmlSoapBody += "                 &lt;q1:LinkToEntityName&gt;" + linkedEntity.LinkToEntityName + "&lt;/q1:LinkToEntityName&gt; ";            xmlSoapBody += "&lt;q1:LinkToAttributeName&gt;" + linkedEntity.LinkToAttributeName + "&lt;/q1:LinkToAttributeName&gt; ";            xmlSoapBody += "&lt;q1:JoinOperator&gt;" + linkedEntity.JoinOperator + "&lt;/q1:JoinOperator&gt; ";            xmlSoapBody += "&lt;q1:LinkCriteria&gt; ";            if (linkedEntity.FilterOperator == null) throw new Error("Must specify non-null value for FilterOperator");            xmlSoapBody += " &lt;q1:FilterOperator&gt;" + linkedEntity.FilterOperator + "&lt;/q1:FilterOperator&gt; ";            xmlSoapBody += " &lt;q1:Conditions&gt; ";            for (conditionLinkedNumber in linkedEntity.Conditions) {                var conditionLinked = linkedEntity.Conditions[conditionLinkedNumber];                xmlSoapBody += "                             &lt;q1:Condition&gt; ";                xmlSoapBody += "                                             &lt;q1:AttributeName&gt;" + conditionLinked.Field + "&lt;/q1:AttributeName&gt; ";                xmlSoapBody += "                                             &lt;q1:Operator&gt;" + conditionLinked.Operator + "&lt;/q1:Operator&gt; ";                if (conditionLinked.Operator != "NotNull" &amp;&amp; conditionLinked.Operator != "Null") {                    xmlSoapBody += "                                             &lt;q1:Values&gt; ";                    xmlSoapBody += "                                                             &lt;q1:Value xsi:type=\"xsd:string\"&gt;" + conditionLinked.Value + "&lt;/q1:Value&gt; ";                    xmlSoapBody += "                                             &lt;/q1:Values&gt; ";                }                xmlSoapBody += "                             &lt;/q1:Condition&gt; ";            }            xmlSoapBody += " &lt;/q1:Conditions&gt; ";            xmlSoapBody += " &lt;q1:Filters /&gt; ";            xmlSoapBody += "&lt;/q1:LinkCriteria&gt; ";            xmlSoapBody += "&lt;q1:LinkEntities /&gt;";            xmlSoapBody += "&lt;/q1:LinkEntity&gt;";        }    }    if (this.LogicalOperator == null) throw new Error("Must specify non-null value for LogicalOperator");    xmlSoapBody += "&lt;/q1:LinkEntities&gt;" + "          &lt;q1:Criteria&gt;  " + "            &lt;q1:FilterOperator&gt;" + this.LogicalOperator + "&lt;/q1:FilterOperator&gt;  " + "            &lt;q1:Conditions&gt;  ";    for (conditionNumber in this.Conditions) {        var condition = this.Conditions[conditionNumber];        if (condition.Operator == null) throw new Error("Must specify non-null value for condition Operator");        xmlSoapBody += "              &lt;q1:Condition&gt;  " + "                &lt;q1:AttributeName&gt;" + condition.Field + "&lt;/q1:AttributeName&gt;  " + "                &lt;q1:Operator&gt;" + condition.Operator + "&lt;/q1:Operator&gt;  ";        if (condition.Operator != "NotNull" &amp;&amp; condition.Operator != "Null") {            xmlSoapBody += "                &lt;q1:Values&gt;  ";            xmlSoapBody += "                  &lt;q1:Value xsi:type=\"xsd:string\"&gt;" + condition.Value + "&lt;/q1:Value&gt;  ";            xmlSoapBody += "                &lt;/q1:Values&gt;  ";        }        xmlSoapBody += "              &lt;/q1:Condition&gt;  ";    }    xmlSoapBody += "            &lt;/q1:Conditions&gt;  " + "            &lt;q1:Filters /&gt;  " + "          &lt;/q1:Criteria&gt;  ";    xmlSoapBody += "&lt;q1:Orders&gt;";    for (orderNumber in this.Orders) {        var order = this.Orders[orderNumber];        if (order.OrderType == null) throw new Error("Must specify non-null value for order OrderType");        if (order.AttributeName == null) throw new Error("Must specify non-null value for order AttributeName");        xmlSoapBody += "&lt;q1:Order&gt;&lt;q1:AttributeName&gt;" + order.AttributeName + "&lt;/q1:AttributeName&gt;";        xmlSoapBody += "&lt;q1:OrderType&gt;" + order.OrderType + "&lt;/q1:OrderType&gt;&lt;/q1:Order&gt;";    }    xmlSoapBody += "&lt;/q1:Orders&gt;";    xmlSoapBody += "        &lt;/query&gt;  " + "      &lt;/RetrieveMultiple&gt;  " + "    &lt;/soap:Body&gt; " + "   &lt;/soap:Envelope&gt;";    var xmlt = xmlSoapHeader + xmlAuthHeader + xmlSoapBody;    var xmlHttpRequest = new ActiveXObject("Msxml2.XMLHTTP");    xmlHttpRequest.Open("POST", "/mscrmservices/2007/CrmService.asmx", false);    xmlHttpRequest.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/crm/2007/WebServices/RetrieveMultiple");    xmlHttpRequest.setRequestHeader("Content-Type", "text/xml; charset=utf-8");    xmlHttpRequest.setRequestHeader("Content-Length", xmlt.length);    xmlHttpRequest.send(xmlt);    if (xmlHttpRequest.responseXML == null || xmlHttpRequest.responseXML.xml == null || xmlHttpRequest.responseXML.xml == "") {        if (xmlHttpRequest.responseText != null &amp;&amp; xmlHttpRequest.responseText != "") throw new Error(xmlHttpRequest.responseText);        else        throw new Error("Error returning response");    }    var xmlResponse = xmlHttpRequest.responseXML.xml;    if (xmlHttpRequest.responseXML.documentElement.selectNodes("//error/description").length &gt; 0) {        throw new Error(xmlResponse);    }    var objNodeList = xmlHttpRequest.responseXML.documentElement.selectNodes("//BusinessEntity");    var totalNodesCount = objNodeList.length;    var result = new RetrieveMultipleResult(this);    var nodeIndex = 0;    var fieldTextTemp = "";    var fieldText = "";    if (totalNodesCount &gt; 0) {        do {            var row = result.AddRow();            for (columnNumber in this.ColumnSet) {                var columnName = this.ColumnSet[columnNumber];                fieldText = "";                var valueNode = objNodeList[nodeIndex].getElementsByTagName("q1:" + columnName)[0];                if (valueNode != null) {                    fieldTextTemp = valueNode.childNodes[0].nodeValue;                    if (fieldTextTemp != null &amp;&amp; fieldTextTemp != "") {                        fieldText = fieldText + fieldTextTemp;                    }                }                row.AddColumn(columnName, fieldText);            }            nodeIndex = nodeIndex + 1;        }        while (totalNodesCount &gt; nodeIndex)    }    return result;}//lock customer to account only// Blank out customerid if they didn't default in an accountvar LOGICAL_OPERATOR_AND = "And";var LOGICAL_OPERATOR_OR = "Or";var CONDITION_OPERATOR_EQUAL = "Equal";var JOINOPERATOR_INNER = "Inner";if ((crmForm.FormType == 1 || crmForm.FormType == 2) &amp;&amp; crmForm.all.customerid.DataValue != null &amp;&amp; crmForm.all.customerid.DataValue[0].type != "1") {    // If contact then blank out the field and set to that account    if (crmForm.all.customerid.DataValue[0].type == "2") {        // Create object passing in the entity you are selecting from             var crmService = new CrmService("account", LOGICAL_OPERATOR_OR);        // Specify select columns        crmService.AddColumn("accountnumber");        crmService.AddColumn("accountid");        crmService.AddColumn("name");        // Define linked entity - similar to SDK overload        var entityLinked = crmService.AddLinkedEntityCondition("account", "contact", "accountid", "parentcustomerid", JOINOPERATOR_INNER)        // Set filter operator (AND, OR, Ect)        entityLinked.FilterOperator = LOGICAL_OPERATOR_AND;        // Add filter condition (can add as multiple)        entityLinked.AddFilterCondition("contactid", crmForm.all.customerid.DataValue[0].id, CONDITION_OPERATOR_EQUAL);        // Retrieve the result object        var result = crmService.RetrieveMultiple();        // Loop through rows and select values (they return strings)        for (rowsNumber in result.Rows) {            var row = result.Rows[rowsNumber];            var ar = new Array(1);            ar[0] = new Object;            ar[0].id = row.GetValue("accountid");            ar[0].type = "1";            ar[0].name = row.GetValue("name");            ar[0].typename = "account";            crmForm.all.customerid.DataValue = ar;        }    }    // After contact fix, double check that it isn't set to something else (lead) and blank it out    if (crmForm.all.customerid.DataValue != null &amp;&amp; crmForm.all.customerid.DataValue[0].type != "1") crmForm.all.customerid.DataValue = null;}crmForm.all.customerid.setAttribute("lookuptypes", "1");]]&gt;&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2187748539439547090-1567563183301206395?l=andreaswijayablog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andreaswijayablog.blogspot.com/feeds/1567563183301206395/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://andreaswijayablog.blogspot.com/2011/03/crm-javascript.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/1567563183301206395'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/1567563183301206395'/><link rel='alternate' type='text/html' href='http://andreaswijayablog.blogspot.com/2011/03/crm-javascript.html' title='CRM Javascript'/><author><name>Andreas</name><uri>http://www.blogger.com/profile/07294319219169612936</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='23' src='http://2.bp.blogspot.com/_kEwj71YPhb8/TJiDclVlgOI/AAAAAAAAAEY/1Th4NMsgW_Q/S220/Andreas2.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2187748539439547090.post-8403843690093849935</id><published>2011-02-22T11:21:00.004+08:00</published><updated>2011-02-22T11:30:00.968+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Dynamics CRM 4.0'/><title type='text'>CRM Entity Relationship Many to Many (N:N)</title><content type='html'>There are two ways of getting the related entity details in many to many relationship in CRM 4.0&lt;br /&gt;&lt;br /&gt;One way is to use &lt;b&gt;RetrieveMultipleRequest&lt;/b&gt; function from the SDK:&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: csharp" type="syntaxhighlighter"&gt;&lt;![CDATA[        public BusinessEntityCollection RetrieveEntityCollectionFromManyToMany(            string linkTableEntityName,            string filterEntityName, string filterEntityIdName, string filterAttribute, string filterValue,            string returnedCollectionEntityName, string returnedCollectionEntityIdName, string[] returnedAttributes)        {            // Selection against linked Filter Entity            var con = new ConditionExpression            {                AttributeName = filterAttribute,                Operator = ConditionOperator.Equal,                Values = new[] { filterValue }            };            var filter = new FilterExpression            {                FilterOperator = LogicalOperator.And            };            filter.AddCondition(con);            // the Entity that you are filtering with            var filterLinkEntity = new LinkEntity            {                LinkToEntityName = filterEntityName,                LinkFromAttributeName = filterEntityIdName,                LinkToAttributeName = filterEntityIdName,                LinkCriteria = filter            };            // The linktable Entity that CRM generates            var linkTableEntity = new LinkEntity            {                LinkToEntityName = linkTableEntityName,                LinkFromAttributeName = returnedCollectionEntityIdName,                LinkToAttributeName = returnedCollectionEntityIdName            };            linkTableEntity.LinkEntities.Add(filterLinkEntity);            // The Entity returning the results            var expression = new QueryExpression            {                EntityName = returnedCollectionEntityName            };            // Set columns being returned            if (returnedAttributes == null)            {                expression.ColumnSet = new AllColumns();            }            else            {                expression.ColumnSet = new ColumnSet(returnedAttributes);            }            expression.LinkEntities.Add(linkTableEntity);            var request = new RetrieveMultipleRequest { Query = expression, ReturnDynamicEntities = true };            var response = (RetrieveMultipleResponse)mService.Execute(request);            return response.BusinessEntityCollection;        }]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;For example, if we have a Loan custom entity and we want to return sets of borrowers (contacts):&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: csharp" type="syntaxhighlighter"&gt;&lt;![CDATA[            CrmServiceWrapper wrapper = new CrmServiceWrapper(crmOrganizationName, crmServer, crmPort, crmUsername, crmUserPassword, crmUserDomain);            BusinessEntityCollection collection = wrapper.RetrieveEntityCollectionFromManyToMany("new_loan_borrower", "new_loan", "new_loanid",    "new_name", "2508280", "contact", "contactid", null);            return collection.BusinessEntities;]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;---&lt;br /&gt;Second way is to use &lt;b&gt;Fetch&lt;/b&gt; function to return the XML of the related entities:&lt;br /&gt;&lt;script class="brush: csharp" type="syntaxhighlighter"&gt;&lt;![CDATA[            CrmServiceWrapper wrapper = new CrmServiceWrapper(crmOrganizationName, crmServer, crmPort, crmUsername, crmUserPassword, crmUserDomain);            string linkFetch = @"&lt;fetch mapping='logical'&gt;             &lt;entity name='new_loan'&gt;              &lt;filter type='and'&gt;               &lt;condition attribute='new_name' operator='eq' value='2508280'/&gt;              &lt;/filter&gt;              &lt;link-entity name='new_loan_borrower' from='new_loanid' to='new_loanid'&gt;               &lt;attribute name='contactid'/&gt;               &lt;link-entity name='contact' to='contactid'&gt;                &lt;attribute name='new_armcontactid'/&gt;                &lt;attribute name='fullname'/&gt;               &lt;/link-entity&gt;              &lt;/link-entity&gt;             &lt;/entity&gt;            &lt;/fetch&gt;";            string result = wrapper.FetchXML(linkFetch);            XmlDocument doc = new XmlDocument();            doc.LoadXml(result);]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;James Downey created a nice little program &lt;a href="http://jamesdowney.net/blog/page/Request-FetchXML-Builder-Key.aspx"&gt;FetchXMLBuilder&lt;/a&gt; to help you build the fetch query.&lt;br /&gt;&lt;br /&gt;---&lt;br /&gt;Just for completion, below is the CRMServiceWrapper constructor that I use:&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: csharp" type="syntaxhighlighter"&gt;&lt;![CDATA[public CrmServiceWrapper(string organizationName, string serverName, string portNumber)        {            // Create authentication token for CrmService web service            CrmAuthenticationToken token = new CrmAuthenticationToken();            token.AuthenticationType = 0;            token.OrganizationName = organizationName;            mService = new CrmService();            mService.Url = "http://" + serverName + ":" + portNumber + "/mscrmservices/2007/crmservice.asmx";            mService.Credentials = CredentialCache.DefaultCredentials;            mService.CrmAuthenticationTokenValue = token;            mService.Timeout = 300 * 1000;        }public CrmServiceWrapper(string organizationName, string serverName, string portNumber, string username, string password, string domain)        {            NetworkCredential credential = new NetworkCredential(username, password, domain);            RetrieveCrmTicketResponse ticketResponse = RetrieveCrmTicket(organizationName, serverName, portNumber, username, password, domain);            // Create authentication token for CrmService web service            CrmAuthenticationToken token = new CrmAuthenticationToken();            token.AuthenticationType = 0;            token.OrganizationName = organizationName;            token.CrmTicket = ticketResponse.CrmTicket;            mService = new CrmService();            mService.Url = "http://" + serverName + ":" + portNumber + "/mscrmservices/2007/crmservice.asmx";            mService.Credentials = credential;            mService.CrmAuthenticationTokenValue = token;            mService.Timeout = 300 * 1000;        }        private RetrieveCrmTicketResponse RetrieveCrmTicket(string organizationName, string serverName, string portNumber, string username, string password, string domain)        {            NetworkCredential credential = new NetworkCredential(username, password, domain);            // Configure CrmDiscoveryService Web service proxy            dService = new CrmDiscoveryService();            dService.Url = "http://" + serverName + ":" + portNumber + "/mscrmservices/2007/AD/CrmDiscoveryService.asmx";            dService.Credentials = credential;            // Retrieve a list of available organisation            RetrieveOrganizationsRequest orgRequest = new RetrieveOrganizationsRequest();            orgRequest.UserId = domain + "\\" + username;            orgRequest.Password = password;            RetrieveOrganizationsResponse orgResponse = (RetrieveOrganizationsResponse)dService.Execute(orgRequest);            // Find the target organization            OrganizationDetail orgInfo = null;            foreach (OrganizationDetail orgDetail in orgResponse.OrganizationDetails)            {                if (orgDetail.OrganizationName.Equals(organizationName))                {                    orgInfo = orgDetail;                    break;                }            }            // Check if the organization was not found            if (orgInfo == null)                throw new Exception("The specified organization was not found.");            // Retrieve a CrmTicket from the CrmDiscoveryService web service            RetrieveCrmTicketRequest ticketRequest = new RetrieveCrmTicketRequest();            ticketRequest.OrganizationName = organizationName;            ticketRequest.UserId = domain + @"\" + username;            ticketRequest.Password = password;            RetrieveCrmTicketResponse ticketResponse = (RetrieveCrmTicketResponse)dService.Execute(ticketRequest);            return ticketResponse;        }]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Hope this helps ^_^&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2187748539439547090-8403843690093849935?l=andreaswijayablog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andreaswijayablog.blogspot.com/feeds/8403843690093849935/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://andreaswijayablog.blogspot.com/2011/02/crm-entity-relationship-many-to-many-nn.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/8403843690093849935'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/8403843690093849935'/><link rel='alternate' type='text/html' href='http://andreaswijayablog.blogspot.com/2011/02/crm-entity-relationship-many-to-many-nn.html' title='CRM Entity Relationship Many to Many (N:N)'/><author><name>Andreas</name><uri>http://www.blogger.com/profile/07294319219169612936</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='23' src='http://2.bp.blogspot.com/_kEwj71YPhb8/TJiDclVlgOI/AAAAAAAAAEY/1Th4NMsgW_Q/S220/Andreas2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2187748539439547090.post-1442302315023332572</id><published>2011-02-15T18:41:00.000+08:00</published><updated>2011-02-15T18:41:31.736+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='my piano songs'/><title type='text'>Valentine Piano Song</title><content type='html'>New Song that I created to share my Valentine Day =)&lt;br /&gt;&lt;br /&gt;&lt;iframe title="YouTube video player" width="560" height="349" src="http://www.youtube.com/embed/w8FAh4mJBZg" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2187748539439547090-1442302315023332572?l=andreaswijayablog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andreaswijayablog.blogspot.com/feeds/1442302315023332572/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://andreaswijayablog.blogspot.com/2011/02/valentine-piano-song.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/1442302315023332572'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/1442302315023332572'/><link rel='alternate' type='text/html' href='http://andreaswijayablog.blogspot.com/2011/02/valentine-piano-song.html' title='Valentine Piano Song'/><author><name>Andreas</name><uri>http://www.blogger.com/profile/07294319219169612936</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='23' src='http://2.bp.blogspot.com/_kEwj71YPhb8/TJiDclVlgOI/AAAAAAAAAEY/1Th4NMsgW_Q/S220/Andreas2.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://img.youtube.com/vi/w8FAh4mJBZg/default.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2187748539439547090.post-7757825598968225971</id><published>2011-02-10T18:02:00.001+08:00</published><updated>2011-02-10T18:09:22.624+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Dynamics CRM 4.0'/><title type='text'>CRM Plugin - Parent and Child Pipeline</title><content type='html'>This concept tends to confuse people often - and I was no exception. I came across this problem when trying to create custom auto-numbering for one of my projects.&lt;br /&gt;&lt;br /&gt;Creating auto-number for Opportunity is easy. This is because the user creates opportunity straight from the home screen - thus the plugin runs on parent pipeline. However, it's a different story if you are dealing with Quote entity.&lt;br /&gt;&lt;br /&gt;Quote can be created in 2 ways, through the home screen OR the opportunity screen. If you create it from the latter, it will run on the child pipeline and you will find that your plugin will not work.&lt;br /&gt;&lt;br /&gt;Registering it as a child pipeline is easy, but CRM makes it harder since you can't use ICRMService. Instead, you have to create CRMService manually by using this piece of code:&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: csharp" type="syntaxhighlighter"&gt;&lt;![CDATA[        public static CrmService CreateCrmService(IPluginExecutionContext context, Boolean flag)        {            var authToken = new CrmAuthenticationToken { AuthenticationType = 0, OrganizationName = context.OrganizationName, CallerId = (flag ? context.UserId : context.InitiatingUserId) };            var corToken = new CorrelationToken { CorrelationId = context.CorrelationId, CorrelationUpdatedTime = context.CorrelationUpdatedTime, Depth = context.Depth };            var regkey = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\MSCRM", false);            var service = new CrmService            {                CrmAuthenticationTokenValue = authToken,                UseDefaultCredentials = true,                Url = String.Concat(regkey.GetValue("ServerUrl").ToString(), "/2007/crmservice.asmx"),                CorrelationTokenValue = corToken            };            return service;        }]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Not only that, with the child plugin you can't use Query expression to fetch other entities in your code unless you register it as ASYNCHRONOUS plugin. Mark Kovalcson in his &lt;a href="http://crmscape.blogspot.com/2009/02/ms-crm-40-plug-in-stages-pipelines-and.html"&gt;blog&lt;/a&gt; found out that:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;A CrmService running Synchronously in a child pipeline is limited to the following:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Create&lt;br /&gt;Delete&lt;br /&gt;Update&lt;br /&gt;RetrieveExchangeRate&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;However a child plugin running in Asynchronous Execution Mode is not limited this way.&lt;br /&gt;&lt;br /&gt;Those 4 allowed actions are hard coded by MS whenever the plugin is executed inside a transaction, and it appears that all synchronous child pipeline events occur inside a transaction.&lt;br /&gt;&lt;br /&gt;However you can do a query in child pipeline if it is registered as asynchronous.&lt;br /&gt;&lt;br /&gt;In review:&lt;br /&gt;&lt;br /&gt;Use ICrmService for all parent pipelines when at all possible.&lt;br /&gt;Use CrmService for child pipelines in asynchronous execution mode.&lt;br /&gt;There is very limited functionality allowed with CrmService for any plugin registered in a synchronous child pipeline&lt;br /&gt;Querying CRM data in a plug-in registered as a synchronous Pre Create in a child process is currently very unsupported. (ie. direct SQL access)&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;In the end, if you want to generate a custom auto-number for QuoteNo, you have to create a child post create plugin and register it as asynchronous (in order to query the quote and update the entity). The code is shown below:&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: csharp" type="syntaxhighlighter"&gt;&lt;![CDATA[using System;using System.Web.Services.Protocols;using Microsoft.Crm.Sdk;using Microsoft.Crm.SdkTypeProxy;namespace My.Plugins{    public class QuoteChildPostCreatePlugin : IPlugin    {        public void Execute(IPluginExecutionContext context)        {            if (context.InputParameters.Properties.Contains(ParameterName.Target) &amp;&amp;                context.InputParameters.Properties[ParameterName.Target] is DynamicEntity)            {                DynamicEntity quo_entity = (DynamicEntity)context.InputParameters[ParameterName.Target];                var quoteId = new Guid(context.OutputParameters.Properties["id"].ToString());                if (quo_entity.Name != EntityName.quote.ToString())                    return;                try                {                    //Child pipeline!                    CrmService crmservice = CrmHelper.CreateCrmService(context, true);                    AutoNumberService aservice = new AutoNumberService(crmservice);                    QuoteNoCalculator quote_no_calc = new QuoteNoCalculator(aservice);                    var quoteNo = quote_no_calc.ChildGetQuoteNoFor("Quote");                    DynamicEntity quoEnt = crmservice.GetEntityByIdentity("quote", "quoteid", quoteId);                    quoEnt.AssignStringValueForField("new_quotenumber",quoteNo);                    crmservice.Update(quoEnt);                }                catch (SoapException ex)                {                    throw new InvalidPluginExecutionException(ex.Message);                }            }        }    }}]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;In this case I'm creating quote with the format SQ00001. The rest of the related code is below:&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: csharp" type="syntaxhighlighter"&gt;&lt;![CDATA[using System;namespace My.Plugins{    public class QuoteNoCalculator    {        private readonly AutoNumberService _aservice;        public QuoteNoCalculator(AutoNumberService service)        {            _aservice = service;        }        private string GetFormattedQuoteNo(int value)        {            return String.Concat("SQ", String.Format("{0:00000}", value));        }                public string ChildGetQuoteNoFor(string name)        {            int value = ChildGetNextAutoNumber(name);            return GetFormattedQuoteNo(value);        }                protected virtual int ChildGetNextAutoNumber(string name)        {            return _aservice.ChildGetNextAutoNumber(name);        }    }}]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: csharp" type="syntaxhighlighter"&gt;&lt;![CDATA[using System;using Microsoft.Crm.Sdk;using Microsoft.Crm.SdkTypeProxy;namespace My.Plugins{    public class AutoNumberService    {        private readonly ICrmService _service;        private readonly CrmService _crmservice;        public AutoNumberService(ICrmService service)        {            _service = service;        }        public AutoNumberService(CrmService service)        {            _crmservice = service;        }              public int ChildGetNextAutoNumber(string name)        {            const string auto_number_field = "new_autonumbervalue";            DynamicEntity entity = _crmservice.GetEntityByColumn("new_autonumber", "new_name", name);            int nextAutoNumber = entity.GetIntegerValueFor(auto_number_field);            if (nextAutoNumber == Int32.MinValue)                throw new InvalidPluginExecutionException("Can not find a entry in the auto number table for Quote");            entity.AssignNumberValueForField(auto_number_field, ++nextAutoNumber);            _crmservice.Update(entity);            return nextAutoNumber;        }    }}]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Note that for autonumbering:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;I created new custom entity new_autonumber&lt;/li&gt;&lt;li&gt;Create 2 attributes : new_name and new_autonumbervalue&lt;/li&gt;&lt;li&gt;Create new record. "Quote" as new_name, 0 as new_autonumbervalue &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;I hope you find this useful. People who think the CRM autoprefix is ugly will agree with me :)&lt;br /&gt;&lt;br /&gt;Andreas&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2187748539439547090-7757825598968225971?l=andreaswijayablog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andreaswijayablog.blogspot.com/feeds/7757825598968225971/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://andreaswijayablog.blogspot.com/2011/02/crm-plugin-parent-and-child-pipeline.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/7757825598968225971'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/7757825598968225971'/><link rel='alternate' type='text/html' href='http://andreaswijayablog.blogspot.com/2011/02/crm-plugin-parent-and-child-pipeline.html' title='CRM Plugin - Parent and Child Pipeline'/><author><name>Andreas</name><uri>http://www.blogger.com/profile/07294319219169612936</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='23' src='http://2.bp.blogspot.com/_kEwj71YPhb8/TJiDclVlgOI/AAAAAAAAAEY/1Th4NMsgW_Q/S220/Andreas2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2187748539439547090.post-920590113135656419</id><published>2011-02-10T17:34:00.003+08:00</published><updated>2011-06-14T10:36:30.033+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Dynamics CRM 4.0'/><title type='text'>CRM Service Extensions and Dynamic Entity Extensions helper</title><content type='html'>Useful extension methods for Dynamics CRM 4.0 :&lt;br /&gt;My ex-colleague wrote this I believe - visit his blog for more detail: &lt;a href="http://loosechainsaw.com"&gt;http://loosechainsaw.com&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;CRM Service&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: csharp" type="syntaxhighlighter"&gt;&lt;![CDATA[using System;using System.Collections.Generic;using Microsoft.Crm.Sdk;using Microsoft.Crm.Sdk.Query;using Microsoft.Crm.SdkTypeProxy;namespace My.Plugins{    public static class CrmServiceExtensions    {        public static DynamicEntity GetEntityByIdentity(this CrmService crmService, string entityName, string identityFieldName, Guid identity)        {            QueryExpression query = new QueryExpression();            query.EntityName = entityName;            query.ColumnSet = new AllColumns();            query.Criteria.AddCondition(identityFieldName, ConditionOperator.Equal, identity);            RetrieveMultipleRequest request = new RetrieveMultipleRequest();            request.ReturnDynamicEntities = true;            request.Query = query;            RetrieveMultipleResponse retrieved = (RetrieveMultipleResponse)crmService.Execute(request);            if (retrieved.BusinessEntityCollection.BusinessEntities.Count &gt; 0)                return (DynamicEntity)retrieved.BusinessEntityCollection.BusinessEntities[0];            return default(DynamicEntity);        }        public static DynamicEntity GetEntityByIdentity(this ICrmService crmService, string entityName, string identityFieldName, Guid identity)        {            QueryExpression query = new QueryExpression();            query.EntityName = entityName;            query.ColumnSet = new AllColumns();            query.Criteria.AddCondition(identityFieldName, ConditionOperator.Equal, identity);            RetrieveMultipleRequest request = new RetrieveMultipleRequest();            request.ReturnDynamicEntities = true;            request.Query = query;            RetrieveMultipleResponse retrieved = (RetrieveMultipleResponse)crmService.Execute(request);            if (retrieved.BusinessEntityCollection.BusinessEntities.Count &gt; 0)                return (DynamicEntity)retrieved.BusinessEntityCollection.BusinessEntities[0];            return default(DynamicEntity);        }        public static DynamicEntity GetEntityByColumn(this CrmService crmService, string entityName, string columnName, object value)        {            QueryExpression query = new QueryExpression();            query.EntityName = entityName;            query.ColumnSet = new AllColumns();            query.Criteria.AddCondition(columnName, ConditionOperator.Equal, value);            RetrieveMultipleRequest request = new RetrieveMultipleRequest();            request.ReturnDynamicEntities = true;            request.Query = query;            RetrieveMultipleResponse retrieved = (RetrieveMultipleResponse)crmService.Execute(request);            if (retrieved.BusinessEntityCollection.BusinessEntities.Count &gt; 0)                return (DynamicEntity)retrieved.BusinessEntityCollection.BusinessEntities[0];            return default(DynamicEntity);        }        public static DynamicEntity GetEntityByColumn(this ICrmService crmService, string entityName, string columnName, object value)        {            QueryExpression query = new QueryExpression();            query.EntityName = entityName;            query.ColumnSet = new AllColumns();            query.Criteria.AddCondition(columnName, ConditionOperator.Equal, value);            RetrieveMultipleRequest request = new RetrieveMultipleRequest();            request.ReturnDynamicEntities = true;            request.Query = query;            RetrieveMultipleResponse retrieved = (RetrieveMultipleResponse)crmService.Execute(request);            if (retrieved.BusinessEntityCollection.BusinessEntities.Count &gt; 0)                return (DynamicEntity)retrieved.BusinessEntityCollection.BusinessEntities[0];            return default(DynamicEntity);        }        public static DynamicEntity GetEntityByCriteria(this CrmService crmService, string entityName, List&lt;conditionexpression&gt; searchCriteria)        {            QueryExpression searchExpression = new QueryExpression();            searchExpression.EntityName = entityName;            searchExpression.ColumnSet = new AllColumns();            if (searchCriteria.Count &gt; 0)                foreach (var conditionExpression in searchCriteria)                    searchExpression.Criteria.AddCondition(conditionExpression);            RetrieveMultipleRequest request = new RetrieveMultipleRequest();            request.ReturnDynamicEntities = true;            request.Query = searchExpression;            RetrieveMultipleResponse response = (RetrieveMultipleResponse)crmService.Execute(request);            if (response.BusinessEntityCollection.BusinessEntities.Count &gt; 0)                return (DynamicEntity)response.BusinessEntityCollection.BusinessEntities[0];            return null;        }        public static List&lt;dynamicentity&gt; SelectManyDynamicEntity(this CrmService crmService, string entityName, string searchAttributeName, string searchAttributeValue, ColumnSetBase columnSet)        {            List&lt;dynamicentity&gt; retrievedDynamicEntities = new List&lt;dynamicentity&gt;();            QueryExpression query = new QueryExpression();            query.EntityName = entityName;            query.ColumnSet = columnSet;            if (!string.IsNullOrEmpty(searchAttributeName) &amp;&amp; !string.IsNullOrEmpty(searchAttributeValue))                query.Criteria.AddCondition(searchAttributeName, ConditionOperator.Equal, searchAttributeValue);            RetrieveMultipleRequest request = new RetrieveMultipleRequest();            request.ReturnDynamicEntities = true;            request.Query = query;            RetrieveMultipleResponse retrieved = (RetrieveMultipleResponse)crmService.Execute(request);            if (retrieved.BusinessEntityCollection.BusinessEntities.Count &gt; 0)            {                foreach (BusinessEntity businessEntity in retrieved.BusinessEntityCollection.BusinessEntities)                {                    retrievedDynamicEntities.Add((DynamicEntity)businessEntity);                }            }            return retrievedDynamicEntities;        }        public static List&lt;dynamicentity&gt; SelectManyDynamicEntityWithSpecifiedConditions(this CrmService crmService, string entityName, List&lt;conditionexpression&gt; conditionExpressions, ColumnSetBase columnSet)        {            List&lt;dynamicentity&gt; entities = new List&lt;dynamicentity&gt;();            QueryExpression searchQuery = new QueryExpression();            searchQuery.EntityName = entityName;            searchQuery.ColumnSet = columnSet;            if (conditionExpressions.Count &gt; 0)                foreach (var conditionExpression in conditionExpressions)                    searchQuery.Criteria.AddCondition(conditionExpression);            RetrieveMultipleRequest request = new RetrieveMultipleRequest();            request.ReturnDynamicEntities = true;            request.Query = searchQuery;            RetrieveMultipleResponse retrievedItems = (RetrieveMultipleResponse)crmService.Execute(request);            if (retrievedItems.BusinessEntityCollection.BusinessEntities.Count &gt; 0)                foreach (var businessEntity in retrievedItems.BusinessEntityCollection.BusinessEntities)                    entities.Add((DynamicEntity)businessEntity);            return entities;        }    }}]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Dynamic Entity&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: csharp" type="syntaxhighlighter"&gt;&lt;![CDATA[using System;using Microsoft.Crm.Sdk;namespace My.Plugins{    public static class DynamicEntityExtensions    {        public static int GetIntegerStatusValueFor(this DynamicEntity entity, string property)        {            if (entity.Properties.Contains(property))                return ((Status)(entity.Properties[property])).Value;            return Int32.MinValue;        }        public static Guid GetLookupAsGuidValueOfPropertyFor(this DynamicEntity entity, string property)        {            if (entity.Properties.Contains(property))                return new Guid(((Lookup)(entity.Properties[property])).Value.ToString());            return Guid.Empty;        }        public static Guid GetCustomerAsGuidValueOfPropertyFor(this DynamicEntity entity, string property)        {            if (entity.Properties.Contains(property))                return new Guid(((Customer)(entity.Properties[property])).Value.ToString());            return Guid.Empty;        }        public static string GetLookupAsStringValueOfPropertyFor(this DynamicEntity entity, string property)        {            if (entity.Properties.Contains(property))                return (((Lookup)(entity.Properties[property])).name.ToString());            return String.Empty;        }        public static string GetStringStatusValueFor(this DynamicEntity entity, string property)        {            if (entity.Properties.Contains(property))                return ((Status)(entity.Properties[property])).name;            return String.Empty;        }        public static string GetStringValueOfPropertyFor(this DynamicEntity entity, string property)        {            if (entity.Properties.Contains(property))                return entity.Properties[property].ToString();            return String.Empty;        }        public static string GetKeyAsStringValueOfPropertyFor(this DynamicEntity entity, string property)        {            if (entity.Properties.Contains(property))                return ((Key)(entity.Properties[property])).Value.ToString();            return String.Empty;        }        public static Guid GetKeyAsGuidValueOfPropertyFor(this DynamicEntity entity, string property)        {            if (entity.Properties.Contains(property))                return new Guid(((Key)(entity.Properties[property])).Value.ToString());            return Guid.Empty;        }        public static int GetIntegerValueFor(this DynamicEntity entity, string property)        {            if (entity.Properties.Contains(property))                return ((CrmNumber)(entity.Properties[property])).Value;            return Int32.MinValue;        }        public static int GetPicklistValueOfPropertyFor(this DynamicEntity entity, string property)        {            if (entity.Properties.Contains(property))                return ((Picklist)entity.Properties[property]).Value;            return Int32.MinValue;        }        public static string GetPicklistNameOfPropertyFor(this DynamicEntity entity, string property)        {            if (entity.Properties.Contains(property))                return ((Picklist)entity.Properties[property]).name;            return String.Empty;        }        public static double GetFloatValueFor(this DynamicEntity entity, string property)        {            if (entity.Properties.Contains(property))                return ((CrmFloat)(entity.Properties[property])).Value;            return Double.MinValue;        }        public static double GetDoubleValueFor(this DynamicEntity entity, string property)        {            if (entity.Properties.Contains(property))                return ((CrmDouble)(entity.Properties[property])).Value;            return Double.MinValue;        }        public static decimal GetDecimalValueFor(this DynamicEntity entity, string property)        {            if (entity.Properties.Contains(property))                return ((CrmDecimal)(entity.Properties[property])).Value;            return Decimal.MinValue;        }        public static decimal GetMoneyValueFor(this DynamicEntity entity, string property)        {            if (entity.Properties.Contains(property))                return ((CrmMoney)(entity.Properties[property])).Value;            return Decimal.MinValue;        }        public static DateTime GetDateTimeValueFor(this DynamicEntity entity, string property)        {            if (entity.Properties.Contains(property))                return ((CrmDateTime)(entity.Properties[property])).UserTime;            return DateTime.MinValue;        }        public static void ApplyActionTo(this DynamicEntity entity, Action&lt;dynamicentity&gt; action)        {            action(entity);        }        public static bool PropertyExistedButNotChanged(DynamicEntity current_employee_entity, DynamicEntity old_employee_entity, string property)        {            var oldcontains = old_employee_entity.Properties.Contains(property);            var currentcontains = current_employee_entity.Properties.Contains(property);            bool changed = true;            if (oldcontains &amp;&amp; !currentcontains)                changed = false;            return changed;        }        public static bool BothContainProperty(DynamicEntity current_employee_entity, DynamicEntity old_employee_entity, string property)        {            var oldcontains = old_employee_entity.Properties.Contains(property);            var currentcontains = current_employee_entity.Properties.Contains(property);            return oldcontains &amp;&amp; currentcontains;        }        public static bool PropertyAdded(DynamicEntity current_employee_entity, DynamicEntity old_employee_entity, string property)        {            var oldcontains = old_employee_entity.Properties.Contains(property);            var currentcontains = current_employee_entity.Properties.Contains(property);            bool changed = false;            if (!oldcontains &amp;&amp; currentcontains)                changed = true;            return changed;        }        public static void AssignStringValueForField(this DynamicEntity entity, string property, string value)        {            if (entity.Properties.Contains(property))                entity.Properties[property] = value;            else                entity.Properties.Add(new StringProperty(property, value));        }        public static void AssignBooleanValueForField(this DynamicEntity entity, string property, bool value)        {            if (entity.Properties.Contains(property))                entity.Properties[property] = new CrmBoolean(value);            else                entity.Properties.Add(new CrmBooleanProperty(property, new CrmBoolean(value)));        }        public static void AssignPicklistValueForField(this DynamicEntity entity, string property, int value)        {            if (entity.Properties.Contains(property))                entity.Properties[property] = new Picklist(value);            else                entity.Properties.Add(new PicklistProperty(property, new Picklist(value)));        }        public static void AssignFloatValueForField(this DynamicEntity entity, string property, double value)        {            if (entity.Properties.Contains(property))                entity.Properties[property] = new CrmFloat(value);            else                entity.Properties.Add(new CrmFloatProperty(property, new CrmFloat(value)));        }        public static void AssignDecimalValueForField(this DynamicEntity entity, string property, decimal value)        {            if (entity.Properties.Contains(property))                entity.Properties[property] = new CrmDecimal(value);            else                entity.Properties.Add(new CrmDecimalProperty(property, new CrmDecimal(value)));        }        public static void AssignMoneyValueForField(this DynamicEntity entity, string property, decimal value)        {            if (entity.Properties.Contains(property))                entity.Properties[property] = new CrmMoney(value);            else                entity.Properties.Add(new CrmMoneyProperty(property, new CrmMoney(value)));        }        public static void AssignNumberValueForField(this DynamicEntity entity, string property, int value)        {            if (entity.Properties.Contains(property))                entity.Properties[property] = new CrmNumber(value);            else                entity.Properties.Add(new CrmNumberProperty(property, new CrmNumber(value)));        }        public static void AssignDateTimeValueForField(this DynamicEntity entity, string property, DateTime value)        {            if (entity.Properties.Contains(property))                entity.Properties[property] = CrmDateTime.FromUniversal(value);            else                entity.Properties.Add(new CrmDateTimeProperty(property, CrmDateTime.FromUniversal(value)));        }        public static void AssignLookupValueForField(this DynamicEntity entity, string property, Lookup value)        {            if (entity.Properties.Contains(property))                entity.Properties[property] = value;            else                entity.Properties.Add(new LookupProperty(property, value));        }    }}]]&gt;&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2187748539439547090-920590113135656419?l=andreaswijayablog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andreaswijayablog.blogspot.com/feeds/920590113135656419/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://andreaswijayablog.blogspot.com/2011/02/crm-service-extensions-and-dynamic.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/920590113135656419'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/920590113135656419'/><link rel='alternate' type='text/html' href='http://andreaswijayablog.blogspot.com/2011/02/crm-service-extensions-and-dynamic.html' title='CRM Service Extensions and Dynamic Entity Extensions helper'/><author><name>Andreas</name><uri>http://www.blogger.com/profile/07294319219169612936</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='23' src='http://2.bp.blogspot.com/_kEwj71YPhb8/TJiDclVlgOI/AAAAAAAAAEY/1Th4NMsgW_Q/S220/Andreas2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2187748539439547090.post-860423538743844948</id><published>2011-01-05T23:51:00.001+08:00</published><updated>2011-02-09T21:01:37.806+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='my piano songs'/><title type='text'></title><content type='html'>Happy New Year Everyone !&lt;br /&gt;&lt;br /&gt;This is my first new song in the new year ^_^&lt;br /&gt;&lt;br /&gt;For you who don't know, my youtube channel is &lt;a href="http://www.youtube.com/nevrene"&gt;http://www.youtube.com/nevrene&lt;/a&gt; &lt;br /&gt;&lt;br /&gt;&lt;object width="425" height="344"&gt;&lt;param name="movie" value="http://www.youtube.com/v/L1iDTfT6aiQ?fs=1&amp;amp;hl=en_US"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/L1iDTfT6aiQ?fs=1&amp;amp;hl=en_US" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;All the best and hope you can achieve your dream in 2011!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2187748539439547090-860423538743844948?l=andreaswijayablog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andreaswijayablog.blogspot.com/feeds/860423538743844948/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://andreaswijayablog.blogspot.com/2011/01/happy-new-year-everyone-this-is-my.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/860423538743844948'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/860423538743844948'/><link rel='alternate' type='text/html' href='http://andreaswijayablog.blogspot.com/2011/01/happy-new-year-everyone-this-is-my.html' title=''/><author><name>Andreas</name><uri>http://www.blogger.com/profile/07294319219169612936</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='23' src='http://2.bp.blogspot.com/_kEwj71YPhb8/TJiDclVlgOI/AAAAAAAAAEY/1Th4NMsgW_Q/S220/Andreas2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2187748539439547090.post-8973441459636399025</id><published>2010-12-10T23:13:00.000+08:00</published><updated>2010-12-10T23:13:28.092+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='my piano songs'/><title type='text'>White Christmas Piano Song</title><content type='html'>Christmas is coming everyone!! Merry Christmas ^_^&lt;br /&gt;&lt;br /&gt;&lt;object height="385" width="640"&gt;&lt;param name="movie" value="http://www.youtube.com/v/3TRUAMvtNys?fs=1&amp;amp;hl=en_US"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/3TRUAMvtNys?fs=1&amp;amp;hl=en_US" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="640" height="385"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2187748539439547090-8973441459636399025?l=andreaswijayablog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andreaswijayablog.blogspot.com/feeds/8973441459636399025/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://andreaswijayablog.blogspot.com/2010/12/white-christmas-piano-song.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/8973441459636399025'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/8973441459636399025'/><link rel='alternate' type='text/html' href='http://andreaswijayablog.blogspot.com/2010/12/white-christmas-piano-song.html' title='White Christmas Piano Song'/><author><name>Andreas</name><uri>http://www.blogger.com/profile/07294319219169612936</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='23' src='http://2.bp.blogspot.com/_kEwj71YPhb8/TJiDclVlgOI/AAAAAAAAAEY/1Th4NMsgW_Q/S220/Andreas2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2187748539439547090.post-449481748735610402</id><published>2010-09-28T14:21:00.002+08:00</published><updated>2010-09-29T08:43:29.832+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SharePoint 2007'/><title type='text'>SharePoint 2007 list item print button with SSRS reportviewer</title><content type='html'>Recently I was tasked to migrate the old Asset data on Access db to SharePoint 2007. It's not difficult using 'Export to Sharepoint List' command and modified certain things such as creating new asset content type, site columns etc.&lt;br /&gt;&lt;br /&gt;I can view the list and the items. Great. but there is no print button! In Access db, they were using Access form to print the asset item. In SharePoint 2007, turns out that I have to do a bit of development to do just that.&lt;br /&gt;&lt;br /&gt;I found the nice &lt;a href="http://www.codestore.net/store.nsf/unid/BLOG-20100811-0741"&gt;blog&lt;/a&gt; on how to do this. However, I don't want to spend ridiculous amount of time playing with HTML markup to get the design I want. It is error-prone as well in terms of printing etc.&lt;br /&gt;&lt;br /&gt;Therefore, I decided to try using Reporting Service reportviewer control on the page that will render the layout. The list item details will be passed as parameters :) Cool!&lt;br /&gt;&lt;br /&gt;If you search google, you would find many articles about passing the parameters in the URL. this is not good since you will get ugly url and it will give you limitation in size. By exposing the 'custom action' into a list 'content type', we can get the List and ID to work with (mentioned in the above blog).&lt;br /&gt;&lt;br /&gt;Enough of the theory, let's see how we can get this going:&lt;br /&gt;1. Design the SSRS report (uh-huh). Add the parameters for each of the list item column you want to include.&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_kEwj71YPhb8/TKF_rnY1rfI/AAAAAAAAAE8/3qbrFtt5meY/s1600/ReportDesign.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="151" src="http://4.bp.blogspot.com/_kEwj71YPhb8/TKF_rnY1rfI/AAAAAAAAAE8/3qbrFtt5meY/s320/ReportDesign.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;2. Upload it to your report server. Then your report is ready for our printing page to consume :)&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_kEwj71YPhb8/TKF_WcU58rI/AAAAAAAAAE4/eHqmoam5WRk/s1600/ReportServer.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="128" src="http://3.bp.blogspot.com/_kEwj71YPhb8/TKF_WcU58rI/AAAAAAAAAE4/eHqmoam5WRk/s320/ReportServer.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;3.If you follow the blog to add a print button, you should have the button in your list dispform.aspx now! Except that inside the body tag of the print.aspx, we use the reportviewer control :&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: xhtml" type="syntaxhighlighter"&gt;&lt;![CDATA[&lt;%@ Assembly Name="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"%&gt; &lt;%@ Page Language="C#" %&gt; &lt;%@ Import Namespace="Microsoft.SharePoint" %&gt;&lt;%@ Import Namespace="Microsoft.Reporting.WebForms" %&gt;&lt;%@ Import Namespace="System.Collections.Generic" %&gt;&lt;%@ Import Namespace="System.Net" %&gt;&lt;%@ Import Namespace="System.Security.Principal" %&gt;&lt;%@ Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls"         Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %&gt; &lt;%@ Register  Assembly="Microsoft.ReportViewer.WebForms, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"    Namespace="Microsoft.Reporting.WebForms"     TagPrefix="rsweb" %&gt;&lt;!-- script tag --&gt;&lt;form runat="server"&gt;&lt;rsweb:ReportViewer  ID="ReportViewer"  runat="server"   Height="800px"   ShowPrintButton="false"    ShowParameterPrompts="false" Width="900px" ZoomMode="FullPage"&gt;&lt;/rsweb:ReportViewer&gt;&lt;/form&gt;]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;4. On your code behind (or inside a script tag if you don't want any code behind), get the report from the server and pass the parameters into the Report in the load event:&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: csharp" type="syntaxhighlighter"&gt;&lt;![CDATA[    protected override void OnLoad(EventArgs e)    {        try        {            SPWeb oWeb = SPControl.GetContextWeb(HttpContext.Current);                        SPList oList = oWeb.Lists[new Guid(Context.Request["List"])];            SPListItem oItem = oList.GetItemById(int.Parse(Context.Request["ID"]));                        //getSupplierID            String assetItemTypeName = oItem["AssetItemType"].ToString().Substring(oItem["AssetItemType"].ToString().IndexOf(";#") + 2);            SPList assetItemTypeList = SPContext.Current.Web.Lists["AssetItemType"];            SPQuery query = new SPQuery();            query.Query = string.Format("&lt;where&gt;&lt;eq&gt;&lt;fieldref Name='Title' /&gt;&lt;value Type='Text'&gt;{0}&lt;/Value&gt;&lt;/Eq&gt;&lt;/Where&gt;", assetItemTypeName);            SPListItem assetItemType = assetItemTypeList.GetItems(query)[0];            //getSupplierName            SPList SupplierList = SPContext.Current.Web.Lists["Suppliers"];            SPQuery supplierQuery = new SPQuery();            supplierQuery.Query = string.Format("&lt;where&gt;&lt;eq&gt;&lt;fieldref Name='SupplierID' /&gt;&lt;value Type='Number'&gt;{0}&lt;/Value&gt;&lt;/Eq&gt;&lt;/Where&gt;", assetItemType["netDeviceSupplierID"].ToString());            SPListItem supplier = SupplierList.GetItems(supplierQuery)[0];                        ReportViewer.ProcessingMode = Microsoft.Reporting.WebForms.ProcessingMode.Remote;            ReportViewer.ServerReport.ReportServerUrl = new Uri("http://ServerName/ReportServer/");            ReportViewer.ServerReport.ReportPath = "/SharePoint/AssetItemReport";            ReportViewer.ServerReport.ReportServerCredentials = new ReportServerCredentials("Username", "Password", "Domain");                        ReportParameterInfoCollection parmInfo = ReportViewer.ServerReport.GetParameters();            List&lt;reportparameter&gt; parms = new List&lt;reportparameter&gt;();            parms.Add(new ReportParameter("ID", oItem["NetworkDeviceID"] != null ? oItem["NetworkDeviceID"].ToString() : ""));            parms.Add(new ReportParameter("ItemType", oItem["AssetItemType"] != null ? oItem["AssetItemType"].ToString().Substring(oItem["AssetItemType"].ToString().IndexOf(";#") + 2) : ""));            parms.Add(new ReportParameter("Description", oItem["Description"] != null?oItem["Description"].ToString():""));            parms.Add(new ReportParameter("Serial", oItem["SerialNumber"] != null ? oItem["SerialNumber"].ToString() : ""));            parms.Add(new ReportParameter("LocCode", oItem["LocCode"] != null ? oItem["LocCode"].ToString() : ""));            parms.Add(new ReportParameter("PONum", oItem["PONum"] != null ? oItem["PONum"].ToString() : ""));            parms.Add(new ReportParameter("SupplierName", oItem["AssetItemType"] != null ? supplier["Title"].ToString() : ""));            parms.Add(new ReportParameter("InvNum", oItem["InvNum"] != null ? oItem["InvNum"].ToString() : ""));            parms.Add(new ReportParameter("PPrice", oItem["PPrice"] != null ? oItem["PPrice"].ToString() : ""));            parms.Add(new ReportParameter("DODelivery", oItem["DODelivery"] != null ? oItem["DODelivery"].ToString() : ""));            parms.Add(new ReportParameter("Custodian", oItem["Custodian"] != null ? oItem["Custodian"].ToString() : ""));            parms.Add(new ReportParameter("Location", oItem["Location"] != null ? oItem["Location"].ToString() : ""));            // Replace Parameters collection            ReportViewer.ServerReport.SetParameters(parms);            ReportViewer.ServerReport.Refresh();        }        catch (Exception ex)        {            Context.Response.Write("Error: " + ex.Message);            Context.Response.Write("Error: " + ex.StackTrace);        }    }]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;5. Notice that you need to provide ReportServerCredentials and set the ProcessingMode to Remote. This will ensure that you don't get the nasty 401 Unauthorized Error. The ReportServerCredentials class is listed below:&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: csharp" type="syntaxhighlighter"&gt;&lt;![CDATA[    [Serializable]    public class ReportServerCredentials : IReportServerCredentials    {        private string _userName;        private string _password;        private string _domain;        public ReportServerCredentials(string userName, string password, string domain)        {            _userName = userName;            _password = password;            _domain = domain;        }        public WindowsIdentity ImpersonationUser        {            get            {                // Use default identity.                return null;            }        }        public ICredentials NetworkCredentials        {            get            {                // Use default identity.                return new NetworkCredential(_userName, _password, _domain);            }        }        public bool GetFormsCredentials(out Cookie authCookie, out string user, out string password, out string authority)        {            // Do not use forms credentials to authenticate.            authCookie = null;            user = password = authority = null;            return false;        }    }]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;6. Also don't forget to check if your ReportViewer handlers exist in your web.config:&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: xml" type="syntaxhighlighter"&gt;&lt;![CDATA[      &lt;add verb="*" path="Reserved.ReportViewerWebPart.axd" type="Microsoft.ReportingServices.SharePoint.UI.WebParts.WebPartHttpHandler, Microsoft.ReportingServices.SharePoint.UI.WebParts, Version=9.0.242.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91" /&gt;      &lt;add verb="*" path="Reserved.ReportViewerWebControl.axd" type = "Microsoft.Reporting.WebForms.HttpHandler, Microsoft.ReportViewer.WebForms, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" /&gt; ]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;7. When you successfully deploy your feature, the print button now will take you to the print.aspx and the page will display your report like this:&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_kEwj71YPhb8/TKGJRCPFEwI/AAAAAAAAAFA/BvznebesLdU/s1600/Result.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="156" src="http://2.bp.blogspot.com/_kEwj71YPhb8/TKGJRCPFEwI/AAAAAAAAAFA/BvznebesLdU/s320/Result.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I hope this article will help you someday :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2187748539439547090-449481748735610402?l=andreaswijayablog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andreaswijayablog.blogspot.com/feeds/449481748735610402/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://andreaswijayablog.blogspot.com/2010/09/sharepoint-2007-list-item-print-button.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/449481748735610402'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/449481748735610402'/><link rel='alternate' type='text/html' href='http://andreaswijayablog.blogspot.com/2010/09/sharepoint-2007-list-item-print-button.html' title='SharePoint 2007 list item print button with SSRS reportviewer'/><author><name>Andreas</name><uri>http://www.blogger.com/profile/07294319219169612936</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='23' src='http://2.bp.blogspot.com/_kEwj71YPhb8/TJiDclVlgOI/AAAAAAAAAEY/1Th4NMsgW_Q/S220/Andreas2.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_kEwj71YPhb8/TKF_rnY1rfI/AAAAAAAAAE8/3qbrFtt5meY/s72-c/ReportDesign.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2187748539439547090.post-3019685262716929046</id><published>2010-09-10T09:21:00.002+08:00</published><updated>2010-09-10T09:22:23.307+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><title type='text'>.NET Convert Word Document into PDF</title><content type='html'>Howdy,&lt;br /&gt;&lt;br /&gt;I came across this old code of converting Word into PDF:&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: vb" type="syntaxhighlighter"&gt;&lt;![CDATA[    Public Sub createPdf(ByVal inputPath As String, ByVal outputPath As String, ByVal myTitle As String, ByVal myAuthor As String, ByVal mySubject As String)        Dim AcroExchApp As Acrobat.CAcroApp = CreateObject("AcroExch.App")        Dim PDDoc As Acrobat.CAcroPDDoc = CreateObject("AcroExch.PDDoc")        Dim avdoc As Acrobat.CAcroAVDoc = CreateObject("AcroExch.AVDoc")        Try            avdoc.Open(inputPath, inputPath)            avdoc = AcroExchApp.GetActiveDoc            If avdoc.IsValid Then                PDDoc = avdoc.GetPDDoc                PDDoc.SetInfo("Title", myTitle)                PDDoc.SetInfo("Author", myAuthor)                PDDoc.SetInfo("Subject", mySubject)                If PDDoc.Save(1 Or 4 Or 32, outputPath) &lt;&gt; True Then                    Stop                End If                PDDoc.Close()            End If        Catch ex As Exception            'This is used to ensure adobe cleans up        Finally            'Cleanup            avdoc.Close(True)            PDDoc = Nothing            avdoc = Nothing            AcroExchApp.Exit()            AcroExchApp = Nothing        End Try    End Sub]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;This used to work well until recently the avdoc object sometimes doesn't get the instance (i.e. null) , however running it twice usually fixed it.&lt;br /&gt;&lt;br /&gt;I don't know what caused this. It might be a system update or something. I also researched that the above code shouldn't even work since it's using Acrobat interop to open a 'doc' type - so that code was kind of a hack.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;To fix the issue, I decided to find alternative way of converting word to PDF pro grammatically. This other way requires office 12 interop instead. So the idea is to open the doc in office and save it as PDF. Simple enough! here is the code:&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: vb" type="syntaxhighlighter"&gt;&lt;![CDATA[    Public Sub createPdf(ByVal inputPath As String, ByVal outputPath As String, ByVal myTitle As String, ByVal myAuthor As String, ByVal mySubject As String)        'If Not IO.Directory.Exists(outputPath) Then        '    IO.Directory.CreateDirectory(outputPath)        'End If        Dim PDFFileName As String = outputPath        Dim MSdoc As Microsoft.Office.Interop.Word.ApplicationClass = Nothing        Dim Source As Object = inputPath        Dim readOnlya As Object = False        Dim Unknown As Object = System.Reflection.Missing.Value        Dim missing As Object = Type.Missing        Try            'Creating the instance of Word Application            If MSdoc Is Nothing Then                MSdoc = New Microsoft.Office.Interop.Word.ApplicationClass()            End If            MSdoc.Visible = False            MSdoc.Documents.Open(Source, Unknown, readOnlya, Unknown, Unknown, Unknown, Unknown, Unknown, Unknown, Unknown, Unknown, Unknown, Unknown, Unknown, Unknown, Unknown)            MSdoc.Application.Visible = False            MSdoc.WindowState = Microsoft.Office.Interop.Word.WdWindowState.wdWindowStateMinimize            Dim FileName As Object = PDFFileName            Dim FileFormat As Object = WdSaveFormat.wdFormatPDF            Dim LockComments As Object = False            Dim AddToRecentFiles As Object = False            Dim ReadOnlyRecommended As Object = False            Dim EmbedTrueTypeFonts As Object = True            Dim SaveNativePictureFormat As Object = False            Dim SaveFormsData As Object = False            Dim SaveAsAOCELetter As Object = False            Dim InsertLineBreaks As Object = False            Dim AllowSubstitutions As Object = False            Dim LineEnding As Object = WdLineEndingType.wdCRLF            Dim AddBiDiMarks As Object = False            MSdoc.ActiveDocument.SaveAs(FileName, FileFormat, LockComments, missing, AddToRecentFiles, missing, ReadOnlyRecommended, EmbedTrueTypeFonts, SaveNativePictureFormat, SaveFormsData, SaveAsAOCELetter, missing, InsertLineBreaks, AllowSubstitutions, LineEnding, AddBiDiMarks)        Catch e As FileLoadException            Console.WriteLine(e.Message &amp; "Error")        Catch e As FileNotFoundException            Console.WriteLine(e.Message &amp; "Error")        Catch e As FormatException            Console.WriteLine(e.Message &amp; "Error")        Finally            If MSdoc IsNot Nothing Then                MSdoc.Documents.Close(Unknown, Unknown, Unknown)            End If            MSdoc.Quit(Unknown, Unknown, Unknown)            MSdoc = Nothing        End Try    End Sub]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;P.S: Don't forget to install Office2007 and Acrobat on the machine :) enjoy!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2187748539439547090-3019685262716929046?l=andreaswijayablog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andreaswijayablog.blogspot.com/feeds/3019685262716929046/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://andreaswijayablog.blogspot.com/2010/09/net-convert-word-document-into-pdf.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/3019685262716929046'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/3019685262716929046'/><link rel='alternate' type='text/html' href='http://andreaswijayablog.blogspot.com/2010/09/net-convert-word-document-into-pdf.html' title='.NET Convert Word Document into PDF'/><author><name>Andreas</name><uri>http://www.blogger.com/profile/07294319219169612936</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='23' src='http://2.bp.blogspot.com/_kEwj71YPhb8/TJiDclVlgOI/AAAAAAAAAEY/1Th4NMsgW_Q/S220/Andreas2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2187748539439547090.post-1856120609075760049</id><published>2010-08-02T21:23:00.001+08:00</published><updated>2010-08-02T21:24:00.207+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='my piano songs'/><title type='text'>Starlight - New Piano Composition</title><content type='html'>Here you go:&lt;br /&gt;&lt;br /&gt;&lt;object width="480" height="385"&gt;&lt;param name="movie" value="http://www.youtube.com/v/Elg7MU8zAHE&amp;amp;hl=en_US&amp;amp;fs=1"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/Elg7MU8zAHE&amp;amp;hl=en_US&amp;amp;fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="385"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;Hope you enjoy it :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2187748539439547090-1856120609075760049?l=andreaswijayablog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andreaswijayablog.blogspot.com/feeds/1856120609075760049/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://andreaswijayablog.blogspot.com/2010/08/starlight-new-piano-composition.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/1856120609075760049'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/1856120609075760049'/><link rel='alternate' type='text/html' href='http://andreaswijayablog.blogspot.com/2010/08/starlight-new-piano-composition.html' title='Starlight - New Piano Composition'/><author><name>Andreas</name><uri>http://www.blogger.com/profile/07294319219169612936</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='23' src='http://2.bp.blogspot.com/_kEwj71YPhb8/TJiDclVlgOI/AAAAAAAAAEY/1Th4NMsgW_Q/S220/Andreas2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2187748539439547090.post-9017561386474049147</id><published>2010-07-01T12:39:00.003+08:00</published><updated>2010-07-01T13:21:23.776+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MEF'/><category scheme='http://www.blogger.com/atom/ns#' term='Silverlight 4'/><title type='text'>Load and Deploy XAP into Silverlight Application through MEF Deployment Catalog</title><content type='html'>What a sunny day today, and it feels brighter when everything comes into place together. Fortunately, this is also the case for MEF (Managed Extensibility Framework).&lt;br /&gt;&lt;br /&gt;At first I could not really be bothered with learning this stuff, however I found out that this framework is what I will be needing most for my project! Why? because MEF has the ability to join every piece of functionality together!&lt;br /&gt;&lt;br /&gt;&lt;span style="text-decoration: underline;"&gt;&lt;b&gt;Managed Extensibility Framework&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;It basically contains three steps that you need to implement:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Export : this can be any class, interface, or objects that you want to export.&lt;/li&gt;&lt;li&gt;Import : This is the place where you can get the exported pieces and do stuff with them.&lt;/li&gt;&lt;li&gt;Composition : Imagine this as a connector between export and import. It basically compose any/all parts that you specify in export and make them available for the import.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;In MEF, a piece of functionality is described as a catalog. The new deployment catalog (which I'm going to be using) is very flexible in terms of adding and removing external functionality in your application.&lt;br /&gt;&lt;br /&gt;For more information, you can read &lt;a href="http://codebetter.com/blogs/glenn.block/" target="_blank"&gt;Glenn Block&lt;/a&gt; posts. I will also use his deployment catalog service for easier XAP adding/removing.&lt;br /&gt;&lt;br /&gt;&lt;span style="text-decoration: underline;"&gt;&lt;b&gt;Real Example - Embedding Bible Application into Silverlight Business Application&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;No, this won't be a difficult demo and No, this won't be a Hello World example. I like showing people a real example of situation that you might encounter in the real world.&lt;br /&gt;&lt;br /&gt;For that purpose, I will be embedding my simple &lt;a href="http://andreaswijayablog.blogspot.com/2010/06/silverlight-4-simple-project-part-1.html" target="_blank"&gt;Indonesian Bible application&lt;/a&gt; that I wrote into Silverlight Business Application. &lt;br /&gt;&lt;br /&gt;So the idea here is that I have built a Silverlight application and I want to just load that in my main business application. This is really cool, especially if you want to organize your source code in a neat manner. MEF really can provide you with plug-in architecture.&lt;br /&gt;&lt;br /&gt;Let's get started then! :)&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Export&lt;/b&gt;&lt;br /&gt;I need to add little piece of code into my bible application. To be able to let other application to import my bible, I need to make this application available. Therefore I need to add the export attribute.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_kEwj71YPhb8/TCwTF8B1OnI/AAAAAAAAADI/tSN3Ytu9TL8/s1600/MEFexport.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_kEwj71YPhb8/TCwTF8B1OnI/AAAAAAAAADI/tSN3Ytu9TL8/s320/MEFexport.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Here I just export the usercontrol of my application. Don't forget to add to the MEF reference System.ComponentModel.Composition located in C:\Program Files (x86)\Microsoft SDKs\Silverlight\v4.0\Libraries\Client\System.ComponentModel.Composition.dll&lt;br /&gt;&lt;br /&gt;Rebuild the project. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Import&lt;/b&gt;&lt;br /&gt;In other posts, they built the application in the same solution as the host. In my case, I don't want to do that. The only thing MEF worry about in Silverlight is that there is an external XAP file in ClientBin directory of the host.&lt;br /&gt;&lt;br /&gt;For this demo, I am just going to copy paste the XAP in the previous section (after the rebuild) into the ClientBin directory of the Silverlight Business Application.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_kEwj71YPhb8/TCwU62zregI/AAAAAAAAADQ/xy3i_OYpoM8/s1600/CopyXAP.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_kEwj71YPhb8/TCwU62zregI/AAAAAAAAADQ/xy3i_OYpoM8/s320/CopyXAP.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Also, add the System.CompositionModel.Composition and System.CompositionModel.CompositionInitializer to the host application. I will then do the import inside my Home page of the host. &lt;br /&gt;&lt;br /&gt;To do this, in Home.xaml I create an ItemsControl that will load the imported usercontrol and bind it to a property of the view model:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_kEwj71YPhb8/TCwWnpKL49I/AAAAAAAAADY/6rhYBraCLPk/s1600/homexaml.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_kEwj71YPhb8/TCwWnpKL49I/AAAAAAAAADY/6rhYBraCLPk/s320/homexaml.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;The home view model is like this:&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: csharp" type="syntaxhighlighter"&gt;&lt;![CDATA[    [Export]    public class HomeViewModel : IPartImportsSatisfiedNotification, INotifyPropertyChanged    {        [ImportMany(AllowRecomposition = true)]        public Lazy&lt;usercontrol&gt;[] Widgets { get; set; }        public IEnumerable&lt;usercontrol&gt; AlkitabWidget { get; private set; }        public void OnImportsSatisfied()        {            AlkitabWidget = Widgets.Select(i =&gt; i.Value);            OnPropertyChanged("AlkitabWidget");        }        public event PropertyChangedEventHandler PropertyChanged;        private void OnPropertyChanged(string property)        {            var handler = PropertyChanged;            if (handler != null)                PropertyChanged(this, new PropertyChangedEventArgs(property));        }    }]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Here I use ImportMany and set AllowRecomposition to True. This indicates that we can import more widget as they are available. Also the recomposition is automatically done for you when there is any change in the composition.&lt;br /&gt;&lt;br /&gt;I won't explain the Lazy declaration as Glenn Block explained it well in his &lt;a href="http://codebetter.com/blogs/glenn.block/" target="_blank"&gt;blog&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Composition - Deployment Catalog&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;The DeploymentCatalogService is this:&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: csharp" type="syntaxhighlighter"&gt;&lt;![CDATA[    public interface IDeploymentCatalogService    {        void AddXap(string uri, Action&lt;asynccompletedeventargs&gt; completedAction = null);        void RemoveXap(string uri);    }    [Export(typeof(IDeploymentCatalogService))]    public class DeploymentCatalogService : IDeploymentCatalogService    {        private static AggregateCatalog _aggregateCatalog;        Dictionary&lt;string, DeploymentCatalog&gt; _catalogs;        public DeploymentCatalogService()        {            _catalogs = new Dictionary&lt;string, DeploymentCatalog&gt;();        }        public static void Initialize()        {            _aggregateCatalog = new AggregateCatalog();            _aggregateCatalog.Catalogs.Add(new DeploymentCatalog());            CompositionHost.Initialize(_aggregateCatalog);        }        public void AddXap(string uri, Action&lt;asynccompletedeventargs&gt; completedAction = null)        {            DeploymentCatalog catalog;            if (!_catalogs.TryGetValue(uri, out catalog))            {                catalog = new DeploymentCatalog(uri);                if (completedAction != null)                    catalog.DownloadCompleted += (s, e) =&gt; completedAction(e);                else                    catalog.DownloadCompleted += new EventHandler&lt;System.ComponentModel.AsyncCompletedEventArgs&gt;(catalog_DownloadCompleted);                catalog.DownloadAsync();                _catalogs[uri] = catalog;            }            _aggregateCatalog.Catalogs.Add(catalog);        }        void catalog_DownloadCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)        {            if (e.Error != null)            {                throw new Exception(e.Error.Message, e.Error);            }        }        public void RemoveXap(string uri)        {            DeploymentCatalog catalog;            if (_catalogs.TryGetValue(uri, out catalog))            {                _aggregateCatalog.Catalogs.Remove(catalog);            }        }    }]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Thank you Glenn for posting this!&lt;br /&gt;&lt;br /&gt;Here are the steps to make things connect together:&lt;br /&gt;1. In App.xaml.cs, call  DeploymentCatalogService.Initialize();  inside Application_Startup&lt;br /&gt;&lt;br /&gt;2. In my home.xaml.cs, I call the SatisfyImports, and add the external XAP using the DeploymentCatalogService. When user is navigated away from the page, I remove the XAP to avoid conflict of adding an existing XAP to the application.&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: csharp" type="syntaxhighlighter"&gt;&lt;![CDATA[    public partial class Home : Page    {        /// &lt;summary&gt;        /// Creates a new &lt;see cref="Home"/&gt; instance.        /// &lt;/summary&gt;        ///         public Home()        {            InitializeComponent();            CompositionInitializer.SatisfyImports(this);            this.Title = ApplicationStrings.HomePageTitle;            this.DataContext = ViewModel;                   }        /// &lt;summary&gt;        /// Executes when the user navigates to this page.        /// &lt;/summary&gt;        protected override void OnNavigatedTo(NavigationEventArgs e)        {            CatalogService.AddXap("AlkitabApplication.xap");        }        protected override void OnNavigatedFrom(NavigationEventArgs e)        {            CatalogService.RemoveXap("AlkitabApplication.xap");        }        [Import]        public HomeViewModel ViewModel { get; set; }        [Import]        public IDeploymentCatalogService CatalogService { get; set; }    }]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Hooray. Now when I run my Silverlight Business Application, my bible application will load inside my home page.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_kEwj71YPhb8/TCwb2WPI-DI/AAAAAAAAADg/-HCJMzlolMI/s1600/embedXAPscreenshot.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_kEwj71YPhb8/TCwb2WPI-DI/AAAAAAAAADg/-HCJMzlolMI/s320/embedXAPscreenshot.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Thanks for reading this and I hope you would find it useful ^_^&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2187748539439547090-9017561386474049147?l=andreaswijayablog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andreaswijayablog.blogspot.com/feeds/9017561386474049147/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://andreaswijayablog.blogspot.com/2010/07/load-and-deploy-xap-into-silverlight.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/9017561386474049147'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/9017561386474049147'/><link rel='alternate' type='text/html' href='http://andreaswijayablog.blogspot.com/2010/07/load-and-deploy-xap-into-silverlight.html' title='Load and Deploy XAP into Silverlight Application through MEF Deployment Catalog'/><author><name>Andreas</name><uri>http://www.blogger.com/profile/07294319219169612936</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='23' src='http://2.bp.blogspot.com/_kEwj71YPhb8/TJiDclVlgOI/AAAAAAAAAEY/1Th4NMsgW_Q/S220/Andreas2.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_kEwj71YPhb8/TCwTF8B1OnI/AAAAAAAAADI/tSN3Ytu9TL8/s72-c/MEFexport.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2187748539439547090.post-2662054091110543294</id><published>2010-06-28T14:49:00.003+08:00</published><updated>2010-06-28T14:51:38.555+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='WCF Service'/><title type='text'>Hosting WCF Service 4.0 in IIS 7.5</title><content type='html'>Hi Everyone,&lt;br /&gt;&lt;br /&gt;Today I want to show you what I did to get my WCF Service hosted on my development machine IIS (this could be your web server too). I am using VS 2010, .NET 4.0 framework, and IIS 7.5 in Windows 7 environment.&lt;br /&gt;&lt;br /&gt;In this demonstration I am going to use my AlkitabWebService.svc found in this post: &lt;a href="http://andreaswijayablog.blogspot.com/2010/06/silverlight-4-simple-project-part-2-wcf.html"&gt;Silverlight 4 Simple Project Part 2 (WCF Service)&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="text-decoration: underline;"&gt;&lt;b&gt;Step 1 - Enabling IIS + ASP.NET Registration&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Click Start -&amp;gt; Control Panel -&amp;gt; Programs -&amp;gt; Programs and Features.&lt;/li&gt;&lt;li&gt;On the left tab, click Turn Windows Features on or off. Turn on the features below and click OK.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_kEwj71YPhb8/TCg-im4n4gI/AAAAAAAAACY/PNBGwzmRC40/s1600/IIS.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_kEwj71YPhb8/TCg-im4n4gI/AAAAAAAAACY/PNBGwzmRC40/s320/IIS.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;When you go to http://localhost , you will now see the IIS7 homepage.&lt;/li&gt;&lt;li&gt;Now go to a command prompt and run aspnet_regiis:&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_kEwj71YPhb8/TCg_c6K6DyI/AAAAAAAAACg/JEWpfcumGI4/s1600/cmdasp.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_kEwj71YPhb8/TCg_c6K6DyI/AAAAAAAAACg/JEWpfcumGI4/s320/cmdasp.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style="text-decoration: underline;"&gt;&lt;b&gt;Step 2 - Publish the WCF service from VS 2010&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Right-click the project and click Publish.&lt;/li&gt;&lt;li&gt;Choose 'File System' as Publish method, and type C:\inetpub\wwwroot\AlkitabWebService\&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_kEwj71YPhb8/TChA_RpKAHI/AAAAAAAAACo/ULVE2Lel3bI/s1600/publishService.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_kEwj71YPhb8/TChA_RpKAHI/AAAAAAAAACo/ULVE2Lel3bI/s320/publishService.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;This will create a folder for your WCFService that you can refer to from IIS in the next step.&lt;br /&gt;&lt;br /&gt;&lt;span style="text-decoration: underline;"&gt;&lt;b&gt;Step 3 - Create New Application in IIS&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Go to your IIS Manager (can be accessed from Administrative Tools).&lt;/li&gt;&lt;li&gt;Right-click Default Web Site -&amp;gt; Add Application...&lt;/li&gt;&lt;li&gt;Enter in the Application Name and point the physical path to the folder that contains our published WCF service.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_kEwj71YPhb8/TChCXNtIlzI/AAAAAAAAACw/XzVoXI98NCc/s1600/iisappwcf.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_kEwj71YPhb8/TChCXNtIlzI/AAAAAAAAACw/XzVoXI98NCc/s320/iisappwcf.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style="text-decoration: underline;"&gt;&lt;b&gt;Step 4 - CrossDomain.xml and ClientAccessPolicy.xml&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;In order to be able to access your localhost in IIS, you need to implement a cross domain policy. I'm just going to make this simple. In your C:\inetpub\wwwroot folder, create a crossdomain.xml and clientaccesspolicy.xml files:&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Crossdomain.xml&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;script class="brush: xml" type="syntaxhighlighter"&gt;&lt;![CDATA[&lt;?xml version="1.0"?&gt;&lt;!DOCTYPE cross-domain-policy SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd"&gt;&lt;cross-domain-policy&gt; &lt;allow-http-request-headers-from domain="*" headers="*"/&gt;&lt;/cross-domain-policy&gt;]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Clientaccesspolicy.xml&lt;/li&gt;&lt;/ul&gt;&lt;script class="brush: xml" type="syntaxhighlighter"&gt;&lt;![CDATA[&lt;?xml version="1.0" encoding="utf-8"?&gt;&lt;access-policy&gt;    &lt;cross-domain-access&gt;        &lt;policy&gt;            &lt;allow-from http-request-headers="SOAPAction" &gt;                &lt;domain uri="https://*"/&gt;                &lt;domain uri="http://*" /&gt;            &lt;/allow-from&gt;            &lt;grant-to&gt;                &lt;resource path="/" include-subpaths="true"/&gt;            &lt;/grant-to&gt;        &lt;/policy&gt;    &lt;/cross-domain-access&gt;&lt;/access-policy&gt;]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="text-decoration: underline;"&gt;&lt;b&gt;Step 5 - Test your WCF Service&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;In IIS Manager, click the AlkitabWebService (alias).&lt;/li&gt;&lt;li&gt;On the right tab, click Browse*:80 to go to your http://localhost/AlkitabWebService/&lt;/li&gt;&lt;li&gt;You should get the view like this:&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_kEwj71YPhb8/TChDrvUCH5I/AAAAAAAAAC4/StEjEgKmaxE/s1600/wcfbrowse.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_kEwj71YPhb8/TChDrvUCH5I/AAAAAAAAAC4/StEjEgKmaxE/s320/wcfbrowse.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Clicking on AlkitabWebService.svc is our Service page. Yay!&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_kEwj71YPhb8/TChELoZw7fI/AAAAAAAAADA/mrWxkaJU9Qo/s1600/alkitabwcfiis.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_kEwj71YPhb8/TChELoZw7fI/AAAAAAAAADA/mrWxkaJU9Qo/s320/alkitabwcfiis.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2187748539439547090-2662054091110543294?l=andreaswijayablog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andreaswijayablog.blogspot.com/feeds/2662054091110543294/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://andreaswijayablog.blogspot.com/2010/06/hosting-wcf-service-40-in-iis-75.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/2662054091110543294'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/2662054091110543294'/><link rel='alternate' type='text/html' href='http://andreaswijayablog.blogspot.com/2010/06/hosting-wcf-service-40-in-iis-75.html' title='Hosting WCF Service 4.0 in IIS 7.5'/><author><name>Andreas</name><uri>http://www.blogger.com/profile/07294319219169612936</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='23' src='http://2.bp.blogspot.com/_kEwj71YPhb8/TJiDclVlgOI/AAAAAAAAAEY/1Th4NMsgW_Q/S220/Andreas2.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_kEwj71YPhb8/TCg-im4n4gI/AAAAAAAAACY/PNBGwzmRC40/s72-c/IIS.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2187748539439547090.post-5189949580948637765</id><published>2010-06-23T11:47:00.012+08:00</published><updated>2010-06-24T08:09:43.699+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Silverlight 4'/><title type='text'>Silverlight 4 Simple Project Part 4 (Binding &amp; Command)</title><content type='html'>&lt;a href="http://andreaswijayablog.blogspot.com/2010/06/silverlight-4-simple-project-part-3.html"&gt;Silverlight 4 Simple Project Part 3 (MVVM Pattern)&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;This is the last part of the blog (finally :P).&lt;br /&gt;&lt;br /&gt;In the previous post we already created our MVVM. How do we connect our View to the ViewModel? Easy! There are couple of ways to do this. We can do it declaratively in XAML or we can do it in the code-behind.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;View - View Model &amp; Binding&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I will choose the first option.&lt;br /&gt;&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: html"&gt;&lt;![CDATA[&lt;usercontrol x:Class="AlkitabApplication.MainPage"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:vm="clr-namespace:AlkitabApplication.ViewModel"mc:Ignorable="d"d:DesignHeight="539" d:DesignWidth="860" xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk" xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"&gt;&lt;UserControl.Resources&gt;&lt;vm:AlkitabViewModel x:Key="ViewModel" /&gt;&lt;/UserControl.Resources&gt;&lt;grid x:Name="LayoutRoot" Background="White" DataContext="{Binding Source={StaticResource ViewModel}}" Height="508" Width="786"&gt;&lt;!--Other Container + Controls--&gt;&lt;/Grid&gt;&lt;/UserControl&gt;]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Looking at the XAML snippet above, we declare our ViewModel as a User Control Resource and set the DataContext of our main grid to that resource.&lt;br /&gt;&lt;br /&gt;Having done that, now we can easily do our data binding for our user elements.&lt;br /&gt;&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: xml"&gt;&lt;![CDATA[&lt;telerik:RadComboBox HorizontalAlignment="Left" Margin="17,42,0,0" Name="cmbBookTitles" VerticalAlignment="Top" Width="146" IsEditable="True"ItemsSource="{Binding Path=bookTitles}" SelectedValue="{Binding Path=SelectedBookTitle, Mode=TwoWay}"&gt;&lt;/telerik:RadComboBox&gt;&lt;telerik:RadComboBox HorizontalAlignment="Left" Margin="184,42,0,0" Name="cmbBookChapters" VerticalAlignment="Top" Width="76" IsEditable="True" ItemsSource="{Binding Path=bookChapters}" SelectedValue="{Binding Path=SelectedBookChapter, Mode=TwoWay}"&gt;&lt;/telerik:RadComboBox&gt;&lt;telerik:RadComboBox HorizontalAlignment="Left" Margin="273,42,0,0" Name="cmbBookVerses" VerticalAlignment="Top" Width="73" IsEditable="True"ItemsSource="{Binding Path=bookVerses}" SelectedValue="{Binding Path=SelectedBookVerse, Mode=TwoWay}"&gt;&lt;/telerik:RadComboBox&gt;&lt;!-- Other two controls for Command section --&gt;&lt;stackpanel Margin="12,80,0,0" HorizontalAlignment="Left" Width="550" VerticalAlignment="Top" Height="416"&gt;&lt;scrollviewer HorizontalScrollBarVisibility="Auto" Height="417" Width="550"&gt;&lt;stackpanel VerticalAlignment="Top" HorizontalAlignment="Left"&gt;&lt;telerik:RadGridView ColumnWidth="*" AutoGenerateColumns="False" ItemsSource="{Binding Path=alkitabsnippet}" Name="radGridView1" Width="520" CanUserSortColumns="True" CanUserResizeColumns="True" CanUserReorderColumns="True" CanUserFreezeColumns="True" EnableColumnVirtualization="True" ShowGroupPanel="False" CanUserDeleteRows="False" CanUserInsertRows="False" CanUserSelect="True" IsEnabled="False"&gt;&lt;telerik:RadGridView.Columns&gt;&lt;telerik:GridViewDataColumn Width="120" Header="verse" DataMemberBinding="{Binding Verse}" UniqueName="verse"&gt;&lt;/telerik:GridViewDataColumn&gt;&lt;telerik:GridViewDataColumn Width="*" Header="content" DataMemberBinding="{Binding Content}" UniqueName="content" TextWrapping="Wrap"&gt;&lt;/telerik:GridViewDataColumn&gt;&lt;/telerik:RadGridView.Columns&gt;&lt;/telerik:RadGridView&gt;&lt;/StackPanel&gt;&lt;/ScrollViewer&gt;&lt;/StackPanel&gt;]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;How cool is that? We don't need any code-behind at all for our XAML! This is the beauty of MVVM Pattern.&lt;br /&gt;&lt;br /&gt;Now when we select our book title, chapter, or verse, we will get our results back in the grid without any postback since all calls are made asynchronously.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_kEwj71YPhb8/TCGIN-b5-mI/AAAAAAAAACI/ZqTFnR21KJM/s1600/Binding.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 282px;" src="http://4.bp.blogspot.com/_kEwj71YPhb8/TCGIN-b5-mI/AAAAAAAAACI/ZqTFnR21KJM/s320/Binding.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5485815594793695842" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Command&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Another new feature in Silverlight 4 is the built-in Commanding option. In this project, if you look at the image above, there is an 'Enable Range' button. I attached a command to this check box so that when IsChecked is True, it will enable the SelectBookVerseEnd selection. If IsChecked is False, it will disable the combobox.&lt;br /&gt;&lt;br /&gt;The SelectBookVerseEnd property will in turn decide whether we call the GetAlkitabSnippet function (single AlkitabSnippet object) or the GetAlkitabSnippets function (multiple AlkitabSnippet objects).&lt;br /&gt;&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: html"&gt;&lt;![CDATA[&lt;checkbox Name="chkRange" Content="Enable Range" Height="16" HorizontalAlignment="Left" Margin="395,20,0,0" VerticalAlignment="Top" IsEnabled="True"IsChecked="False" Command="{Binding Path=DisableRangeCommand, Mode=TwoWay}" /&gt;&lt;telerik:RadComboBox HorizontalAlignment="Left" Margin="395,42,0,0" Name="cmbBookVersesEnd" VerticalAlignment="Top" Width="73"  IsEditable="True"ItemsSource="{Binding Path=bookVerses}" IsEnabled="{Binding IsChecked, Mode=OneWay,ElementName=chkRange}" SelectedValue="{Binding Path=SelectedBookVerseEnd, Mode=TwoWay}"/&gt;]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Notice that I use UI Element to Element binding between the IsEnabled property of the combobox and the IsChecked property of the checkbox.&lt;br /&gt;&lt;br /&gt;To make the commanding easier, I am using the DelegateCommand class (put this inside your ViewModel) that implements the ICommand interface. This class will have the Action and CanExecute parameters that are required by the interface.&lt;br /&gt;&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: csharp"&gt;&lt;![CDATA[public class DelegateCommand : ICommand{Func&lt;object, bool&gt; canExecute;Action&lt;object&gt; executeAction;bool canExecuteCache;public DelegateCommand(Action&lt;object&gt; executeAction, Func&lt;object, bool&gt; canExecute){this.executeAction = executeAction;this.canExecute = canExecute;}#region ICommand Memberspublic bool CanExecute(object parameter){bool temp = canExecute(parameter);if (canExecuteCache != temp){canExecuteCache = temp;if (CanExecuteChanged != null){CanExecuteChanged(this, new EventArgs());}}return canExecuteCache;}public event EventHandler CanExecuteChanged;public void Execute(object parameter){executeAction(parameter);}#endregion} ]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;If you look at the XAML, the command of the checkbox is bound to DisableRangeCommand.&lt;br /&gt;Lets look at how the commanding is implemented in our view model&lt;br /&gt;&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: csharp"&gt;&lt;![CDATA[public ICommand DisableRangeCommand { get; set; } //declare the Command public AlkitabViewModel(IAlkitabService alkitabService){if (!IsDesignTime){_AlkitabService = alkitabService;GetBookTitles();this.DisableRangeCommand = new DelegateCommand(this.ResetBookVerseEnd, this.CanDisableRange); //set the command }}//this is the Command functionprivate void ResetBookVerseEnd(object param){if (this.SelectedBookVerseEnd &gt;= 0){this.SelectedBookVerseEnd = -1;this.SelectedBookVerse = SelectedBookVerse;}else{this.SelectedBookVerseEnd = this.SelectedBookVerse;}}//Return true for CanExecute parameterprivate bool CanDisableRange(object param){return true;}]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;and that's it! Simple is that. Commanding enables MVVM pattern since we don't require to handle the UI event in the XAML code behind.&lt;br /&gt;&lt;br /&gt;I will post the solution later on. Thanks for reading this and I hope you will find it useful for your own purposes.&lt;br /&gt;&lt;br /&gt;&lt;object width="560" height="340"&gt;&lt;param name="movie" value="http://www.youtube.com/v/n4jkk3JBF_I&amp;hl=en_US&amp;fs=1&amp;hd=1"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/n4jkk3JBF_I&amp;hl=en_US&amp;fs=1&amp;hd=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="560" height="340"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;Regards,&lt;br /&gt;&lt;br /&gt;Andreas&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2187748539439547090-5189949580948637765?l=andreaswijayablog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andreaswijayablog.blogspot.com/feeds/5189949580948637765/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://andreaswijayablog.blogspot.com/2010/06/silverlight-4-simple-project-part-4.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/5189949580948637765'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/5189949580948637765'/><link rel='alternate' type='text/html' href='http://andreaswijayablog.blogspot.com/2010/06/silverlight-4-simple-project-part-4.html' title='Silverlight 4 Simple Project Part 4 (Binding &amp; Command)'/><author><name>Andreas</name><uri>http://www.blogger.com/profile/07294319219169612936</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='23' src='http://2.bp.blogspot.com/_kEwj71YPhb8/TJiDclVlgOI/AAAAAAAAAEY/1Th4NMsgW_Q/S220/Andreas2.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_kEwj71YPhb8/TCGIN-b5-mI/AAAAAAAAACI/ZqTFnR21KJM/s72-c/Binding.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2187748539439547090.post-8149911237627239452</id><published>2010-06-23T10:34:00.002+08:00</published><updated>2010-06-23T13:35:10.294+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Silverlight 4'/><title type='text'>Silverlight 4 Simple Project Part 3 (MVVM Pattern)</title><content type='html'>&lt;a href="http://andreaswijayablog.blogspot.com/2010/06/silverlight-4-simple-project-part-2-wcf.html"&gt;Silverlight 4 Simple Project Part 2 (WCF Service)&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;In Part 2 we already created our WCF Service that can return some results to us when functions are called.&lt;br /&gt;&lt;br /&gt;In this post I will start building my Silverlight Application :) &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Silverlight Project&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Create new project inside the same solution. Choose Silverlight Application and name it AlkitabApplication. Right-click the project and choose Add Service Reference. click Discover and you can see that our AlkitabWebService.svc is shown. Easy!&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_kEwj71YPhb8/TCF01mnnufI/AAAAAAAAAB4/Ai5OtbPJZYU/s1600/SilverlightProject.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 155px;" src="http://1.bp.blogspot.com/_kEwj71YPhb8/TCF01mnnufI/AAAAAAAAAB4/Ai5OtbPJZYU/s320/SilverlightProject.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5485794285362592242" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;In the above picture you can also see that I created three new folders called Model, ViewModel, and Views. Move the MainPage.xaml to the Views folder.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Model View View Model (MVVM) Pattern&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;For those who are new to this term, you can read this. Otherwise you might want to move on.&lt;br /&gt;&lt;br /&gt;MVVM is just a pattern. There is no strict procedure on how to implement it. This pattern is created for developers to separate the logic of their application, providing a nice way to do unit testing and creating blendability between designer &lt;-&gt; developer. &lt;br /&gt;&lt;br /&gt;What this means is that designers can focus on playing around with the Views and developers can provide back-end data in the View Model (that perform queries against the Model) independently. The View can then just hook the View Model into it and create the bindings between the UI Elements &lt;-&gt; data. Moreover, developers can provide designers with dummy data to test while designing the Views.&lt;br /&gt;&lt;br /&gt;People have been creating tools and frameworks to assist this pattern, such as MVVM Light, MEF, and Prism. However, I won't be using any of those since my application is really simple.&lt;br /&gt;&lt;br /&gt;Confused? Let's see in action! &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Model&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Rather than calling WCF Service straight in our XAML code behind, we will create a class called AlkitabService.cs in our Model folder. It is nice to have a high level layer that provides us with one logical purpose: Our Data Source!&lt;br /&gt;&lt;br /&gt;This class will provide us sets of functions that call WCF Service functions asynchronously. Asynchronous call is what Silverlight is all about right? :) &lt;br /&gt;&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: csharp"&gt;&lt;![CDATA[&lt;br /&gt;    public interface IAlkitabService&lt;br /&gt;    {&lt;br /&gt;        void GetBookTitles(EventHandler&lt;GetBookTitlesCompletedEventArgs&gt; callback);&lt;br /&gt;        void GetBookChapters(string bookTitle, EventHandler&lt;GetBookChaptersCompletedEventArgs&gt; callback);&lt;br /&gt;        void GetBookVerses(string bookTitle, int bookChapter, EventHandler&lt;GetBookVersesCompletedEventArgs&gt; callback);&lt;br /&gt;        void GetAlkitabSnippet(string bookTitle, int bookChapter, int bookVerse, EventHandler&lt;GetAlkitabSnippetCompletedEventArgs&gt; callback);&lt;br /&gt;        void GetAlkitabSnippets(string bookTitle, int bookChapter, int bookVerseStart, int bookVerseEnd, EventHandler&lt;GetAlkitabSnippetsCompletedEventArgs&gt; callback);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public class AlkitabService : IAlkitabService&lt;br /&gt;    {&lt;br /&gt;        public void GetBookTitles(EventHandler&lt;GetBookTitlesCompletedEventArgs&gt; callback)&lt;br /&gt;        {&lt;br /&gt;                AlkitabWebServiceClient client = new AlkitabWebServiceClient();&lt;br /&gt;                client.GetBookTitlesCompleted += callback;&lt;br /&gt;                client.GetBookTitlesAsync();&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        //...Other Functions&lt;br /&gt;&lt;br /&gt;        public void GetAlkitabSnippets(string bookTitle, int bookChapter, int bookVerseStart, int bookVerseEnd, EventHandler&lt;GetAlkitabSnippetsCompletedEventArgs&gt; callback)&lt;br /&gt;        {&lt;br /&gt;            AlkitabWebServiceClient client = new AlkitabWebServiceClient();&lt;br /&gt;            client.GetAlkitabSnippetsCompleted += callback;&lt;br /&gt;            client.GetAlkitabSnippetsAsync(bookTitle, bookChapter, bookVerseStart, bookVerseEnd);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Views&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I am not much of a designer, but I like clean design :) Here is what the application looks like:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_kEwj71YPhb8/TCF6Fc0wE9I/AAAAAAAAACA/r1hnBB7moro/s1600/Views.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 281px;" src="http://1.bp.blogspot.com/_kEwj71YPhb8/TCF6Fc0wE9I/AAAAAAAAACA/r1hnBB7moro/s320/Views.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5485800055169356754" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I won't show you the XAML just yet because I will show it when I'm doing the bindings. In this project I am using Telerik Silverlight controls (RadComboBox and RadGridView). Simple reason, they have nice features such as Auto-Complete, Filtering, etc. However you can use the normal Silverlight controls to do the same thing.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;View Model&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Here is the main player. This is where all the logic resides. Inside the folder, I created two classes: ViewModelBase.cs and AlkitabViewModel.cs &lt;br /&gt;&lt;br /&gt;ViewModelBase is just a base class that implements INotifyPropertyChanged. Remember that all data/properties exposed in the UI need to have this event raised to notify the UI elements. &lt;br /&gt;&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: csharp"&gt;&lt;![CDATA[&lt;br /&gt;    public class ViewModelBase : INotifyPropertyChanged&lt;br /&gt;    {&lt;br /&gt;        protected void OnNotifyPropertyChanged(string p)&lt;br /&gt;        {&lt;br /&gt;            if (PropertyChanged != null)&lt;br /&gt;            {&lt;br /&gt;                PropertyChanged(this, new PropertyChangedEventArgs(p));&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public bool IsDesignTime&lt;br /&gt;        {&lt;br /&gt;            get&lt;br /&gt;            {&lt;br /&gt;                return (Application.Current == null) || (Application.Current.GetType() == typeof(Application));&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public event PropertyChangedEventHandler PropertyChanged;&lt;br /&gt;    }&lt;br /&gt;]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Inside AlkitabViewModel.cs is where we call our Model and store the data into our class properties that we can then bind to our UI.&lt;br /&gt;&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: csharp"&gt;&lt;![CDATA[&lt;br /&gt;    public class AlkitabViewModel : ViewModelBase&lt;br /&gt;    {&lt;br /&gt;        IAlkitabService _AlkitabService;&lt;br /&gt;        ObservableCollection&lt;string&gt; _BookTitles;&lt;br /&gt;        ObservableCollection&lt;int&gt; _BookChapters;&lt;br /&gt;        ObservableCollection&lt;int&gt; _BookVerses;&lt;br /&gt;        ObservableCollection&lt;AlkitabSnippet&gt; _AlkitabSnippet;&lt;br /&gt;&lt;br /&gt;        private string selectedBookTitle;&lt;br /&gt;        private int selectedBookChapter;&lt;br /&gt;        private int selectedBookVerse;&lt;br /&gt;        private int selectedBookVerseEnd = -1;&lt;br /&gt;&lt;br /&gt;        public ICommand DisableRangeCommand { get; set; }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        public AlkitabViewModel() : this(new AlkitabService()) &lt;br /&gt;        {&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public AlkitabViewModel(IAlkitabService alkitabService)&lt;br /&gt;        {&lt;br /&gt;            if (!IsDesignTime)&lt;br /&gt;            {&lt;br /&gt;                _AlkitabService = alkitabService;&lt;br /&gt;                GetBookTitles();&lt;br /&gt;&lt;br /&gt;                this.DisableRangeCommand = new DelegateCommand(this.ResetBookVerseEnd, this.CanDisableRange);&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public string SelectedBookTitle&lt;br /&gt;        {&lt;br /&gt;            get&lt;br /&gt;            {&lt;br /&gt;                    return this.selectedBookTitle;&lt;br /&gt;            }&lt;br /&gt;            set&lt;br /&gt;            {&lt;br /&gt;                if (value != this.selectedBookTitle)&lt;br /&gt;                {&lt;br /&gt;                    this.selectedBookTitle = value;&lt;br /&gt;                    GetBookChapters();&lt;br /&gt;                    OnNotifyPropertyChanged("SelectedBookTitle");&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;       &lt;br /&gt;        //...other selected properties&lt;br /&gt;&lt;br /&gt;        public ObservableCollection&lt;string&gt; bookTitles&lt;br /&gt;        {&lt;br /&gt;            get&lt;br /&gt;            {&lt;br /&gt;                if (_BookTitles != null &amp;&amp; _BookTitles.Count != 0) {this.SelectedBookTitle = _BookTitles[0];}&lt;br /&gt;                   &lt;br /&gt;                return _BookTitles;&lt;br /&gt;            }&lt;br /&gt;            set&lt;br /&gt;            {&lt;br /&gt;                if (_BookTitles != value)&lt;br /&gt;                {&lt;br /&gt;                    _BookTitles = value;&lt;br /&gt;                    OnNotifyPropertyChanged("bookTitles");&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        //... other Observable Collection properties&lt;br /&gt;&lt;br /&gt;        public void GetBookTitles()&lt;br /&gt;        {&lt;br /&gt;            _AlkitabService.GetBookTitles((s, e) =&gt; this.bookTitles = e.Result);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public void GetAlkitabSnippets()&lt;br /&gt;        {&lt;br /&gt;            _AlkitabService.GetAlkitabSnippets(this.SelectedBookTitle, this.SelectedBookChapter, this.SelectedBookVerse, this.SelectedBookVerseEnd, &lt;br /&gt;                (s, e) =&gt; this.alkitabsnippet = e.Result);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        //... other calls to our AlkitabService functions&lt;br /&gt;        //... command function (will be explained in the other post)&lt;br /&gt;]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Notice that we raise the NotifyPropertyChanged event in the setter of all properties.&lt;br /&gt;&lt;br /&gt;I hope you don't get a headache from this. In the next post I will talk about hooking up our ViewModel to our Views and perform the bindings. I will also quickly explain the Commanding in Silverlight 4.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://andreaswijayablog.blogspot.com/2010/06/silverlight-4-simple-project-part-4.html"&gt;Silverlight 4 Simple Project Part 4 (Binding &amp; Command)&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2187748539439547090-8149911237627239452?l=andreaswijayablog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andreaswijayablog.blogspot.com/feeds/8149911237627239452/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://andreaswijayablog.blogspot.com/2010/06/silverlight-4-simple-project-part-3.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/8149911237627239452'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/8149911237627239452'/><link rel='alternate' type='text/html' href='http://andreaswijayablog.blogspot.com/2010/06/silverlight-4-simple-project-part-3.html' title='Silverlight 4 Simple Project Part 3 (MVVM Pattern)'/><author><name>Andreas</name><uri>http://www.blogger.com/profile/07294319219169612936</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='23' src='http://2.bp.blogspot.com/_kEwj71YPhb8/TJiDclVlgOI/AAAAAAAAAEY/1Th4NMsgW_Q/S220/Andreas2.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_kEwj71YPhb8/TCF01mnnufI/AAAAAAAAAB4/Ai5OtbPJZYU/s72-c/SilverlightProject.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2187748539439547090.post-4683920969946765820</id><published>2010-06-23T09:28:00.001+08:00</published><updated>2010-06-28T14:06:34.510+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Silverlight 4'/><category scheme='http://www.blogger.com/atom/ns#' term='WCF Service'/><title type='text'>Silverlight 4 Simple Project Part 2 (WCF Service)</title><content type='html'>&lt;a href="http://andreaswijayablog.blogspot.com/2010/06/silverlight-4-simple-project-part-1.html"&gt;Silverlight 4 Simple Project Part 1 (Overview &amp; Database)&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Here I will create a WCF Service as a middleman for our Silverlight &lt;-&gt; Alkitab Database that I mentioned in Part 1.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;New Project &amp; LINQ to SQL&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;To start, I will create a WCF Service Application from Visual Studio 2010 (I didn't choose WCF Service Library because we will host it as a 'web' application in the future).&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_kEwj71YPhb8/TCFlDTqxPUI/AAAAAAAAABg/OpUb2ciqNBc/s1600/WCFNewProject.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 221px;" src="http://2.bp.blogspot.com/_kEwj71YPhb8/TCFlDTqxPUI/AAAAAAAAABg/OpUb2ciqNBc/s320/WCFNewProject.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5485776928607649090" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Then right-click the project, Add New Item -&gt; LINQ to SQL Classes. We want to drag our two tables from the Server Explorer into the dbml file. This will provide us the DataContext we require for performing our queries.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_kEwj71YPhb8/TCFmbvu_TBI/AAAAAAAAABo/HwDIY4xhzUk/s1600/WCFDBML.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 138px;" src="http://1.bp.blogspot.com/_kEwj71YPhb8/TCFmbvu_TBI/AAAAAAAAABo/HwDIY4xhzUk/s320/WCFDBML.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5485778447970028562" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;WCF Service&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Next, rename Service.svc and IService.cs to friendlier names like AlkitabWebService.svc and IAlkitabWebService.cs &lt;br /&gt;&lt;br /&gt;IAlkitabWebService.cs is the interface class for our service. This will hold all the OperationContract (functions) declarations and any DataContract (web class) that you want to create along with its DataMember (class property). Here I have sets of operations and AlkitabSnippet class that will hold verse and content:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:csharp"&gt;[ServiceContract]&lt;br /&gt;public interface IAlkitabWebService&lt;br /&gt;{&lt;br /&gt;[OperationContract]&lt;br /&gt;string GetContent(string bookTitle, int bookChapter, int bookVerse);&lt;br /&gt;&lt;br /&gt;[OperationContract]&lt;br /&gt;ObservableCollection&amp;lt;AlkitabSnippet&gt; GetAlkitabSnippet(string bookTitle, int bookChapter, int bookVerse);&lt;br /&gt;&lt;br /&gt;[OperationContract]&lt;br /&gt;ObservableCollection&amp;lt;AlkitabSnippet&gt; GetAlkitabSnippets(string bookTitle, int bookChapter, int bookVerseStart, int bookVerseEnd);&lt;br /&gt;&lt;br /&gt;[OperationContract]&lt;br /&gt;ObservableCollection&amp;lt;string&gt; GetBookTitles();&lt;br /&gt;&lt;br /&gt;[OperationContract]&lt;br /&gt;ObservableCollection&amp;lt;int&gt; GetBookChapters(string bookTitle);&lt;br /&gt;&lt;br /&gt;[OperationContract]&lt;br /&gt;ObservableCollection&amp;lt;int&gt; GetBookVerses(string bookTitle, int bookChapter);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// Use a data contract as illustrated in the sample below to add composite types to service operations.&lt;br /&gt;[DataContract]&lt;br /&gt;public class AlkitabSnippet&lt;br /&gt;{&lt;br /&gt;string verse;&lt;br /&gt;string content;&lt;br /&gt;&lt;br /&gt;[DataMember]&lt;br /&gt;public string Verse&lt;br /&gt;{&lt;br /&gt;get { return verse; }&lt;br /&gt;set { verse = value; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;[DataMember]&lt;br /&gt;public string Content&lt;br /&gt;{&lt;br /&gt;get { return content; }&lt;br /&gt;set { content = value; }&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;In the AlkitabWebService.svc.cs, we implement all the service functions that we need to get data out of the database. Here are two of the functions:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:csharp"&gt;public class AlkitabWebService : IAlkitabWebService&lt;br /&gt;{&lt;br /&gt;public ObservableCollection&amp;lt;AlkitabSnippet&gt; GetAlkitabSnippets(string bookTitle, int bookChapter, int bookVerseStart, int bookVerseEnd)&lt;br /&gt;{&lt;br /&gt;ObservableCollection&amp;lt;AlkitabSnippet&gt; snippets = new ObservableCollection&amp;lt;AlkitabSnippet&gt;();&lt;br /&gt;&lt;br /&gt;AlkitabDataContext db = new AlkitabDataContext();&lt;br /&gt;&lt;br /&gt;var query = from c in db.Alkitabs&lt;br /&gt;join b in db.AlkitabBooks&lt;br /&gt;on c.book equals b.bookno&lt;br /&gt;where b.booktitle == bookTitle &amp;&amp; c.chapter == bookChapter &amp;&amp; c.verse &gt;= bookVerseStart &amp;&amp; c.verse &amp;lt;= bookVerseEnd&lt;br /&gt;select new { verse = c.verse, content = c.content };&lt;br /&gt;&lt;br /&gt;foreach (var e in query)&lt;br /&gt;{&lt;br /&gt;AlkitabSnippet snippet = new AlkitabSnippet();&lt;br /&gt;snippet.Verse = bookTitle + " " + bookChapter + ":" + e.verse;&lt;br /&gt;snippet.Content = e.content;&lt;br /&gt;snippets.Add(snippet);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;return snippets;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public ObservableCollection&amp;lt;string&gt; GetBookTitles()&lt;br /&gt;{&lt;br /&gt;ObservableCollection&amp;lt;string&gt; booktitles = new ObservableCollection&amp;lt;string&gt;();&lt;br /&gt;&lt;br /&gt;AlkitabDataContext db = new AlkitabDataContext();&lt;br /&gt;&lt;br /&gt;Table&amp;lt;AlkitabBook&gt; AlkitabBook = db.GetTable&amp;lt;AlkitabBook&gt;();&lt;br /&gt;&lt;br /&gt;var query = from a in AlkitabBook orderby a.bookno select a.booktitle;&lt;br /&gt;&lt;br /&gt;foreach (var e in query)&lt;br /&gt;{&lt;br /&gt;booktitles.Add(e.ToString());&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;return booktitles;&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;One question you might ask (I asked this to myself as well when I was a total newbie) is what is an ObservableCollection&lt;t&gt;. WCF Proxy Class use this type of collection by default. However, this collection is different from other type of normal collection, lets say List&lt;t&gt;, in a sense that it provides notification when items get added, removed, or refreshed and when the items property is changed (it implements INotifyCollectionChanged and INotifyPropertyChanged).&lt;br /&gt;&lt;br /&gt;This is required for Silverlight to get the notification any change so that it can update all the UI elements associated with the collection.&lt;br /&gt;&lt;br /&gt;That's all we need to do for our WCF Service :) &lt;br /&gt;&lt;br /&gt;In the next post we will create our Silverlight application that references this service. I will start with the explanation of MVVM model, the popular pattern of building your application.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://andreaswijayablog.blogspot.com/2010/06/silverlight-4-simple-project-part-3.html"&gt;Silverlight 4 Simple Project Part 3 (MVVM Pattern)&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2187748539439547090-4683920969946765820?l=andreaswijayablog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andreaswijayablog.blogspot.com/feeds/4683920969946765820/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://andreaswijayablog.blogspot.com/2010/06/silverlight-4-simple-project-part-2-wcf.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/4683920969946765820'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/4683920969946765820'/><link rel='alternate' type='text/html' href='http://andreaswijayablog.blogspot.com/2010/06/silverlight-4-simple-project-part-2-wcf.html' title='Silverlight 4 Simple Project Part 2 (WCF Service)'/><author><name>Andreas</name><uri>http://www.blogger.com/profile/07294319219169612936</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='23' src='http://2.bp.blogspot.com/_kEwj71YPhb8/TJiDclVlgOI/AAAAAAAAAEY/1Th4NMsgW_Q/S220/Andreas2.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_kEwj71YPhb8/TCFlDTqxPUI/AAAAAAAAABg/OpUb2ciqNBc/s72-c/WCFNewProject.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2187748539439547090.post-6881825571655803175</id><published>2010-06-23T09:10:00.012+08:00</published><updated>2010-06-24T11:50:47.184+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Silverlight 4'/><title type='text'>Silverlight 4 Simple Project Part 1 (Overview + Database)</title><content type='html'>Howdy!&lt;br /&gt;&lt;br /&gt;This will be my first technical blog. The motivation behind this is that I love learning Silverlight (and it's version 4 now!). So I decided to create my own simple project as I am thinking of building a website for my church community group in the future.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;Overview: &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Why not start with a simple module? I want to be able to search for a bible verse in a quick way and no hassle of having to spend much time on it. Therefore I want the users to be able to select the book title, chapter, and verse (or verse range) and have the contents showed in front of them straight away!&lt;br /&gt;&lt;br /&gt;Here is a video showing the completed application with some explanation:&lt;br /&gt;&lt;br /&gt;&lt;object height="340" width="560"&gt;&lt;param name="movie" value="http://www.youtube.com/v/n4jkk3JBF_I&amp;hl=en_US&amp;fs=1&amp;hd=1"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/n4jkk3JBF_I&amp;hl=en_US&amp;fs=1&amp;hd=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="560" height="340"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Database:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Now.. I found out that there are already some English bible web services out there. However since my community is Indonesian, I want to have an Indonesian bible, and it turns out that there is none! and there is no SQL formatted database dump available either :(&lt;br /&gt;&lt;br /&gt;However, I could find the text format of the bible. I looked inside and here is what it looks like:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_kEwj71YPhb8/TCLV-poPA7I/AAAAAAAAACQ/8UHS6fA8rZM/s1600/BibleText.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_kEwj71YPhb8/TCLV-poPA7I/AAAAAAAAACQ/8UHS6fA8rZM/s320/BibleText.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;'This must be my day', I said to myself; This is because I could easily do this:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_kEwj71YPhb8/TCFf_yUWreI/AAAAAAAAABQ/_hqziic_msw/s1600/BibleTableDesign.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5485771370557517282" src="http://1.bp.blogspot.com/_kEwj71YPhb8/TCFf_yUWreI/AAAAAAAAABQ/_hqziic_msw/s320/BibleTableDesign.png" style="cursor: pointer; display: block; height: 140px; margin: 0px auto 10px; text-align: center; width: 320px;" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;And just use bulk insert to load the txt file (Alkitab = Bible):&lt;br /&gt;&lt;pre class="brush:sql"&gt;BULK INSERT Alkitab&lt;br /&gt;FROM 'c:\IndonesianBible.txt'&lt;br /&gt;WITH&lt;br /&gt;(&lt;br /&gt;FIELDTERMINATOR = '\t',&lt;br /&gt;ROWTERMINATOR = '\n'&lt;br /&gt;)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Nice. Now I have my Indonesian bible database. To improve my database, I am going to create another table that contains my book title and link both tables together:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_kEwj71YPhb8/TCFgznzFyqI/AAAAAAAAABY/xgrt1SeiBAs/s1600/BibleTableDiagram.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5485772261086841506" src="http://3.bp.blogspot.com/_kEwj71YPhb8/TCFgznzFyqI/AAAAAAAAABY/xgrt1SeiBAs/s320/BibleTableDiagram.png" style="cursor: pointer; display: block; height: 112px; margin: 0px auto 10px; text-align: center; width: 320px;" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;In the next post I will create a WCF Service with some functions that will query this database and return the contents that will be consumed by our Silverlight application. :)&lt;br /&gt;&lt;br /&gt;&lt;a href="http://andreaswijayablog.blogspot.com/2010/06/silverlight-4-simple-project-part-2-wcf.html"&gt;Silverlight 4 Simple Project Part 2 (WCF Service)&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2187748539439547090-6881825571655803175?l=andreaswijayablog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andreaswijayablog.blogspot.com/feeds/6881825571655803175/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://andreaswijayablog.blogspot.com/2010/06/silverlight-4-simple-project-part-1.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/6881825571655803175'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/6881825571655803175'/><link rel='alternate' type='text/html' href='http://andreaswijayablog.blogspot.com/2010/06/silverlight-4-simple-project-part-1.html' title='Silverlight 4 Simple Project Part 1 (Overview + Database)'/><author><name>Andreas</name><uri>http://www.blogger.com/profile/07294319219169612936</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='23' src='http://2.bp.blogspot.com/_kEwj71YPhb8/TJiDclVlgOI/AAAAAAAAAEY/1Th4NMsgW_Q/S220/Andreas2.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_kEwj71YPhb8/TCLV-poPA7I/AAAAAAAAACQ/8UHS6fA8rZM/s72-c/BibleText.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2187748539439547090.post-5212964421659603992</id><published>2010-06-22T20:30:00.000+08:00</published><updated>2010-06-22T21:47:58.762+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='my piano songs'/><title type='text'>My Piano Songs - Blog Started!</title><content type='html'>Hello Everyone,&lt;br /&gt;&lt;br /&gt;As I am starting my blog, I want to entertain you all with few of my popular songs. Feel free to listen to all of them and give any feedback! ^_^&lt;br /&gt;&lt;br /&gt;Here you go:&lt;br /&gt;&lt;br /&gt;1. Rising&lt;br /&gt;&lt;br /&gt;&lt;embed src="http://www.google.com/reader/ui/3523697345-audio-player.swf" flashvars="audioUrl=http://pianoismyfriend.com/wp-content/uploads/lagu/Rising.mp3" pluginspage="http://www.macromedia.com/go/getflashplayer" height="27" width="400"&gt;&lt;/embed&gt;&lt;br /&gt;&lt;br /&gt;2. Winter Love&lt;br /&gt;&lt;br /&gt;&lt;embed src="http://www.google.com/reader/ui/3523697345-audio-player.swf" flashvars="audioUrl=http://pianoismyfriend.com/wp-content/uploads/audition/Winter%20Love.mp3" pluginspage="http://www.macromedia.com/go/getflashplayer" height="27" width="400"&gt;&lt;/embed&gt;&lt;br /&gt;&lt;br /&gt;3. The Truth&lt;br /&gt;&lt;br /&gt;&lt;embed src="http://www.google.com/reader/ui/3523697345-audio-player.swf" flashvars="audioUrl=http://pianoismyfriend.com/wp-content/uploads/lagu/The%20Truth.mp3" pluginspage="http://www.macromedia.com/go/getflashplayer" height="27" width="400"&gt;&lt;/embed&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I will probably post my other songs regularly. I will also post my YouTube videos here as well. Feel free to follow my blog :)&lt;br /&gt;&lt;br /&gt;Thanks and Enjoy!&lt;br /&gt;&lt;br /&gt;Andreas&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2187748539439547090-5212964421659603992?l=andreaswijayablog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andreaswijayablog.blogspot.com/feeds/5212964421659603992/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://andreaswijayablog.blogspot.com/2010/06/my-piano-songs-blog-started.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/5212964421659603992'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2187748539439547090/posts/default/5212964421659603992'/><link rel='alternate' type='text/html' href='http://andreaswijayablog.blogspot.com/2010/06/my-piano-songs-blog-started.html' title='My Piano Songs - Blog Started!'/><author><name>Andreas</name><uri>http://www.blogger.com/profile/07294319219169612936</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='23' src='http://2.bp.blogspot.com/_kEwj71YPhb8/TJiDclVlgOI/AAAAAAAAAEY/1Th4NMsgW_Q/S220/Andreas2.jpg'/></author><thr:total>0</thr:total></entry></feed>
