Monday 26 September 2011

CRM Entropy - A Microsoft CRM Blog: Updated CRM Javascript Library: 1.2

It’s been a little while since I published all the additions I’ve made to my personal CRM Javascript Library up to GitHub, but today I found a few moments to do so.  Most of the scripts I’ve published on this blog are in the library, and are up-to-date with the most recent bug-fixes and features.  This library of functions is what I use in my CRM deployment, and helps by drastically reducing the amount of effort spent in deploying functionality to customizations.

One of these days, I’m going to have to get around to writing up descriptions of all the functions on the project page.  Oh well.  Hopefully, the names of the functions are pretty clear regarding their intended application.  Also, since most of them come from posts, a cursory search through the blog should reveal helpful explanations and even some sample code.

CRM Entropy - A Microsoft CRM Blog: Global MVP Summit, Here I Come!

Registration for the Microsoft 2011 MVP Global Summit opened on Monday, last week.  The moment registration was possible, I completed it.  My excitement could be barely contained when Matt Wittemann, a fellow CRM MVP from C5Insight, agreed to room with me during the event.  This will be my first Summit, and it will be awesome to have an experienced guide.

(Matt blogged about my Javascript Grid Editor project earlier this year, several months before I found out I had been nominated for the MVP Award.  Since then, I’ve become a follower of his ICU MSCRM blog.  He’s really got some neat stuff there, so check it out if you haven’t had a chance.)

I’m also blessed to have my employer, BC Technical, offer to send me to the event.  Obviously it’s easier to attend the Summit for us state-side MVPs, but even without compensated hotel accommodations, attending the event would have exhausted my available funds.  I don’t write about my employer much in this blog, mostly because this blog is a personal space, but this exception I’m making is to say, “thank you,” in a public format.  BC Technical has always encouraged personal growth in my career, but this contribution makes them invested in a way I didn’t expect.  May we all be so fortunate!

As for the Summit, I’m ardently anxious to meet my personal CRM heroes—many of whom have indicated that they will be attending.  I’ve had a wonderful chance, through various MVP-related channels, to establish personal relationships with people I only knew by name only a year ago.  Though the Global MVP Summit is not product-specific, I’m sure most of my time will be spent within the CRM-sphere.

So, it’s full-steam ahead to the Summit!  If you’re attending, and would like to meet, send me a message.  If you’re a part of the CRM MVP team, I probably owe you a beer, so don’t forget to collect!

CRM Entropy - A Microsoft CRM Blog: Brad Wilson on Partners in CRM Online

Again, Software Advice continues their series of interview videos with Dynamics CRM GM, Brad Wilson:

Brad Wilson talks about the change in Microsoft Partner involvement with the advent of Cloud-based CRM.

Source: http://www.softwareadvice.com/articles/crm/can-dynamics-crm-partners-survive-in-the-cloud-era-microsoft-executive-interview-1022411/

Touching on the complaints I made in my last post about the absence of the Partner-centric CRM deployment option, Brad Wilson suggests rightly that the relationship between Partners and Microsoft have changed in the CRM arena.  Unfortunately, it seems that the only “out” for a Partner is to:

  1. become an ISV-development shop (subsisting on the new Dynamics Marketplace for revenue), and/or
  2. become consultants for business and data-management processes in the CRM space

As a point of topic, the improved turn-around for “trial” deployments of CRM Online seems to be ungracious at best, as Partners appear to have been reduced to glorified CRM Online sales agents; the knife twisting a full 360° when both the interviewer Don Fornes and Brad conclude: “change is hard.”

At this point, I should state that I’m uncertain if the Partner-hosted CRM option still exists with CRM 2011.  I don’t know why it wouldn’t, but it appears completely absent from these interviews.  I always assumed that “On-Premise” was a simple moniker, and that it didn’t actually necessitate on-site visits from a Partner to “drop in a CD”.  Granted, I’m certain the deployment of a CRM Online organization would be dramatically faster than an On-Premise installation, but haven’t we improved that process in the age of virtualization?

I understand that Microsoft is investing heavily in CRM Online, and for smaller organizations with immediate needs, it can hardly be beat as a robust, capable, and prompt solution.  What I fear, however, is that Microsoft is calling all chickens home to roost, and arbitrarily discarding the value Partners have established apart from CRM Online, and the differences in the capabilities, customization or otherwise, with On-Premise.

Nowhere is it apparent that the customer will have the ability to protect, optimize, or archive their data in CRM Online in ways that are intrinsic to CRM On-Premise, and it seems that such is readily sacrificed for the ability to move faster.  I don’t care how fast your car can go, if you have no way to stop it or correct your course without a fiery spectacle, you won’t find me in the passenger seat.

P.S.  I would love to be soundly debated and corrected if anything I have said is incorrect.

CRM Entropy - A Microsoft CRM Blog: CRM Gotcha: Using Javascript URIs in SiteMap

Donna Edwards, CRM forums co-owner and established MVP, will often bounce threads from the “main” CRM forum into the CRM Development forum, which I comfortably call home, whenever the question is a particularly obscure one and hasn’t received an answer from the cabal of experts usually found in the “main” CRM forum.  I delight in any opportunity to take her “escalations” as a personal challenge.  Today, I found it in this thread.

The author explains that his usage of a “javascript:” URI produces interesting behavior when placed into the Url attribute of a SubArea element within the CRM SiteMap.  At first, with some simple JavaScript, he was receiving the text “[object]” in the dynamic CRM content frame.  Then, when he voided the return of the URI’s script, the “Loading…” message and graphic would remain (until some other area was loaded).

I encountered a similar behavior when working on the Embedded Advanced Find View project, and guessed that the same situational elements must be present here.  Not wanting to be wrong, I pulled out the IE Developer Tools (side-note: Microsoft, this is seriously the coolest feature of IE 8), and confirmed it.

So, what explains the behavior?  The answer is simple:  AJAX.  See, CRM’s UI scripts don’t simply pass the Url value into the src attribute of a frame (or Iframe); how would it achieve the “Loading…” message, if it did?  The trick, is that CRM scripts overwrite the contents of the dynamic content frame with the HTML necessary to display that message, and then instantiates a new, ActiveX [FreeThreaded]DOMDocument object behind-the-scenes to load the target URI.  When the status of the DOM document object becomes complete, the dynamic content frame’s DOM is overridden with the results.

This means that the original contents are lost.  Because the previous contents were also loaded in this dynamic fashion, and don’t exist in the browsing history, the frame can’t be historically reverted (e.g. javascript:history.go(-1)).  Additionally, a “javascript:” URI isn’t loaded into the DOM document object until after the contents have already been replaced by the “Loading…” message.  So, it makes any reference to the information that had originally been in the frame nearly impossible to obtain.

