Tuesday, May 8, 2012

Parse Json in Silverlight

            string jsonstring = "";//Must be a Json String
            byte[] inputarray = Encoding.UTF8.GetBytes(jsonstring);
            MemoryStream stream = new MemoryStream(inputarray);
            StreamReader reader = new StreamReader(stream);
           
            XmlDictionaryWriter xmlData = JsonReaderWriterFactory.CreateJsonWriter(reader.BaseStream);

Friday, March 16, 2012

Modifying System Ribbon button functionality CRM 2011


I found ribbons in 2011 the most painful part, till i learnt how to use it. It is actually cooler than in CRM4. To modify a system button functionality: All that we need to do here is copy the button ID as is from exportedribbonxml available from  sdk\samplecode\cs\client\ribbon\exportribbonxml\exportedribbonxml\myentityribbon.xml.
In this case, i'm gonna modify my email form's send button functionality. The button definition from emailribbon.xml looks like:

<Button Id="Mscrm.Form.email.Send" Command="MSCRM.Form.email.Send.CustomCommand" Sequence="1" Alt="$Resources:Ribbon.Form.email.MainTab.Actions.Send" LabelText="$Resources:Ribbon.Form.email.MainTab.Actions.Send" Image16by16="/_imgs/SFA/SendAsEmail_16.png" Image32by32="/_imgs/SFA/SendAsEmail_32.png" TemplateAlias="o1" ToolTipTitle="$Resources:Mscrm_Form_email_MainTab_Actions_Send_ToolTipTitle" ToolTipDescription="$Resources:Mscrm_Form_email_MainTab_Actions_Send_ToolTipDescription" />

Add that buttondefinition as we would do for adding any custom button. Just match the location attribute of the Customaction tag for the button with the button ID.
i.e.  Change your CustomAction's location attribute

<CustomAction Id="Mscrm.Form.email.Send.CustomAction" Location="Mscrm.Form.email.Send" Sequence="1"><CommandUIDefinition><Button Id="Mscrm.Form.email.Send" Command="MSCRM.Form.email.Send.CustomCommand" Sequence="1" Alt="$Resources:Ribbon.Form.email.MainTab.Actions.Send" LabelText="$Resources:Ribbon.Form.email.MainTab.Actions.Send" Image16by16="/_imgs/SFA/SendAsEmail_16.png" Image32by32="/_imgs/SFA/SendAsEmail_32.png" TemplateAlias="o1" ToolTipTitle="$Resources:Mscrm_Form_email_MainTab_Actions_Send_ToolTipTitle" ToolTipDescription="$Resources:Mscrm_Form_email_MainTab_Actions_Send_ToolTipDescription" /></CommandUIDefinition></CustomAction>

After this, i define a Commanddefinition MSCRM.Form.email.Send.CustomCommand inside my command definition tag.

<CommandDefinition Id="MSCRM.Form.email.Send.CustomCommand">            <EnableRules><EnableRule Id="Mscrm.UserHasRoleForSend"/>            </EnableRules><DisplayRules><DisplayRule Id="Mscrm.CanWritePrimary" />              <DisplayRule Id="Mscrm.Form.email.InDraftOrFailedState" /></DisplayRules><Actions><JavaScriptFunction FunctionName="send" Library="/_static/activities/email.js" /></Actions></CommandDefinition>

After this, i define my customrule "Mscrm.UserHasRoleForSend" inside a javascript.

<EnableRules><EnableRule Id="Mscrm.UserHasRoleForSend"><CustomRule FunctionName="UserHasRoleForSend" Library="$webresource:customscripts_CheckUserRoleForMarketingList.js" /></EnableRule></EnableRules>

customscripts_CheckUserRoleForMarketingList.js is a webresource jscript that i've already uploaded. I'm calling a function UserHasRoleForSend in customscripts_CheckUserRoleForMarketingList.js. The function returns a true or false value.
Since the display rules are inbuilt i'm not redefining them in my customizations.xml.
Note: If not required, we can remove the displayrules from the custom command. In my case, i just needed to add an additional condition for enabling the "send" button in email form. The same can be done for HomePageGrid buttons also.



Thursday, March 8, 2012

Sample Odata Query CRM2011


