Finally there: Show and hide fields based on the users role!

Hi all,

I've been posting around showing and hiding fields more often. I won't be talking about that now, instead I'll be discussing the ability to perform JavaScript coding based on the users role.

This solution is very neat and very clean, though unsupported!!! Now... Let's get started and dig into this.

MS CRM has a lot of Javascript codes delivered with the product. One of these codes is located here: "/_controls/RemoteCommands/RemoteCommand.js". This file is being included into every page. One of the functions in this file is RemoteCommand(sObject, sCommand, sUrlBase). You can use this function to connect to CRM webservices.

Via Javascript you can get the userid of the currently logged in user via this RemoteCommand. This is done using this code:


var command = new RemoteCommand("SystemUser", "WhoAmI", "/MSCRMServices/");
var oResult = command.Execute();


Another webservice which is interesting is the UserManager webservice. By using this function, you can get all roles of the system. The roles to which the user is assigned are marked with "checked='true'". Here's the code to get this list


var command = new RemoteCommand("UserManager", "GetUserRoles");
command.SetParameter("userIds", "<guid>" + userId + "</guid>");
var oResult = command.Execute();


Now if we add this functionality to functions and add some try catches, then you'll end up with this code:


function getUserId()
{
try
{
var command = new RemoteCommand("SystemUser", "WhoAmI", "/MSCRMServices/");
var oResult = command.Execute();

if (oResult.Success)
{
return oResult.ReturnValue.UserId;
}
}
catch(e)
{
alert("Error while retrieving userid.");
}
return null;
}

function getUserRoles(userId)
{
try
{
var command = new RemoteCommand("UserManager", "GetUserRoles");
command.SetParameter("userIds", "<guid>" + userId + "</guid>");

var oResult = command.Execute();

if (oResult.Success)
{
return oResult.ReturnValue;
}
}
catch(e)
{
alert("Error while retrieving roles.");
}
return null;
}


Now we only have to add functions which checks if the user has a specific role. The final code is:


function getUserId()
{
try
{
var command = new RemoteCommand("SystemUser", "WhoAmI", "/MSCRMServices/");
var oResult = command.Execute();

if (oResult.Success)
{
return oResult.ReturnValue.UserId;
}
}
catch(e)
{
alert("Error while retrieving userid.");
}
return null;
}

function getUserRoles(userId)
{
try
{
var command = new RemoteCommand("UserManager", "GetUserRoles");
command.SetParameter("userIds", "<guid>" + userId + "</guid>");

var oResult = command.Execute();

if (oResult.Success)
{
return oResult.ReturnValue;
}
}
catch(e)
{
alert("Error while retrieving roles.");
}
return null;
}

function userHasRole(userId, roleName)
{
result = getUserRoles(userId);
if (result != null)
{
var oXml = new ActiveXObject("Microsoft.XMLDOM");
oXml.resolveExternals = false;
oXml.async = false;
oXml.loadXML(result);

roleNode = oXml.selectSingleNode("/roles/role[name='" + roleName + "']");
if (roleNode != null)
{
if (roleNode.selectSingleNode("roleid[@checked='true']") != null)
return true;
}
}

return false;
}

function currentUserHasRole(roleName)
{
userId = getUserId();
return userHasRole(userId, roleName);
}


Now you can check for roles by using the code listed down here:

if(currentUserHasRole('Salesperson')){
alert('true');
}else{
alert('false');
}


You can copy and paste the functions as well as the last code in the form onload event. This is not really user friendly / readable though. If you copy and paste the functions to the global.js script instead, then you can use the last code snippet in the form onload.

Now. To get back to the subject "show and hide fields based on the users role"... If you modify the last code snippet to contain the showing and hiding fields as discussed in this article, instead of alert('true') and alert('false'), then you've got a very good customized system.

Thanks go out to Steven Brom (Qurius Advanced Solutions - NL) for supplying the codes!

Update 1: Thanks to Josh Painter who pointed me to the fact that I forgot to replace the < sign with <> in the codes.

Update 2: I mentioned that this solution was supported, but since we're using webservices from MS CRM other then the regular webservice, this is unsupported anyway... But still it's cool ;)

Update 3: This code doens't work on the outlook client. I'm still thinking about a solution to that.

Update 4: The code above is created for CRM 3.0. For CRM 4.0 look at the following blogs:
http://www.crowehorwath.com/cs/blogs/crm/archive/2008/05/08/hide-show-fields-in-crm-4-0-based-on-security-role.aspx
http://jianwang.blogspot.com/2008/01/crm-40-check-current-users-security.html