I’m sure somebody will figure out how best to produce content or redirection within the dynamic content frame, while simultaneously using a “javascript:” URI, but I’m unaware of any such process available today.  I think it’s simply safer to say that, though not expressly declared as such in the SDK, “javascript:” URIs aren’t supported.

CRM Entropy - A Microsoft CRM Blog: Good Code, by XKCD

As a frequenter of the CRM Development community, I find great comfort in knowing that I’m not the only one who is frustrated by timetables when developing.  That’s why I wanted to share today’s offering by a web comic strip (technically) that I read regularly, XKCD:

“No, and the requirements have changed” is a bittersweet rut I find myself in a lot.  And it’s true, that somehow, by some miracle, “Good Code” just appears out of thin air—or at least it seems to, because it was written during a drunken, midnight coding session too good to remember.

Enjoy!

CRM Entropy - A Microsoft CRM Blog: It’s Been Quiet

I’m not altogether certain how much of an audience my blog has.  If the Feedburner statistics are accurate, then it’s roughly a couple hundred.  That doesn’t consider, however, those who don’t use RSS or Atom to follow it.  However, some of you may wonder why this space has been unusually quiet recently, and I wanted to take a few moments to explain why.

In the first week of January, my daughter was diagnosed with Neuroblastoma.  It’s been a hectic and busy month for me, causing a great deal of absence away from the CRM community.  Now that I’m back to work and managing to recover some of the time I’ve dedicated to supporting the family during this trying time, I’m easing back into my usual community involvements.  However, limitations being what they are, I doubt that I will be able to return to my previous station completely.

I will not be attending the MVP Summit, and hope that my contributions so far, and what little I’m able to make throughout the remainder of my “cycle” will earn me a renewal, so that I may attempt to attend again next year.  I’ve made this information known to the MVP team already, but include it here for those who aren’t apart of the NDA-based conversation channels.  I will truly miss this opportunity at such an exciting time in CRM’s history (with the advent of CRM 2011).

My wife and I are blessed and fortunate to have a strong network of family and friends to support us during this challenge, and we look forward to our daughter’s complete recovery with great hope.  Though things will become more difficult in the months ahead, we know that we will not have to undertake its monumental burden alone.

I thank all of you who send us your support, prayers, good thoughts, and the like.

CRM Entropy - A Microsoft CRM Blog: Brad Wilson on the State of CRM

The kind folks over at Software Advice have asked me to review their on-going series of interviews within the Microsoft CRM sphere, whereby they take a look at the offerings surrounding Microsoft Dynamics CRM, and include them on my blog.  The last time they requested involvement of this space, for marketing material, I must admit that I was unfriendly.  This space is not an advertisement platform—it’s an evolving personal experience shared with the CRM Community.

That said, I have reviewed this new material and found it more suitable than their last request for inclusion in this space.  Below is a video interview with none other than the GM of Dynamics CRM, Brad Wilson, and his thoughts on the state of CRM in the marketplace.  I believe this clip stands apart from any marketing purpose and provides insight into the experience Microsoft has had with CRM as a product.  Though the clip is painfully short for the amount of material I’m sure Brad keeps locked up in that large cranium of his, it is concise and to the point:

Brad Wilson, GM for Microsoft Dynamics CRM, discusses the evolution of CRM in the marketplace with Don Fornes of Software Advice.

Source: http://www.softwareadvice.com/articles/crm/state-of-the-crm-software-market-microsoft-executive-interview-1022111/

CRM Entropy - A Microsoft CRM Blog: Brad Wilson on Cloud-Driven CRM

Software Advice follows up with their series of video-interview clips of Brad Wison, GM of Dynamics CRM at Microsoft, with their latest offering:

Brad Wilson talks about CRM in the cloud and how Microsoft leverages customer choice, between this and On-Premise, with Microsoft CRM.

Source:  http://www.softwareadvice.com/articles/crm/how-many-customers-really-want-crm-in-the-cloud-microsoft-executive-interview-1022311/

While the clip format, as a trend, seems to be short, it’s the questions and answers themselves that are short.  While it’s nice to hear Brad Wilson offering up a bit of an official PR-stylized look into the element of choice Microsoft CRM grants between Online and On-Premise, and the ability to move between them interchangeably, he suggest that the key factor for this decision is the customer’s IT competency—in so many words.  (While the word “Online” is never used, he directly states that “in the cloud” means Microsoft data-centers.)

I think Brad Wilson has done CRM, the product, a disservice.  With my employer, CRM was acquired in its earliest stages while the company staff count was below 20, and IT itself was a single man.  Now that we’ve grown to well over 120 employees, CRM is still run by a single--albeit different--man:  me.  The fact that I’m an MVP is proof in the pudding that one person can learn enough about CRM in a growing company that is still relatively small to keep it running well all by himself.

As a product, the ease of customization and deployment really speaks to the capability of CRM On-Premise.  In fact, one of the most critical business decisions are how and when to make backups… and what concerns me most is the inability to do so in CRM Online.  However, CRM On-Premise does not disappoint, being contained nearly entirely within SQL Server.  It’s so easy to backup, a single guy can setup a simple job to do it for him.

The logistical impracticality of providing this capability to CRM Online, however, also does CRM, the product, a disservice.  I maintain resolute in my declaration that CRM is the best product Microsoft ever made, because of its flexibility and time-to-market for even moderately complex, customized solutions.  If there’s one factor I think should serve as a guide to a customer’s choice in deployment types, between Online and On-Premise, I think it should be where the two really differ:  how much control one has over the data.

Sure, this does assume you have some functionally capable IT staff, but even the bevy of Microsoft CRM consultants and hosted-deployment shops are capable of providing this data control for very reduced cost, and without the need for dedicated IT.  I think a customer of Microsoft CRM would be disadvantaged to believe that they only have two choices, overlooking the powerful advantages gained by finding the middle-ground between them that goes unmentioned in this discussion.

CRM Entropy - A Microsoft CRM Blog: Patrick Smacchia on Code Partitioning

While I’m still trying to find time to contribute to the CRM community with the often overwhelming personal time requirements, I found a lot of helpful information in an article by Patrick Smacchia, whom I know from the NDepend project.  He has written a very thorough and enlightening article on the principles and practices of segmenting code through the use of solutions, projects, and assemblies in Visual Studio.  I intend to use this information to make myself a more efficient developer in my CRM projects.  Thank you, Patrick!

CRM Entropy - A Microsoft CRM Blog: CRM Wiki Moves to TechNet!

Several months ago, I was encouraged by George Doubinski to contribute to his blossoming CRM Wiki project, crmwiki.net.  At the time, the only thing I had to contribute was a list of CRM Development Resources which I had compiled into Microsoft’s public CRM forums.  The content was moved rapidly, and in the spirit of encouraging more utilization of the Wiki by the community, I removed my listings from the thread.