function GetCity()
{
var serverUrl = "http://"+window.location.host+"/" + Xrm.Page.context.getOrgUniqueName();
  var id = Xrm.Page.getAttribute("new_courtid").getValue();
if(id!=null)
{
    var ODataPath = serverUrl + "/XRMServices/2011/OrganizationData.svc";

    var retrieveReq = new XMLHttpRequest();
//replace with your odata query
    var Odata = ODataPath + "/AccountSet?$select=new_city&$filter=accountId eq guid'" + id[0].id + "'";
    retrieveReq.open("GET", Odata, true);
    retrieveReq.setRequestHeader("Accept", "application/json");
    retrieveReq.setRequestHeader("Content-Type", "application/json; charset=utf-8");
    retrieveReq.onreadystatechange = function () { retrieveReqCallBack(this); };
    retrieveReq.send();
}
}

function retrieveReqCallBack(retrieveReq) {

    if (retrieveReq.readyState == 4 /* complete */) {
        if (retrieveReq.status == 200) {
            var retrieved = JSON.parse(retrieveReq.responseText).d;
//replace attribute name as in the query
            var city= retrieved.results[0]["new_city"];
            Xrm.Page.data.entity.attributes.get('new_city').setValue(city.Value);
        }
        else {
            errorHandler(retrieveReq);
            alert("Unable to Retrieve City");
        }
    }
}

Tuesday, March 6, 2012

Read Config File from a different location


ExeConfigurationFileMap cf =
                new ExeConfigurationFileMap() { ExeConfigFilename = "C:\\app.config" };


            Configuration configFile = ConfigurationManager.OpenMappedExeConfiguration(cf, ConfigurationUserLevel.None);


This by default provides KeyValuePair when you attempt to read the settings. To return KeyValuePair as NameValuePair, Use as below. 




            ExeConfigurationFileMap cf =
                new ExeConfigurationFileMap() { ExeConfigFilename = "C:\\app.config" };


            Configuration confFile = ConfigurationManager.OpenMappedExeConfiguration(cf, ConfigurationUserLevel.None);
                       NameValueCollection _collsettings = new NameValueCollection();
            foreach (string key in confFile.AppSettings.Settings.AllKeys)
            {
                 _collsettings.Add(confFile.AppSettings.Settings[key].Key, confFile.AppSettings.Settings[key].Value);
            }


If you are reading machine config file, make use of Suitable class instead of Execonfigurationfilemap.

Tuesday, January 3, 2012

Could not load file or assembly ‘Microsoft.Crm, Version=5.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35′

 

Sharing from Nishant Rana's Blog..

Could not load file or assembly ‘Microsoft.Crm, Version=5.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35′ or one of its dependencies. The system cannot find the file specified or Deploying custom web application inside ISV folder of CRM 2011

Posted: January 20, 2011 in CRM, CRM 2011, Microsoft Dynamics CRM
Tags: ,

To deploy our custom web application inside ISV folder of CRM 2011 we need to follow the below steps
Make following changes in the web.config
<configuration>
<configSections>
<remove name=crm.authentication />
</configSections>
<system.web>
<httpModules>
<clear/>
</httpModules>

……………………
And after deploying the application within the ISV folder, place the following dlls within its bin folder
  • AntiXssLibrary.dll
  • Microsoft.Crm.dll
  • Microsoft.Crm.Sdk.dll
  • Microsoft.Crm.Platform.Sdk.dll
We can find these dll’s inside
../Microsoft Dynamics CRM/Server/Bin folder.
The above solution worked perfectly for Beta Versions of CRM 2011.
Recently we upgraded to RTM, and we had to deploy a WCF Service and custom web site inside isv.
For WCF service we had to make following changes to the web.config apart from the changes mentioned above
<serviceHostingEnvironment aspNetCompatibilityEnabled=”false”>
</serviceHostingEnvironment>
</system.serviceModel>
And in case of custom web site we had to add the following additional dll’s
  • Microsoft.Crm.Sdk.Proxy.dll
  • Microsoft.Xrm.Sdk.dll
Hope it helps!

Thursday, October 20, 2011

Impersonation in CRM2011

Impersonate in Plugins:

ICrmService service = context.CreateCrmService(context.InitiatingUserId);
Instead of context.InitiatingUserId use the user guid of the user.

ICrmService service = context.CreateCrmService(userId);