Hide and show fields based on the logged in user

There have been a lot of requests on how to hide and show fields since my earlier postings regarding hiding and showing fields and rows. John Straumann has written an article about this before. A working solution, but not too nice though.

Here's another solution which is unsupported (ofcourse ;) ), but it gives you a lot more freedom.

So how to tackle this problem. We already know how to hide and show fields. Now wouldn't it be great if we know what user is logged in? We would then be able to say (ofcourse modify the loggedInUser id with the guid of the user you need):


if (loggedInUser == '{123456789-1234-5678-9012-123456789012}'{
crmForm.all.name_c.style.display = 'none';
crmForm.all.name_d.style.display = 'none';
} else{
crmForm.all.name_c.style.display = 'block';
crmForm.all.name_d.style.display = 'block';
}

Now... how do we get that loggedInUser?
This is where it gets quite tricky. You can open the aspx page where you want to use this code. So why not add a little bit of asp coding in there? Lets say you want to use the code on the contact page. Then go to the server and open the "/SFA/conts/edit.aspx" page. Add this piece of code just before another script starts:

<script language="javascript">
var loggedInUser = '<%=Microsoft.Crm.Security.User.Current.UserAuth.UserId%>';
</script>


And now we have the loggedInUser! Save the file, store the javascript in the page onload and publish the contact. You will now have a page special for one user.
You can extend the codes as much as you like. You con for instance change the
Microsoft.Crm.Security.User.Current.UserAuth.UserId
with
Microsoft.Crm.Security.User.Current.IsSysAdmin
.
This all is undocumented and unsupported. Therefore you should only try these kind of modifications if you feel comfortable with this.

Good luck!



Dynamics vision of Bill Gates

Unfortunately I didn't make it to the Convergence 2006. Luckily there are other ways to get the same information as what is given there. Microsoft has posted an article on PressPass regarding Bill's vision for the new generation of Business Solutions that enable people-ready business.

Read the article here.

Most important is that Bill outlined five key and unique pillars to Microsoft's approach to role-based productivity:
- Familiar, Tailored User Experience
- Service-Oriented Architecture
- Integrated Collaboration
- Immediately Insightful
- Rapid Development Composition

Read the article for more detailed information!



Article in .NET Magazine #12

Together with Sahin Ozdemir, one of my direct colleages, I have written an article regarding MS CRM 3.0 for the nr 1 Microsoft Developer magazine in the netherlands: .NET Magazine. Ofcourse all the Dutch readers already have a free (yeah, Dutch people love free things) subscription, otherwise get one now at: http://www.microsoft.nl/magazine !

Back to the topic. We wrote an article, in Dutch, for programmer's. The main topics are:
- Customization tools
- ISV script / Form customization
- ISV code
- Import / Export
- Pre / Post-callouts
- Workflow services
- CRM Reports

A quote of one of the many replies we've got:
"This is the first time that a business application which improves productivity for programmers is exposed in a highly technical magazine on a way which is very interesting for .NET developers. This article does show perfectly what the addition is of Avanade in .NET minded Netherlands!"

Download the article here (Dutch only).



CRM Blog world

Wonderfull thing blogging. I'm doing this now for more then half a year and still am having fun to continue. But more and more blogs are coming up. There's a huge list now of people blogging mostly about MS CRM. So where is this list? Everyone has got some other blogs on their blogroll, but there is no full list. Well. Here's a list of what I think is the complete list of MS CRM blogs at the moment. Starting with the Microsoft people, then MVP's and then the other bloggers. Some blogs are marked with [inactive]. Those are blogs that have mentioned to stop or which do not have any CRM related post for the last half year. Furthermore there's no logic in the ordering. Hope you find some new information which you can use!


Microsoft Bloggers:
MSCRM Team Blog http://blogs.msdn.com/crm
MSCRM Partner Specialist Team West region http://westregioncrm.spaces.live.com/
Andrew Bybee [MS -US] http://bybeeworld.spaces.live.com/
Arash Ghanaie-Sichanie [MS - US] [inactive] http://blogs.msdn.com/arash/default.aspx
Ben Riga [MS - US] http://blogs.msdn.com/benriga/default.aspx
Ben Vollmer [MS - US] http://blogs.msdn.com/midatlanticcrm/default.aspx
Benjamin Lecoq [MS - France] http://blogs.msdn.com/benlec
Bill Patterson [MS -US] http://pattersonwc.spaces.live.com/
Charles Eliot [MS - US] [inactive] http://blogs.msdn.com/charle/
Charly Wood [MS - US] [inactive] http://blogs.msdn.com/charliew/
David Orlander [MS - Norway (language: norwegian)] http://www.crmnorway.com/
Jason Hunt [MS - US] [inactive] http://blogs.msdn.com/jasonhun/
Jim Glass [MS - US] http://blogs.msdn.com/jim_glass/
Jon White [MS - US] [inactive] http://blogs.msdn.com/jonwhite/
Jonas Deibe [MS - Sweden] http://blogs.msdn.com/jonasd/
Joriz Kalz [MS - Germany] http://blogs.msdn.com/joris_kalz/
Kevin Nazemi [MS - US] [inactive / cleared] http://blogs.technet.com/microsoftcrm/
Marcello Fisicaro [ MS - Italy] http://mfisicar.officeisp.net/blog/default.aspx
Menno te Koppele [MS - US] http://blogs.msdn.com/mscrmfreak/
Michael Rich [MS - US] [inactive] http://blogs.msdn.com/microsoft_crm_western_region_news/
Michaeljon Miller [MS - US] http://blogs.msdn.com/mikemill/default.aspx
Michaeljon Miller [MS - US] [inactive] http://inside-mscrm.blogspot.com/
Philip Richardson [MS - US] http://www.philiprichardson.org/blog/
Philip Richardson [MS - US] [inactive] http://spaces.msn.com/philiprichardson/
Philippe Brisaud and Vincent [MS - FR (language: french)] http://blogs.msdn.com/frcrm/
Prashanth Kaankadae [MS - US] http://blogs.technet.com/pkcrm/
Praveen Upadhyay [MS - US] [inactive] http://blogs.msdn.com/crmbest/
Ross Dembecki [MS - Australia] http://microsoft-crm-au.spaces.live.com/
Satya Nadella [MS - US] http://blogs.msdn.com/satyanadella
Simon Hutson [MS - UK] http://blogs.msdn.com/ukcrm/default.aspx
UK MCS [MS - UK] http://blogs.msdn.com/b/thecrmguys/

MVP's

Aaron Elder [MVP CRM - US - Ascentium] http://www.ascentium.com/blog/crm/Default.aspx
Aaron Elder [MVP CRM - US - Invoke Systems] http://www.invokesystems.com/cs/blogs/mscrm/
Aaron Elder [MVP CRM - US - Invoke Systems] [inactive] http://spaces.msn.com/members/provega/
Aaron Elder [MVP CRM - US - Invoke Systems] [inactive] http://blogs.msdn.com/aaronel
Andreas Donaubauer [MVP CRM - Germany (language: German)] http://www.crmfaq.de/
Andrii Butenko [MVP CRM - Ukraine] http://a33ik.blogspot.com/
Ayaz Ahmad [MVP CRM - Pakistan - Ovex Technologies] http://ayazahmad.wordpress.com/
Darren Liu [MVP CRM - Crowe Chizek - US] http://msdynamicscrm-e.blogspot.com/
Darren Liu [MVP CRM - Crowe Chizek - US (language: chinese)] http://msdynamicscrm.blogspot.com/
David Jennaway [MVP CRM - Excitation Ltd - UK] http://mscrmuk.blogspot.com/
David Yack [MVP ASP.NET - US - Colorado Technology Consultants] http://crm.davidyack.com/ [CRM]
http://blog.davidyack.com/ [ASP.NET]
Frank Lee [MVP CRM - US - Workopia] http://spaces.msn.com/microsoft-crm/
Frank Lee [MVP CRM - US - Workopia] [inactive] http://microsoft-crm.blogspot.com/
Geoffroy Gabel [MVP CRM - FR (language french)] http://mscrm3.blogspot.com/
Guy Riddle [MVP CRM - Australia - Snapdragon] http://guyriddle.spaces.live.com/
Guy Riddle [MVP CRM - Australia - Snapdragon] http://www.mscrm.com.au/
Joel Lindstrom [MVP CRM - Customer Effective - US] http://blog.customereffective.com/
John O'Donnell [MVP CRM - US - Crowe Chizek] http://crowechizek.typepad.com/crm/
Larry Lentz [MVP CRM - US - Lentz Computer Services] http://ts2community.com/blogs/larrylentz/
Leon Tribe [MVP CRM - Australia] http://leontribe.blogspot.com/
Marco Amoedo [MVP CRM - Spain - Plain Concepts] http://geeks.ms/blogs/marco
Matt Wittemann [MVP CRM - US - gTECHserv] http://icu-mscrm.blogspot.com/
Matt Wittemann [MVP CRM - US - gTECHserv] http://www.askcrm.com/Home/tabid/866/BlogID/15/Default.aspx
Michael Höhne [MVP CRM - DE - Stunnware] http://www.stunnware.com/crm2
Mitch Milam [MVP CRM - US - Infinite-X] http://blogs.infinite-x.net/
Nithya Balasubramanian [MVP CRM - India] http://niths.wordpress.com/
Ronald Lemmen [MVP CRM - NL - Avanade] http://ronaldlemmen.blogspot.com/
Scott Colson [MVP CRM - US] http://msmvps.com/blogs/crm/default.aspx
Umar Khan [MVP CRM - Pakistan] http://umarkhan.wordpress.com/


Company Blogs:
C5 Insight http://blogs.c5insight.com
CustomerEffective http://blog.customereffective.com/
CWRMobility http://www.cwrmobility.com/weblog/
Simego http://www.simego.com/Blog/
Sonoma Partners http://blog.sonomapartners.com/
Unitek http://www.unitek.com/training/microsoft/crm/blog/


Other Bloggers:
Abe Saldana [US] http://blog.crmbuzz.net/Default.aspx
Andrey Slepitsky [Russia (language: russian)] http://blogs.technet.com/ansle
Anne Stanton [The Norwich Group - US] http://www.crmlady.com/
Arne Janning [Germany] [inactive] http://geekswithblogs.net/insidemscrm/
Asle Berg [Columbus IT - Norway (language: norwegian)] http://dynamics-crm.blogspot.com/
Ben Hosking [UK] http://crmbusiness.wordpress.com/
Boris Kanlica [Turkey] http://www.cub-e.net/
Brian [US] http://mscrmspot.blogspot.com/
Cafe CRM [FR (language French) ] http://cafecrm.typepad.com/webblog/ms_crm/index.html
Carsten Groth [Germany (language: german)] http://carstengroth.spaces.live.com/
Catherine Eibner [Cybner - Australia] http://blog.cybner.com.au/
Christian B. Mortensen [Denmark] http://blogs.msdn.com/cbm/
Cornel Croitoriu [Romania] http://crmstuff.blogspot.com/
Craig Hamer http://blog.crmvault.net/
David Fronk [Dynamic Methods - US] http://dmcrm.blogspot.com/
David Hawes [Avanade - UK] http://blog.davehawes.com/
Dejan Dular [Slovenia] http://a-crm.blogspot.com/
Douglas Leung [Unique World - Australia] http://sharepointsix.blogspot.com/
Erik van Hoof [CWR Mobility - NL] http://www.cwrmobility.com/weblog/
Gagandeep Singh http://mscrmnovice.blogspot.com/
Gareth Tucker [Avanade - Singapore] http://garethtuckercrm.com/
George Doubinski [Australia] http://crm.georged.id.au/
Greg Owen [UK] http://thecrmgrid.wordpress.com/
Guenter [World-Direct.at - Austria] http://geekswithblogs.net/guentersblog/
Gustaf Westerlund [Logica CMG - Sweden] http://gustafwesterlund.blogspot.com/
Hans Veldman [ACI - Netherlands] http://microsoftdynamicscrm.blogspot.com/
Henry Cordes [Avanade - Netherlands] http://www.henrycordes.nl/category/CRM.aspx
Hero [India] http://www.crmsaurin.tk/
Ibrahim Sukari [RightServ - Australia] http://www.mscrmblog.net/
Imran [Pakistan] http://microsoftcrm3.blogspot.com/
Imran [inactive] http://crmexpert.blogspot.com/
Jeff Bennett [Solutions Consulting Group] [inactive] http://mscrm-notes-from-the-field.blogspot.com/
John O'Connor [US] http://crmnit.blogspot.com/
John Straumann [Canada] http://mscrmguy.blogspot.com/
John Straumann [Canada] [inactive] http://blogs.msdn.com/jstraumann
Julian Sharp [active again!] http://spaces.msn.com/members/mscrm
Keith Delarge [Aspective - UK] http://www.mscrmblog.com/
Kjell-Sverre Jerijærvi [Objectware - Norway] http://kjellsj.blogspot.com/
Luis Mazario [Spain (language: Spanish)] http://blogs.msdn.com/crmlandia
Maarten Dominicus [NL] http://www.crmwatcher.com/
Mads Nissen [Norway] [inactive] http://weblogs.asp.net/mnissen/category/5782.aspx
Maik Roempagel http://blog.codealchemist.com/
Marcello Tonarelli [VAR Group - Italian] http://marcellotonarelli.wordpress.com/category/ms-dynamics-crm/
Mario Raunig [World-direct.at - Austria] http://marioraunig.blogspot.com/
Mike Snyder [Sonoma Partners - US] http://blog.sonomapartners.com/
Mike Taylor [UK] http://crmuser.blogspot.com/
Neil Huffman [Productivegap - US] http://nhuffman.spaces.live.com/
Oguz KIRIS [Turkey] http://www.crm4.ws/
Olivier Furnemont [METRUM SàRL - LUX] http://www.furnemont.eu/
Oshri Cohen [Canada] http://mymscrm3.blogspot.com/
Peter Florijn [NL] - http://customcrm.blogspot.com/
Peter Maude [inactive] http://www.tconv.com/blogs/crm3tips/
Phil Adams http://blog.expertsoftware.co.uk/
Pierre Hulsebos [EHTC - US] http://blog.solomon2crm.com/
Rich Oyler & Nicholas Cole [Saratogaus - US] http://crmblog.saratogaus.com/
Rob Bakkers [Avanade - NL] [inactive] http://robbakkers.blogspot.com/
Robert MacLean [South Afrika] http://www.sadev.co.za/
Robert Peledie [UK] http://www.crmrocks.net/
Robert Peledie [UK] http://www.crmconsult.info/
Roberto Nocera [Avanade - Italy (language: italian)] http://blogs.ugidotnet.org/rnocera
Roberto Vecchio [Italy (language: italian)] http://blogs.ugidotnet.org/roblog/
Ron Kane [Scotland] http://mscrminscotland.blogspot.com/
Ross Lotharius [Ascentium - USA] http://rosslotharius.com/
Ryan Farley [inactive] http://crmdeveloper.com/blog
Sandor Schellenberg [Atos Origin - NL] http://friendlycrmonster.blogspot.com/
Seidl Michael [Germany (language english/german)] http://mscrm.m-seidl.com/
Seth Kircher [Navint - US] http://navintmicrosoftcrm.blogspot.com/
Stéphane Dorrekens [Belgiu] http://blog.dorrekens.com
Stephen Maij [SeeSharp - NL] http://www.maijspace.nl/
Steve Boyce [UK] http://blog.crmvault.net/
Wim Coorevits [U2U - Belgium] http://www.u2u.info/Blogs/WimCo
Wolter Kreun [Netherlands] http://www.crmmaps.com/
Wolter Kreun [Netherlands] http://skypecrm.blogspot.com/
Xavier Courchinoux http://blogs.msdn.com/xavier_courchinoux/

General CRM Blogs
Aina Neva Fiati [Indonesia] http://www.crmpieces.blogspot.com/



MS CRM SDK 3.0.4

Microsoft posted the newest version of the SDK for MS CRM 3.0 yesterday. We're on version 3.0.4 now.

Download the SDK here.

Overview
The Microsoft CRM 3.0 SDK is for developers, system customizers and report writers. It contains the following sections:

Server Programming Guide – A guide for developers writing server side code, custom business logic, integration modules, workflow assemblies and more. This guide provides an architectural overview of Microsoft CRM, the entity model, security model, Web services, and sample code.

Client Programming Guide – A guide for developers customizing the Web client or the Microsoft CRM client for Outlook, including scripting, integration of custom Web pages, and sample code.

ISV Programming Guide - A guide for independent software vendors (ISVs) developing installable add-ins for Microsoft CRM.

Report Writers Guide - A guide for developers writing reports for Microsoft CRM using Microsoft SQL Server Reporting Services Report Designer.



Hiding rows

Hi!

Have you already tried to remove fields as described in this article?

I've been using this quite some time now, but I noticed something weird. When you have removed two fields which are on the same line, then you don't want to see this row at all. Well, this doesn't work by default.

By using jscript you'll need to access the table row and hide it. This doesnt work with the style.visibility = 'hidden'. Instead, you should use this line:


crmForm.all.field.parentElement.parentElement.style.display = 'none';

This row should remove the whole line. Yes, thats what it should do. So if it doesn't do that, what does it do? It removes everything except for picklists. You’ll need to hide those manually as described in the other article:
crmForm.all.picklist_d.style.display = 'none';


It's not business critical, but it does fine-tune your UI when working with advanced UI manipulation.

Good luck!

Update:
Robert Amos mailed me his solution. He's hiding complete sections. Here's part of his mail:

I usually pick the first (top left) field in CRM and work on it:
crmForm.all.firstfield_c.parentElement.parentElement. parentElement.style.display = 'none';

That should pick the element containing the entire section and suck it out of the form. So I've been hiding non-relevant sections so the user doesn't get confused. Keeps it clean :)