Now, George has taken the Wiki a step further by contacting the TechNet Wiki Advisory Board about making some space within their Wiki for CRM.  They seemed altogether pleased with the idea, and George then enlisted the help of myself and Neil Benson, to kick-start the Wiki space.  This seems to be a fantastic endeavor upon which the whole community can build knowledge surrounding CRM, and I wholeheartedly support it.

My first project within the new Dynamics CRM Wiki, will be to post the first revisions to the Dynamics CRM Survival Guide.  Hopefully, the community will be able to help me fill it in.  At the very least, however, it should serve as a fantastic starting point for people who are newcomers to Microsoft CRM!

CRM Entropy - A Microsoft CRM Blog: A Call-To-Arms For CRM Experts!

The CRM Community needs your help!  A new wiki has been established at TechNet Wiki for CRM.  While the principal pages have been setup, Neil Benson, George Doubinski, and I need your help in filling it in with content.  To that end, I’ve created a CRM Article Recommendations page with a list of topics I’d personally like to see deployed to the wiki.

Even if you’re not an author, or contributor, we’d be happy to find your article recommendations within that space.  Afraid to edit a wiki?  Don’t fret.  You can tweet your recommendations @crmwiki for good measure! 

Since activity within the wiki counts as community contribution, it may be a great way to not only secure the renewal of MVP status, but to obtain it for aspiring experts!  While many CRM MVPs are birthed from the flames of the CRM Forums, I’m excited at the prospect that some may yet come from the CRM Wiki.

I can’t enumerate how many times I’ve posted responses in the CRM Forum that refer to older threads.  If that practice could be replaced by references to a live and active wiki, I believe the whole community stands to benefit.  So, I openly encourage existing MVPs and CRM experts alike to join in welcoming and contributing to the new wiki.  And for those who become involved: thank you!

CRM Entropy - A Microsoft CRM Blog: Slowly Getting Back

For those who have been concerned about the well-being of my daughter, please know that things are doing tremendously well.  Her treatment is far from over, but the chemotherapy portion is nearly complete and a recent surgery was successful at removing 90-99% of her existing mass.  Other treatments remain, but we remain very hopeful due to her resilience thus far.

I’ve been working at night on freelance work for George Doubinski, and have been picking up Silverlight as quickly as possible.  One thing that disappointed me was the dearth of information regarding Silverlight development in CRM 4.  Considering the maturity of both product lines, I would have thought them to have been married much sooner than CRM 2011.  To that end, I’ve decided to participate in CRMUG’s 10@10of10 presentation series and bring what I’ve learned to those of us who haven’t quite moved into CRM 2011 yet.  CRMUG membership is required to attend.

I’m still working up the presentation content, but I’m hoping to have a sensible development example for producing Silverlight code that works for both CRM 4 and CRM 2011.  At any rate, I expect to reproduce the contents and code from the presentation upon this blog; so if you can’t attend the Live Meeting, be sure to check back in the following weeks.

Aside from that, I’ve decided to apply some theme changes to the blog to encourage me to post a little more often.  I’m certainly looking forward to producing more CRM 2011 resources (while bringing forward as many of the CRM 4 developments as are suitable).  However, the pace will be crawling for a while.  Some of you may have seen more recent involvements from me in the CRM Development forum.  Indeed, that’s a pretty good indicator of my free time, because that’s where I spend it.

CRM Entropy - A Microsoft CRM Blog: Silverlight and CRM 4

[UPDATE:  A demonstration of this code can be found in a follow-up post.]

My presentation this morning at CRMUG’s 10@10of10 went pretty well, I thought.  There weren’t too many attendees, though.  I can’t say I blame anyone for that.  In my experience, very few jump with glee for a chance to look at code.

Since the format was limited to 10 minutes, I obviously had to truncate a great deal of the information I wanted to provide.  It’s funny, because at first I wondered what I’d fill 10 minutes with.  Those who attended will likely visit this space to retrieve what I promised:  the code.  So, without further ado:

The Code
<heavenly chorus>