To Impersonate in WebPages:
Create crmservice and assign callerid property to the user to be impersonated.

Friday, June 10, 2011

Date as per User Settings


//*********************************************************************
//**  DEFAULT DUE DATE:  UPON LOAD OF THE FORM, FOR CREATE ONLY, WE 
//**  SET THE DUE DATE TO THE CURRENT DATE AND TIME FOR THE CRM USER.
//*********************************************************************
var result = new Date();
if(crmForm.FormType ==1 )
{

fetchUserTime();
crmForm.all.scheduledend.DataValue = result;
}
//**************** **************************************
//*****************Get Current User ************************
//*******************************************************
function getCurrentUser()
{
//Create the XML that will fetch the required info.
var XMLRequest = "" + 
"<?xml version=\"1.0\" encoding=\"utf-8\"?>" + 
"<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\">" + GenerateAuthenticationHeader() +
" <soap:Body>" + 
" <RetrieveMultiple xmlns=\"http://schemas.microsoft.com/crm/2007/WebServices\">" + 
" <query xmlns:q1=\"http://schemas.microsoft.com/crm/2006/Query\" xsi:type=\"q1:QueryExpression\">" + 
" <q1:EntityName>systemuser</q1:EntityName>" + 
" <q1:ColumnSet xsi:type=\"q1:ColumnSet\">" + 
" <q1:Attributes>" + 
" <q1:Attribute>systemuserid</q1:Attribute>" + 
" <q1:Attribute>fullname</q1:Attribute>" + 
" </q1:Attributes>" + 
" </q1:ColumnSet>" + 
" <q1:Distinct>false</q1:Distinct>" + 
" <q1:Criteria>" + 
" <q1:FilterOperator>And</q1:FilterOperator>" + 
" <q1:Conditions>" + 
" <q1:Condition>" + 
" <q1:AttributeName>systemuserid</q1:AttributeName>" + 
" <q1:Operator>EqualUserId</q1:Operator>" + 
" </q1:Condition>" + 
" </q1:Conditions>" + 
" </q1:Criteria>" + 
" </query>" + 
" </RetrieveMultiple>" + 
" </soap:Body>" + 
"</soap:Envelope>" + 
"";
try
{
//Create Http request object
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", XMLRequest.length);
xmlHttpRequest.send(XMLRequest);

//Store the response which would be XML
var Result = xmlHttpRequest.responseXML;

/*
The return is of type "BusinessEntity" if you were using similar code one server side.
Hence we need to select node of type "BusinessEntity"

In our case It should be not more one than one node
*/
var BusinessEntityNodes = Result.selectNodes("//RetrieveMultipleResult/BusinessEntities/BusinessEntity");

// Check If data was retrived
if (BusinessEntityNodes.length != 0)
{
    var BusinessEntityNode = BusinessEntityNodes[0]; 
    var SystemUserId = BusinessEntityNode.selectSingleNode("q1:systemuserid");
    var FullName = BusinessEntityNode.selectSingleNode("q1:fullname");
    var SystemUserId = (SystemUserId == null) ? null : SystemUserId.text;
    var FullName = (FullName == null) ? null : FullName.text;
}
return SystemUserId ;
}
catch (e)
{
alert(e.message);
}

}
//****************************************************************************
//***********************Fetch User Time in CRM**********************************
//****************************************************************************
function fetchUserTime()
{
var xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" + 
"  <soap:Header>" + 
"    <CrmAuthenticationToken xmlns=\"http://schemas.microsoft.com/crm/2007/WebServices\">" + 
"      <AuthenticationType xmlns=\"http://schemas.microsoft.com/crm/2007/CoreTypes\">0</AuthenticationType>" + 
"      <OrganizationName xmlns=\"http://schemas.microsoft.com/crm/2007/CoreTypes\">"+ORG_UNIQUE_NAME +"</OrganizationName>" + 
"      <CallerId xmlns=\"http://schemas.microsoft.com/crm/2007/CoreTypes\">00000000-0000-0000-0000-000000000000</CallerId>" + 
"    </CrmAuthenticationToken>" + 
"  </soap:Header>" + 
"  <soap:Body>" + 
"      <Request xsi:type=\"RetrieveUserSettingsSystemUserRequest\" ReturnDynamicEntities=\"true\">" + 
"        <EntityId>"+getCurrentUser()+"</EntityId>" + 
"        <ColumnSet xmlns:q1=\"http://schemas.microsoft.com/crm/2006/Query\" xsi:type=\"q1:ColumnSet\">" + 
"          <q1:Attributes>" + 
"            <q1:Attribute>timezonebias</q1:Attribute>" + 
"          </q1:Attributes>" + 
"        </ColumnSet>" + 
"      </Request>" + 
"    </Execute>" + 
"  </soap:Body>" + 
"</soap:Envelope>" + 
"";

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;
//Create an XML document that can be parsed.
var oXmlDoc = new ActiveXObject("Microsoft.XMLDOM");
oXmlDoc.async = false;
oXmlDoc.loadXML(resultXml.xml);
//Value the user is interesed in in string form
var times = oXmlDoc.getElementsByTagName("Property");
var difference = Number(times[0].text);

//And the result - Date object
var gmtday= result.getUTCDate();
var gmtmonth = result.getUTCMonth();
gmtmonth=gmtmonth;
var gmtYear = result.getUTCFullYear();
var gmthours = result.getUTCHours();
var gmtminutes = result.getUTCMinutes();

result.setFullYear(gmtYear);
result.setMonth(gmtmonth);
result.setDate(gmtday);
result.setHours(gmthours);
result.setMinutes(gmtminutes);
result.setMinutes ( result.getMinutes() - difference);
}