using System; using System.Collections.Generic; using System.ComponentModel; using System.ServiceModel; using System.ServiceModel.Channels; using System.ServiceModel.Description; using System.ServiceModel.Dispatcher; using System.Runtime.Serialization; using System.Xml;  namespace CrmSDK { public partial class DynamicEntity { private Dictionary<string, Property> namedProperties;  [System.Xml.Serialization.XmlIgnore] public Dictionary<string, Property> NamedProperties { get { return namedProperties; } set { namedProperties = value; this.RaisePropertyChanged("NamedProperties"); } }  public DynamicEntity() { this.PropertyChanged += new PropertyChangedEventHandler(dynamicEntity_PropertyChanged); }  private void dynamicEntity_PropertyChanged(object sender, PropertyChangedEventArgs e) { if (e.PropertyName == "Properties") { NamedProperties = convertPropertyArray(this.Properties); } }  private static Dictionary<string, Property> convertPropertyArray(Property[] properties) { Dictionary<string, Property> propertyDictionary = new Dictionary<string, Property>();  for (int propertyIndex = 0; propertyIndex < properties.Length; propertyIndex++) propertyDictionary.Add(properties[propertyIndex].Name, properties[propertyIndex]);  return propertyDictionary; } }  public class CrmServiceConnectionParams { public String Scheme { get; set; }  public String Url { get; set; }  public CrmAuthenticationToken AuthenticationToken { get; set; }  public BasicHttpSecurityMode SecurityMode { get; set; }  private void setSecurityModeFromScheme() { switch (Scheme) { case "https": SecurityMode = BasicHttpSecurityMode.Transport; break; default: SecurityMode = BasicHttpSecurityMode.None; break; } }  public CrmServiceConnectionParams(String url, CrmAuthenticationToken token) { if (url.Contains("://")) { string[] urlSplit = url.Split(new string[] { "://" }, StringSplitOptions.None);  Scheme = urlSplit[0]; Url = urlSplit[1]; } else throw new ArgumentException("Failure creating CrmServiceConnectionParams instance. Invalid or missing URL scheme (e.g. 'http://').");  AuthenticationToken = token;  setSecurityModeFromScheme(); }  public CrmServiceConnectionParams(String scheme, String url, CrmAuthenticationToken token) { Scheme = scheme; Url = url; AuthenticationToken = token;  setSecurityModeFromScheme(); }  public CrmServiceConnectionParams(String scheme, String url, CrmAuthenticationToken token, BasicHttpSecurityMode securityMode) { Scheme = scheme; Url = url; AuthenticationToken = token; SecurityMode = securityMode; } }  public class CrmServiceInstance { private CrmServiceConnectionParams connectionParams; public CrmServiceConnectionParams ConnectionParams { get { return connectionParams; } set { connectionParams = value; spawnCrmService(); } }  private CrmServiceSoapClient crmService; public CrmServiceSoapClient CrmService { get { return crmService; } set { crmService = value; isCrmServiceReady = true;  if (OnCrmServiceReady != null) OnCrmServiceReady(this, new EventArgs()); } }  #region OnCrmServiceReady Event  public event EventHandler<EventArgs> OnCrmServiceReady;  private bool isCrmServiceReady; public bool IsCrmServiceReady { get { return isCrmServiceReady; } }  

CRM Entropy - A Microsoft CRM Blog: I’m a Microsoft MVP! (Still)

It’s surprising to me to think that a year ago, I was welcomed graciously into the arms of the MVP program.  Mostly, because this year seems to have just flown by.  Awaiting news of my renewal status caused even more anxiety than I had last year, because my daughter’s illness dropped my activity level in the community quite a bit.

I tried desperately to find time to contribute as often as I could, so that I might secure my MVP renewal—and it appears those efforts paid off.  Soon, our daughter’s treatments will be largely over, and things brought to a more stable and relaxed atmosphere around the home.  This is exactly the situation I need to move forward with CRM 2011, and really make a return to the forums a stronger developer for it.

Thanks to Microsoft, Melissa (my MVP team lead), and the many MVPs whom I’ve come to know on a personal level over the last year.  I promise to make the MVP Global Summit this year to make up for last year.

CRM Entropy - A Microsoft CRM Blog: Silverlight and CRM 4 (continued)

[UPDATE: The conclusion of this series is up, and in it I discuss the code and break-down how I developed it and why it works the way it does.]

I promised in my last post on the subject that I would include an example of the code I presented during my CRMUG 10@10of10 segment.  Then, I went to delay that example for a couple of weeks while I was looking for a good time to produce it.  Well, today was that day.

For starters, the example code is hosted at CodePlex.  I put the project together in Visual Studio 2010, so the solution and project files will all reflect that.  Also, you will need the Silverlight 4 Tools for VS 2010 and the Silverlight 4 for Developers Runtime to open the project files.  Head on over there to download it, decompress it to your favorite demonstration code directory, and come back here for the instructions on putting it together.

Putting It Together

First, download the WSDL from a CRM deployment you would like to compile the project against.  I personally prefer a “vanilla” deployment of CRM to keep the WSDL small, and rely on DynamicEntity to perform all the dirty work for me—however that is not necessary for this sample project (in fact, I don’t use DynamicEntity at all in it, though my special “NamedProperties” extension is available to the project for your own tinkering amusement).

1 - Customization

2 - Download WSDL

3 - Download WSDL for CrmService

4 - Download WSDL for CrmService - Save As

Save the resultant XML file somewhere easy to locate, such as the root folder for our project.

5 - Save WSDL as Xml File

Open the solution in Visual Studio, and add a “Service Reference” to the Simple CRM App project.

6 - Add Service Reference

Be sure to specify the XML file location as the “Address” and then click Go.  Upon a successful load, the “Services” frame will contain an item titled “CrmService”.  Specify the “Namespace” value as CrmSDK.  Click OK when finished.

7 - Add Service Reference - Location and Namespace

Next, add a “Reference” to the Simple CRM App.Web project.

8 - Add Reference

Locate and select the assembly microsoft.crm.sdk.dll from the CRM 4 SDK.  Click OK.

9 - Add Reference - CRM SDK

Now, build the whole solution.

To deploy the project to CRM, create this new folder:

<crm web root>/ISV/SCA

In this folder place the following files from the Simple CRM App.Web project folder:

Silverlight.js
SimpleCrmApp.aspx
ClientBin/Simple CRM App.xap  (copy the folder)

Deploy this file:

Simple CRM App.Web/bin/SimpleCRMApp.Web.dll

Into the following location:

<crm web root>/bin/

Now, in order to view the project, export your SiteMap.xml from the customizations, and insert this code into some reasonable area

<SubArea Id="SimpleCrmApp" PassParams="1" Url="/../ISV/SCA/SimpleCrmApp.aspx" AvailableOffline="false">
  <Titles>
    <Title LCID="1033" Title="Simple CRM App" />
  </Titles>
  <Descriptions>
    <Description LCID="1033" Description="A simple Silverlight demonstration." />
  </Descriptions>
</SubArea>

Import the altered SiteMap.xml, and refresh your CRM window to view the changes.  Upon clicking on the new navigation item, you should be treated to a very basic Silverlight page that shows a list of all active accounts by name.

I’ll get into the details of the code a little more with another post to follow within a day or two.

CRM Entropy - A Microsoft CRM Blog: New Twitter Feed

As you may notice, on the right-side of this blog is now a small reproduction of a twitter feed I setup for this blog, and for other CRM related goodness.  Many MVPs engage in Twitter, and a few have asked me to use it to broadcast blog updates.  Apparently RSS and Atom up and died since last I checked.

Anyway, new posts will be dropped in that space as well, if you’re keen to follow that kind of thing.  Another post will be coming tonight to complete the “Silverlight and CRM 4” trilogy.  Stay tuned.

CRM Entropy - A Microsoft CRM Blog: Silverlight and CRM 4 (continued, again)

When I delivered the code example in my last post on the subject, I knew that it would probably be worthwhile to pick apart the individual code elements in order to provide a better understanding of what’s going on underneath it all.  This marks the final chapter of the saga which started as a 10-minute presentation, and culminates about 40-hours of work.

Again, this subject matter all stems from my participation in CRMUG’s ongoing 10@10of10 series.  To date, I’ve slept in too long to catch any of the other presentations live—for that I apologize to the other presenters, because I really am interested in their content matter.  Problem is, I’ve been up until 4 A.M. most mornings doing freelance work, or dealing with other things.  Thankfully, CRMUG will be posting the session recordings to their site—or so I’m told.

The code I will present will be in snippets from the Simple CRM 4 Silverlight Application project that I’ve uploaded to CodePlex.  If you didn’t already download it to build the application for yourself using my last post’s instructions, you’ll probably want to do so now for what follows.  (You will also need the Silverlight 4 Tools for VS 2010 and the Silverlight 4 for Developers Runtime to work with the project files.)

What follows: A Silverlight primer

Ok, so… first thing’s first:  If you’re inexperienced with Silverlight, I recommend the Silverlight Jumpstart book by David Yack (downloadable as a PDF).  It serves as a pretty good primer for working with Silverlight in general.  I used it, and found it very informative and useful. 

Mr. Yack also wrote another book, CRM as a Rapid Development Platform that contains a chapter on Silverlight development for CRM.  I also found that chapter useful in my project, but diverged from his examples by using the WSDL for web-service interaction.  His point about WSDL bloat upon the final XAP file are valid, and should be considered when developing smaller, single-purpose products.  However, for richer and fuller Silverlight apps, I find the WSDL to be integral to the speed of development.

I’m not going to get into the ins-and-outs of Silverlight development.  There’s too much to cover for this space, and I will simply proceed under the assumption that you, the reader, will find this knowledge for yourself and use it to obtain an understanding from what follows.

What follows: Connecting to CRM

There are two things necessary to connect Silverlight to CRM:

  1. knowing the service endpoint and authentication method1
  2. having an asynchronous interface to the endpoint methods3

For ease of use within the context of the ISV folder, I split these requirements across two projects, respectively:

  1. an ASPX host page for the Silverlight control
  2. the WSDL in the Silverlight application

Because Silverlight must ultimately satisfy both requirements internally, there is a third, intermediary requirement caused by my division of responsibility:  passing service endpoint and authentication information from the host page into Silverlight2.

Knowing the service endpoint and authentication method

Because I decided to use an ASPX page and code-behind file to meet this requirement, the process is decidedly simple, and is explained best in these snippets of code:

SimpleCrmApp.aspx.cs (line 35):
serviceUrl = this.Request.Url.Scheme + "://" + this.Request.Url.Host + "/MSCRMServices/2007/CrmService.asmx";

The snippet above uses the Page.Request member to assemble relevant components of the scheme used to view the page (“http” or “https”), and the hostname.

SimpleCrmApp.aspx.cs (lines 19 and 38):
orgName = Request.QueryString["orgname"];
//... jump over code
CrmAuthenticationToken token = CrmAuthenticationToken.ExtractCrmAuthenticationToken(Context, orgName);

The snippet above shows how the code-behind grabs the value of “orgname” from the same Page.Request to complete our ExtractCrmAuthenticationToken() method call.  This parameter must be passed to the host page somehow.  In our example, we accomplish this in this part of the SiteMap.xml configuration:

SiteMap.xml:
<SubArea Id="SimpleCrmApp" PassParams="1" Url="/../ISV/SCA/SimpleCrmApp.aspx" AvailableOffline="false">

Here, we rely on PassParams to do our dirty work for us.

Now, you might be misled into thinking that the token would be sufficient for Silverlight to authenticate its own SOAP messages.  Many in the forums have.  The reason you would be wrong is that the ExtractCrmAuthenticationToken() method provides you with the CrmAuthenticationToken instance used by CRM’s platform to communicate with the web service endpoints.

As I previously explained, this poses a problem because this token is designed to always operate under two conditions:

  1. Use to communicate with SOAP under a CrmImpersonator() call, which removes impersonation from the thread, thereby bringing “SYSTEM” user network credentials for use with…
  2. Integrated Authentication

It’s important to note that the reason token won’t work for Silverlight in strictly Integrated Authentication environments is because of the presence of the CallerId value. Any time this value is not Guid.Empty, CRM assumes impersonation is taking place, and checks the credentials for membership in the PrivUserGroup.  Because CRM does not communicate with itself over IFD, the CrmAuthenticationToken provided with always have an AuthenticationType of “0” and will never contain a CrmTicket.

When authenticating via IFD, you must supply a value for CallerId.  That’s what explains this bit:

SimpleCrmApp.aspx.cs (line 40):
callerId = token.CallerId.ToString();

Finally, I need a sensible way to determine if CRM is being used in an IFD scenario or not.  I could go the complicated way, parsing the URL to find out if the hostname has the orgname in it—but that’s a lot of code.  A more elegant way, is to look for the browser-cookie “MSCRMSession”:

SimpleCrmApp.aspx.cs (line 28):
// A broadly applicable mechanism for detecting IFD is the presence of the MSCRMSession cookie
if (Request.Cookies["MSCRMSession"] is HttpCookie)
    authType = "2";
else
    authType = "0";

Fun, huh?

Here’s why “MSCRMSession” is also important: it contains the value of the CrmTicket.  See, whenever the browser is authenticated via IFD, it uses a browser-cookie (which is inaccessible through JavaScript or Silverlight) to hold this ticket value.  The nice thing is, that it’s passed in every HTTP request header that originates from the browser (including Silverlight) to its domain of origin.  Therefore, we do not need to worry about finding it or passing it through the headers of our own SOAP requests.

Notice how every value I’m taking is ending up in string format?  Well that leads into the next requirement.

Passing service endpoint and authentication information from the host page into Silverlight

There are a handful of ways to obtain data from a Silverlight application’s hosting page:

  • Inspect the DOM.
  • Call a JavaScript function.
  • Use InitParams.

I’m sure there are others I’m unfamiliar with, but let me tell you why I choose the InitParams: it’s easy, and it’s a one-way stream into Silverlight that doesn’t require any backward movement by the Silverlight app into its execution context.  It simply doesn’t care.  In fact, if I had some other way that I would like to instantiate my Silverlight app in a wholly different context, I could rely on data passed into InitParams to define its operation.

To achieve this, there are two code-snippets on the server side, and one on the Silverlight side to illustrate how this works:

SimpleCrmApp.aspx (line 69):
<param name="initParams" value="<%= BuildInitValue() %>" />

The snippet above, from the <object> container for the Silverlight control, instructs Silverlight to receive the value and pass it into the Startup event arguments.  To construct the value, I have this function:

SimpleCrmApp.aspx.cs (lines 43 – 47):
protected string BuildInitValue()
{
    // build a series of parameters to be piped into the Silverlight app from the hosting control page
    return "callerId=" + callerId + ",orgName=" + orgName + ",serviceUrl=" + serviceUrl + ",authType=" + authType;
}

Since the values are being embedded into the host page by this function, I need to work with strings—which flows from the code in the first requirement.  Then, it’s a matter of examining the values from the Startup event arguments in Silverlight:

App.xaml.cs (lines 30 – 34):
if (e.InitParams == null ||
    e.InitParams["callerId"] == String.Empty ||
    e.InitParams["orgName"] == String.Empty ||
    e.InitParams["serviceUrl"] == String.Empty)
    throw new ArgumentException("This Silverlight application requires values for callerId, orgName, urlScheme, and serviceUrl parameters.");

The snippet above occurs as the first statement in the handler Application_Startup(), which has been attached to the Startup event of the Application class in my custom constructor:

App.xaml.cs (line 20):
this.Startup += this.Application_Startup;

As you can see, the type StartupEventArgs (and its instance, e) expose the member InitParams, from which I obtain the values I submitted from the hosting page via its implementation of IDictionary.

So, now what?  Well, since we have all of the necessary information to connect to CRM, it’s time to start working with the code from my first post.

Having an asynchronous interface to the endpoint methods

Since I have all the information I need to connect to CRM within the Application_Startup() call, I refrain from storing the information and instead use it immediately to construct an instance of my CrmServiceInstance class:

App.xaml.cs (lines 36 – 51):
// Construct a new CrmAuthenticationToken from some of the InitParams elements
CrmAuthenticationToken authToken = new CrmAuthenticationToken();
 
authToken.AuthenticationType = Convert.ToInt32(e.InitParams["authType"]);
 
// This is an important piece for determining proper IFD communication
if (authToken.AuthenticationType != 0)
    authToken.CallerId = new Guid(e.InitParams["callerId"]);
else
    authToken.CallerId = Guid.Empty;
 
authToken.OrganizationName = e.InitParams["orgName"];
 
// Create a new CrmServiceInstance and assign a new CrmServiceConnectionParams object to its ConnectionParams member
CrmServiceInstance crmService = new CrmServiceInstance();
crmService.ConnectionParams = new CrmServiceConnectionParams(e.InitParams["serviceUrl"], authToken);

In the snippet above, you can see that I’m constructing a new CrmAuthenticationToken object, with all the various input received through InitParams.  I then pass this and the endpoint URL (also taken from InitParams) to the ConnectionParams member of crmService

Because I perform these immediately upon the application startup, I have no need to examine the IsCrmServiceReady member or attach any handlers to the OnCrmServiceReady event—it is simply ready for me to proceed.  However, I put an example of how this might be performed in this code snippet from the MainPage_Loaded() event handler:

MainPage.xaml.cs (lines 42 – 46):
// Validate the readiness of the crmServiceInstance before proceeding further; use an event handler to work out the kinks
if (!crmServiceInstance.IsCrmServiceReady)
    crmServiceInstance.OnCrmServiceReady += new EventHandler<EventArgs>(crmService_OnCrmServiceReady);
else
    crmService_OnCrmServiceReady(this, new EventArgs());

Where this event is handy, is if I had created my CrmServiceInstance in XAML—rather than directly in the code, as with this example.

From here, I pass crmService into the customized constructor for my MainPage class.  Once this is done, a connection to CRM has been adequately defined and is now available for my Silverlight page, MainPage, to use for what follows.

What follows: Using CrmServiceSoapClient

Because Silverlight requires web-service interaction to operate in an asynchronous way (for non-interfering performance reasons), all of the traditional methods from [I]CrmService are implemented in CrmServiceSoapClient with an “Async” suffix.  Execute() becomes ExecuteAsync(), and RetrieveMultiple() becomes RetrieveMultipleAsync(), for example.  Working with these asynchronous counterparts can be perplexing, considering that they all have no return.

The returns are provided through events.  Each traditional method not only has an “Async” representation in Silverlight, but also a “Completed” event; ExecuteCompleted and RetrieveMultipleCompleted, for example.  This means that every method call to the web-services is handled by every active event handler registered to these events.  This can complicate the design of your Silverlight application, to a degree—given that:

  1. You should always have the event handler in place before the method is called; and
  2. Every event handler will catch every execution of the method for the same CrmServiceSoapClient instance

For our example, however, all I need is a simple, one-time query for all active Account names.  I achieve that with the following code in the crmService_OnCrmServiceReady() method (again, this method is an event handler for the CrmServiceInstance.OnCrmServiceReady event, and is not needed by the code, but provided for example purposes):

MainPage.xaml.cs (lines 51 – 66):
// Query for active accounts
QueryByAttribute query = new QueryByAttribute();
query.EntityName = EntityName.account.ToString();
query.Attributes = new string[] { "statecode" };
query.Values = new object[] { 0 };
 
// Query three specific string columns
ColumnSet columns = new ColumnSet();
columns.Attributes = new string[] { "name" };
 
query.ColumnSet = columns;
 
// Assign a handler to deal with the results, before triggering the execution of the query
crmServiceInstance.CrmService.RetrieveMultipleCompleted += new EventHandler<RetrieveMultipleCompletedEventArgs>(CrmService_RetrieveMultipleCompleted);
 
crmServiceInstance.CrmService.RetrieveMultipleAsync(query);

Note that one statement before I call RetrieveMultipleAsync(), I attach the handler CrmServce_RetrieveMultipleCompleted() to the RetrieveMultipleCompleted event.  I do this to prevent any possible—though unlikely—race condition by which the thread processing the “RetrieveMultiple” message might finish and trigger the event, before the event handler is assigned.

So, interpreting the return is an important function of CrmService_RetrieveMultipleCompleted().  Here’s the body of that method:

MainPage.xaml.cs (lines 69 – 82):
void CrmService_RetrieveMultipleCompleted(object sender, RetrieveMultipleCompletedEventArgs e)
{
    // Instantiate a new List<account> for our results
    List<account> retrievedAccounts = new List<account>();
 
    // Assign the results of our query to the new List
    foreach (account a in e.Result.BusinessEntities)
    {
        retrievedAccounts.Add(a);
    }
 
    // Push the results into our RetrievedRecords data context
    RetrievedRecords.AccountRecords = retrievedAccounts;
}

As you can see, RetrieveMultipleCompletedEventArgs (as an instance, e) has a Result member that contains our retrieved records, much the same way as the traditional RetrieveMultipleResponse would.

The rest of my code operates the way a basic Silverlight application should when pushing data to the view.  To make a long story short, I use a “ViewModel” for the data, represented by a collection of DisplayAccount.  These are handled by the class CrmRecords, which serves as the type for the RetrievedRecords member of MainPage.  These serve as abstractions of the account type to limit the amount of columns automatically generated by the DataGrid.

What follows:  Bed Time

Ok, I’ve been up late working on this post.  Time for bed.  Hopefully, it all makes sense.  Comment below if you have additional inquiries.

CRM Entropy - A Microsoft CRM Blog: Unexpected Benefits of an MVP Award

So, today I started work for my new employer, JourneyTEAM, a Microsoft Gold Partner and Microsoft Dynamics shop.  They’re a smaller outfit with a close-knit group of gurus, code-monkeys, and sales experts with whom I’m excited to now be allied.

I was contacted 3 weeks ago by a 3rd-party talent-sourcing firm looking for CRM Developers in the Salt Lake City area.  Because I’m not one to turn down a good opportunity, I explored what JourneyTEAM had to offer.

Aside from a welcome increase in pay, the chief benefits that I expect to receive with JourneyTEAM are as follows:

  1. Broader exposure to industries utilizing CRM
  2. Developing with a “TEAM”
  3. Incentive to maintain MVP status
  4. Microsoft certification classes and exams
  5. No more IT support

The last one is a particularly poignant one for me.

See, I started down the path of my development career some 11 years ago.  Then, I worked at the lowest rung on the IT ladder:  Internet Helpdesk.  Fresh out of high-school, and with a passion for programming that I’d fostered since the age of 12, I knew I had to find work with computers.  Since then, programming has taken an increasingly important role in my jobs, starting with helpful personal utilities and culminating most recently in heavy CRM customization and development for BC Technical.

All the while, however, I maintained no less than 80% of my job description founded in IT: from server and network maintenance, to RAID building and desktop software support.  I was, and probably will remain, a competent and proven IT professional.  But it was never my love, as development is.  Sure, I am good at IT, and will be uniquely posited to utilize that experience in venturing forward into the future with JourneyTEAM—but I will not lose an ounce of sleep if I never have to see a BIOS flash utility, Excel formula problem, or unpowered monitor ever again.

So, for those who I have turned down in the past for consulting and development work—due to my personal time constraints--now is your opportunity to reconsider my involvement.  Please contact me at JourneyTEAM about your needs, and I’ll happily involve myself in every capacity I am able.

To my old employer, I bid you farewell and believe that our paths will cross again soon—I do miss you all!

To my new employer, watch out!  I come ready to get things done and get them done right.

CRM Entropy - A Microsoft CRM Blog: Changing Product Unit Groups

I ran into a situation where a large list of Products had been imported into CRM 2011, but the Unit Groups for many of them needed to be changed after the fact.  As many have discovered, even though the form customization options for the Product entity professes that the field is not flagged as “read only”, the field is in fact “read only” when Products are opened.

The workaround is fairly simple, but comes with some caveats:  export the records to an Excel spreadsheet with the option “Make this available for re-importing by including required column headings” selected.  You must export both the Unit Group field and the Default Unit field.  In spreadsheet form, you can alter the Unit Group and the Default Unit.  Now, here’s the caveats:

  1. The Default Unit must be uniquely named.  Multiple Units with identical names (in any Unit Group) will cause the import to fail, because it does not look for the Unit in a specific Unit Group.  The failure is because CRM cannot properly resolve the Unit, due to name duplication.
  2. Beware of any Price List Items configured to use the old Units configured for this Product.  I don’t know what CRM will do to you if you try to use the Product in a Quote/Order/Invoice after you change its Unit Group in this way.

When you import the changed data, you should notice that the modifications to the Unit Group (and Default Unit) values have been properly changed.

[Update:  Astute reader, Jevgenij, notes that the following Microsoft KB will also allow you to work around the problem using the Bulk Edit feature: http://support.microsoft.com/kb/949941  This is particularly useful for CRM administrators.  The process above, however, will work for anyone with access Product catalog maintenance.]

CRM Entropy - A Microsoft CRM Blog: Copying Lookup Values

Very recently a poster in the CRM Development forum asked why she could not copy the value from a Contact Lookup field into the “To” field of a Phone Call entity.  On the surface, her code was very simple and would largely be expected to work.  What ended up working was basically creating a new value for the PartyList that recreated values from the Contact Lookup.

Why was this necessary?  I don’t really know, and haven’t looked any deeper into CRM 2011 yet, but what I know from CRM 4 is that certain expressions of the DataValue for a Lookup field can contain extra, undocumented data elements.  I suspect that CRM 2011 has expanded the use and perhaps number of these undocumented data elements, and their presence from one Lookup field prevents the direct assignment of the value to another Lookup field.

Perhaps this is limited to Single-to-PartyList copies, but perhaps not.  Either way, I’ve whipped up a handy function that can help easily copy or append values into Lookups when those values are taken from other Lookups.  Also, it allows you to provide a delegate function to which it will pass each entity reference and expect a boolean indication as to whether or not the value should be accepted for inclusion in the target attribute.

function CopyLookupValue(sourceAttribute, targetAttribute, boolAppendSource, funcDelegate)
{
var sourceValue = sourceAttribute.getValue();
var newValue = [];

if (typeof boolAppendSource != "undefined" && boolAppendSource)
{
sourceValue = targetAttribute.getValue().concat(sourceValue);
}

foreach(var valueIndex in sourceValue)
{
var copyValue = true;

if (typeof funcDelegate == "Function")
{
copyValue = funcDelegate(sourceValue[valueIndex]);
}

if (copyValue)
{
newValue.push({
id: sourceValue[valueIndex].id,
name: sourceValue[valueIndex].name,
entityType: sourceValue[valueIndex].entityType});
}
}

targetAttribute.setValue(newValue);
}

Using the thread that initiated this code as an example, here is how the above code would be used to copy the value of a Contact field on a parent form window to a To field on the child form window:

var remoteAttribute = window.parent.opener.Xrm.Page.data.entity.attributes.get("bc_contact");

CopyLookupValue(remoteAttribute, Xrm.Page.getAttribute("to"));

CRM Entropy - A Microsoft CRM Blog: Ask the MVP (CRMUG)

There’s an upcoming roundtable event, hosted by CRMUG, where many CRM MVPs have agreed to come together and address questions submitted to the “Ask the MVP” event site.  After the bulk of the event, I understand there will be time afterward for free-form, open floor discussion and Q&A.  However, if you want to make sure your question is asked, drop an email to Janet Lampert or Donna Edwards well in advance!  As with most CRMUG events, attendance is limited to CRMUG members—become a member today, and reap the benefits.

I’m personally excited to get involved in this event, since this is the second CRMUG event to which I’ve been invited to participate.  Hopefully, I am more useful to the discussion than a fly-on-the-wall.  Many long-time MVP greats will be coming to the table, and I’m honored to find myself among them.  We haven’t seen the question list yet, so I’m anxious to find out what you, the audience, want to know!

CRM Entropy - A Microsoft CRM Blog: DOM Events and CRM 2011

Recently, another MVP asked in a private forum how one might connect to the “onclick” event of a CRM field.  With the new Xrm.Page namespace object model, it seemed that all references to the actual DOM element of the control were lost (or at least, very well hidden).  Well, I did some poking around, and I discovered two things:

  1. Xrm.Page lives only within the scope of web-resources and their execution (wherever and however they are scripted to occur); this means that the old days of firing up the IE Developer Toolbar to hack CRM on-the-fly are gone.
  2. The DOM elements are buried in undocumented members of the control object (as opposed to the attribute object).  As a consequence, the following hack is unsupported, but also much easier to implement than the supported method of using a Web Resource to present your own custom controls that drive, in the background, CRM’s native controls.

So, here’s the method I found to achieve access to the DOM element control container, and how to assign a new “onclick” handler to it:

var controlname = "ownerid"; // The "Owner" field, as an example

function myFunction ()
{
alert("I have been clicked");
}

Xrm.Page.getControl(controlName)[“_control”][“_element”].attachEvent(‘onclick’, myFunction);

Wasn’t that easy?

CRM Entropy - A Microsoft CRM Blog: CRM 2011 and WSDL

CRM 2011 makes a dramatic change with the WSDL implementation compared to CRM 4.0.  The biggest difference?  The WSDL file you download is not a full definition of the service (for either Discovery or Organization). 

Instead it’s a very small and self-conscious (“lightweight”) WSDL that points back to the same service (and host) with an import directive for the full WSDL.  What does this accomplish?  Well, WSDL-imports are supposed to allow a WSDL definition to be modular with reusable and multi-authored definitions.  We really don’t see that being applied in CRM’s case in any sensible fashion (like importing out-of-the-box entity/attribute definitions separately from custom ones, or importing WSDLs with Solution-based scopes).  All it seems to do is complicate the retrieval of information we need for our application.

So, if you prefer or require the late-bound Entity class, and you don’t have local access to a CRM system.  Having a “full” WSDL file could help when you want to avoid…

  1. …deployment of the CRM DLLs.  This may be important when single-assembly functionality is imperative and assembly dependency deployment is a serious headache, such as CLR operations from SQL for integration projects.  Or maybe the target system doesn’t use or support .Net.
  2. …the code-generation tool.  Let’s face it, the code-generation tool is nice for simple and quick developments, there’s no argument about the excellence of many of its Utility methods.  However, it produces a lot more code than many will ever use—artificially inflating the assembly size unnecessarily.  And the code it produces isn’t without its own bugs.  Sometimes keeping things simple is its own reward.

So, when you need to have the “full” WSDL file, for your services, use links formatted like so:

Discovery Service

http[s]://<crmServer>/<crmOrg>/XRMServices/2011/Discovery.svc?wsdl=wsdl0

Organization Service

http[s]://<crmServer>/<crmOrg>/XRMServices/2011/Organization.svc?wsdl=wsdl0

CRM Entropy - A Microsoft CRM Blog: Review: CRM 2011 Administration Bible

Publisher: Wiley
Authors: Matt Wittemann, Geoff Ables
CRM Entropy Rating (in Baked Goods): 3.1415926535897

Matt, a fellow CRM MVP, sent me a copy of this book a long time ago, and I’ve pretty much only used it for reference material here and there until recently.  I’ve read a handful of CRM 4 books in my day, and found a great deal of helpful information from them.  The Microsoft Dynamics CRM 2011 Administration Bible marks my first in-depth read relating to CRM 2011.

The title of this book is both accurate and misleading—and I don’t mean from a theological standpoint.  (Though I imagine, given the apologist forewords by Matt and Geoff, the word “God” was uttered on multiple occasions with various modifiers during its authoring.)  This book is indeed a Bible in the sense that it combines a complete picture of CRM, from URL to SQL, from Form to Filter, and from Dialog to Migration.  It really has it all.

However, don’t let the word “Administration” throw you for a loop.  This book isn’t geared specifically for administrators of any kind, and it doesn’t just cover administration.  It’s so thoroughly educational on the core processes of CRM, I dare say that it is the first and last book you’ll need for Microsoft Dynamics CRM 2011 (see my “Bible” comment above).  Matt and Geoff take special care to make every reader an Administrator.  And that’s why the damn thing is so thick!  (Caution: Ordering more than 3 of these books at a time involves freight charges.*)

The machines with which this Bible was written have long surrendered their keyboards to a higher power.  The material is dense and enriching not only for newcomers to the CRM experience, but for those arriving to CRM 2011 looking for what changed from the previous version—like myself.  As with a religious text, you’ll find yourself engaged in the index or table of contents quite a bit, if you’re working with CRM already.  But, you will find value throughout the areas you don’t think you need to read.

This book will teach you all of the standard features that come with Dynamics CRM out-of-the-box, and then open your mind to the possibilities of custom enrichment.  It wouldn’t be a book to buy if you’re only investigating Dynamics CRM (though it wouldn’t hurt to read); but it is an essential part of any CRM implementation, and its material is useful to every deployment and use of CRM that I can think of.

So, from this digital pulpit, I preach from one Bible, and that is the Microsoft Dynamics CRM 2011 Administration Bible!  If you have Dynamics CRM, do yourself a favor and have this book, too.

* I’m kidding!  But really, you do get more words for your dollar… and the most helpful ones to boot!

Link building Aims to Create Your Reputation : Useful and interesting web sites


Search Engine Optimization is the way of increasing your websites visibility for the relevant keywords that are related to your business. Its goal is simply to make the internet an accessible addition to all kinds business so that they can be successful. This can truly and only be achieved by mastering the techniques of link building. Link building if done in the appropriate manner tends to boost up your rankings over the internet and especially around search engines. This way you get more traffic and unique visitors which in turn create opportunities for future business.

Link building is a hyper active task which requires complete focus and understanding on how the search engine algorithms and robots operate. The main of these people involved is to find new techniques and ways to evolve the needs of the clients.

Why Do You Use SEO techniques such as link building:
Search engines out perform all other types of media in driving traffic to websites and 85% of the people opt for these search engines to increase their website visitors. These engines divert the best quality traffic as the people are really looking for product, service and solution.

The Reason you opt for Search engine Optimization is that 93% of people don’t look beyond the first page when browsing the net, so how can you possibly expect people to visit your website. Link building creates opportunities for your site to come on the first page and in this way you can get the maximum chances of good business. Another problem is that people look fro the latest brands and if your product is new and people are not aware of it, so it’s the work of these search engines to create awareness for your product.

Different Services Offered By SEO:
SEO also provide different service to increase and optimize traffic through link building techniques such as Internet Marketing Services. And these internet services further are categorized as:

  • Search Friendly Web Design.
  • Link Exchange Programs.
  • Social Media Optimization.
  • Targeted and search Marketing.
  • Pay Per Click Programs.

There are many available options to choose from and the marketer uses the technique that best suits his product and his requirement. And the aim of all these services is the same that is to increase targeted traffic to boost sales and website ranking, which in turn means creating maximum number of link across the internet. The purpose of all this is to get the required website first page ranking as that’s what we intend to do so that we can compete in this competitive world.

Globalization has created many positive and negative aspects on internet marketing. The positive ones are that we get a chance to choose from a variety of markets and also have the option of choosing the best product according to our need. And the negative aspect is that it has increased the competition in this open market and ha surely implemented the rule of "Survival Of The Fittest".

Thomas Alling runs a blog where he writes about internet marketing and search engine optimization. On his blog, you will also find posts on the popular topic "how to make money online". In addition to this, Mr Alling writes unbiased reviews in the 'make money surveys' niche.