//********************************************************************
//***************End of Fetch User Time**********************************
//********************************************************************

Tuesday, May 3, 2011

Modify Views of System entities

I had always been thinking that queue views cannot be modified. Thanks to Vince Bullinger i found out how to do that.
go to Workplace/home_workplace.aspx. 


just alert the sViewId from this method. 

function nodeSelect( sQueueId, sViewId, sMenuId )
{
crmGrid.SetParameter("viewid", sViewId);
crmGrid.SetParameter("qid", sQueueId);
crmGrid.Reset();
resetMenuItems(sMenuId);
}

use the following url:
http://crm/tools/viewEditor/viewManager.aspx?id={00000000-0000-0000-00AA-000010001400}
crm - your organisation name 
id = the alerted sViewId. 

You can change the view and then publish all customizations. View is now customized. 





Wednesday, April 13, 2011

filtered lookup in Jscript


crmForm.all.new_subcategoryid.AddParam("search","<fetch mapping='logical'><entity name='new_casesubcategory'><filter><condition attribute='new_categoryid' operator='eq' value='" + crmForm.all.new_categoryid.DataValue[0].id + "' /></filter></entity></fetch>");

Tuesday, April 12, 2011

GridView/Listviews do not retain values inside CRM but work fine in dev environment

You need to enableviewstate in web.config file

<pages enableViewState="true">
or
do the same individually at pagelevel

as <@Page EnableViewState="true" />










A common issue raised in the CRM Development forum is of custom web pages that work correctly in a development environment, but then fail to work when deployed into the CRM web site. The most common reason for this is that the CRM web.config overrides some of the default ASP.Net configuration settings.

The relevant entries in the CRM web.config (in the root of the CRM web site) are:

<pages buffer="true" enableSessionState="false" enableViewState="false" validateRequest="false/">
<sessionState mode="Off"/>

These have 2 main consequences:

  1. Session State is disabled. This issue is relatively easy to diagnose, as you tend to get a clear error message if trying to use session state when it is disabled
  2. ViewState is disabled. This can be a more subtle effect, as developers often rely on viewState without necessarily being aware of it. ViewState is what allows ASP.Net web controls to maintain property values across web requests; if it is disabled then it leads to symptoms such as values not being retained, or list boxes losing their contents
The solution for viewState is straightforward. You can reenable viewState for you application either in the web.config in your application directory, or at the page level within the <@Page> directive. These looks like the following:
web.config:
<pages enableViewState="true" />
Page directive:
<@Page EnableViewState="true" />
Session state is a bit more complex, as this is configured at the web application level. Personally, I've never seen any reason to use session state within custom code in the CRM web site; CRM doesn't use this, and I find it best to mimic CRM behaviour wherever possible.
And one final point about best practise; as this post demonstrates, it is best not to rely on the default ASP .Net configuration settings, rather I find it best to always explicitly enable or disable settings in the local web.config