Default account view is 'Active Accounts' for Tom, and 'My Active Accounts' view is default for Peter.
I've developed a little wizard and I would like to share it.
The following ideas for this wizard are:
1. Create a entity child to systemuser entity in which user can select default view for an entity.
2. To write plugin which will handle RetrieveMultiple message on savedquery entity.
1. Create a Default User View entity:
1.1. Creation of Default User View Entity:
Here I input Display Name, Plural Name, ownership is organization, name of entity. Mark all details as shown.
I set primary attribute name as new_entityname.
I create a relation between my newly created entity and systemuser entity where systemuser is primary entity.
I create required attributes:
new_defaultview - for default view identifier
new_defaultviewdisplayname - display name of default View
new_entitydisplayname - display name of entity (entity schema name will be stored in new_entityname field)
new_entitytypecode - entity type code
Appearance of form:
Second tab will be hide in OnLoad event handler - it contains fields Default View Name, Entity Display Name and Entity Type Code:
OnLoad Script of form:
//function converts text field Entity Name to picklist and fills it with entities
function ConvertEntityToPicklist(fieldName, dataItems)
{
var defaultValue = crmForm.all[fieldName].DataValue;
var table = crmForm.all[fieldName + "_d"];
var select = "<select req='0' id='" + fieldName + "' name='" + fieldName + "' defaultSelected='' class='ms-crm-SelectBox' tabindex='1170' onchange='new_entityname_onchange0();'>";
var defaultValueFound = false;
for (var i = 0; i < dataItems.length; i++)
if (dataItems[i].selectSingleNode('IsCustomizable').text == "true")
{
select += "<option value='" + dataItems[i].selectSingleNode('LogicalName').text + "' ";
select += "entitytypeid='"+dataItems[i].selectSingleNode('ObjectTypeCode').text+"'";
if (dataItems[i].selectSingleNode('LogicalName').text == defaultValue)
{
select += " SELECTED";
defaultValueFound = true;
}
select += ">" + dataItems[i].selectSingleNode('DisplayName/LocLabels/LocLabel/Label').text + "</option>";
}
if ((defaultValue != null) && (defaultValue.length > 0) && !defaultValueFound)
{
select += "<option value='" + defaultValue + "' SELECTED>" + defaultValue + "</option>";
}
select += "</select>";
table.innerHTML = select;
}
//function converts text field Default View to picklist and fills it with Views for entity selected in Entity Name picklist
function CreateQueriesList(fieldName, dataItems)
{
var defaultValue = crmForm.all[fieldName].DataValue;
var table = crmForm.all[fieldName + "_d"];
var select = "<select req='0' id='" + fieldName + "' name='" + fieldName + "' defaultSelected='' class='ms-crm-SelectBox' tabindex='1170'>";
var defaultValueFound = false;
for (var i = 0; i < dataItems.length; i++)
{
select += "<option value='" + dataItems[i].selectSingleNode('./savedqueryid').nodeTypedValue + "' ";
if (dataItems[i].selectSingleNode('./savedqueryid').nodeTypedValue == defaultValue)
{
select += " SELECTED";
defaultValueFound = true;
}
select += ">" + dataItems[i].selectSingleNode('./name').nodeTypedValue + "</option>";
}
if ((defaultValue != null) && (defaultValue.length > 0) && !defaultValueFound)
{
select += "<option value='" + defaultValue + "' SELECTED>" + defaultValue + "</option>";
}
select += "</select>";
table.innerHTML = select;
}
//Hide second tab
crmForm.all.tab1Tab.style.display = 'none';
//Request to retrieve all entities
var request = "" +
"<?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>" +
" <Execute xmlns=\"http://schemas.microsoft.com/crm/2007/WebServices\">" +
" <Request xsi:type=\"RetrieveAllEntitiesRequest\">" +
" <RetrieveAsIfPublished>true</RetrieveAsIfPublished>" +
" <MetadataItems>EntitiesOnly</MetadataItems>" +
" </Request>" +
" </Execute>" +
" </soap:Body>" +
"</soap:Envelope>";
var xmlHttpRequest = new ActiveXObject("Msxml2.XMLHTTP");
xmlHttpRequest.Open("POST", "/mscrmservices/2007/MetadataService.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", request.length);
xmlHttpRequest.send(request);
var result = xmlHttpRequest.responseXML;
//Retrieve a collection of entities
var schemaNames = result.selectNodes("//CrmMetadata/CrmMetadata");
//Convertion
ConvertEntityToPicklist('new_entityname', schemaNames);
//Request to retrieve all Public Views for entity
var xml = "<?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>"+
"<Fetch xmlns='http://schemas.microsoft.com/crm/2007/WebServices'>"+
"<fetchXml>"+
"<fetch mapping='logical'>"+
" <entity name='savedquery'>"+
" <attribute name='name'/>"+
" <attribute name='savedqueryid'/>"+
" <filter type='and'>"+
" <condition attribute='isprivate' operator='eq' value='false'/>"+
" <condition attribute='inproduction' operator='eq' value='true'/>"+
" <condition attribute='isquickfindquery' operator='eq' value='false'/>"+
" <condition attribute='returnedtypecode' operator='eq' value='"+
document.getElementById('new_entityname').options[document.getElementById('new_entityname').selectedIndex].getAttribute('entitytypeid')+
"'/>"+
" <condition attribute='querytype' operator='eq' value='0'/>"+
" </filter>"+
" </entity>"+
"</fetch>"+
"</fetchXml>"+
"</Fetch>"+
"</soap:Body>"+
"</soap:Envelope>";
var xHReq = new ActiveXObject("Msxml2.XMLHTTP");
xHReq.Open("POST", "/mscrmservices/2007/CrmService.asmx", false);
xHReq.setRequestHeader("SOAPAction","http://schemas.microsoft.com/crm/2007/WebServices/Fetch");
xHReq.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
xHReq.setRequestHeader("Content-Length", xml.length);
xHReq.send(xml);
var resultXml = xHReq.responseXML;
var resultSet = resultXml.text;
resultSet.replace('<','<');
resultSet.replace('>','>');
var oXmlDoc = new ActiveXObject("Microsoft.XMLDOM");
oXmlDoc.async = false;
oXmlDoc.loadXML(resultSet);
//Retrieve a collection of Views
var results = oXmlDoc.getElementsByTagName('result');
//Conversion
CreateQueriesList('new_defaultview', results);
OnSave script of Form:
crmForm.all.new_entitydisplayname.DataValue = document.getElementById('new_entityname').options[document.getElementById('new_entityname').selectedIndex].innerText;
crmForm.all.new_defaultviewdisplayname.DataValue = document.getElementById('new_defaultview').options[document.getElementById('new_defaultview').selectedIndex].innerText;
crmForm.all.new_entitytypecode.DataValue = document.getElementById('new_entityname').options[document.getElementById('new_entityname').selectedIndex].getAttribute('entitytypeid');
Entity Name OnChange event handler:
//Request to retrieve all Public Views for entity
var xml = "<?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>"+
"<Fetch xmlns='http://schemas.microsoft.com/crm/2007/WebServices'>"+
"<fetchXml>"+
"<fetch mapping='logical'>"+
" <entity name='savedquery'>"+
" <attribute name='name'/>"+
" <attribute name='savedqueryid'/>"+
" <filter type='and'>"+
" <condition attribute='isprivate' operator='eq' value='false'/>"+
" <condition attribute='inproduction' operator='eq' value='true'/>"+
" <condition attribute='isquickfindquery' operator='eq' value='false'/>"+
" <condition attribute='returnedtypecode' operator='eq' value='"+
document.getElementById('new_entityname').options[document.getElementById('new_entityname').selectedIndex].getAttribute('entitytypeid')+
"'/>"+
" <condition attribute='querytype' operator='eq' value='0'/>"+
" </filter>"+
" </entity>"+
"</fetch>"+
"</fetchXml>"+
"</Fetch>"+
"</soap:Body>"+
"</soap:Envelope>";
var xHReq = new ActiveXObject("Msxml2.XMLHTTP");
xHReq.Open("POST", "/mscrmservices/2007/CrmService.asmx", false);
xHReq.setRequestHeader("SOAPAction","http://schemas.microsoft.com/crm/2007/WebServices/Fetch");
xHReq.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
xHReq.setRequestHeader("Content-Length", xml.length);
xHReq.send(xml);
var resultXml = xHReq.responseXML;
var resultSet = resultXml.text;
resultSet.replace('<','<');
resultSet.replace('>','>');
var oXmlDoc = new ActiveXObject("Microsoft.XMLDOM");
oXmlDoc.async = false;
oXmlDoc.loadXML(resultSet);
//Results Retrieve
var results = oXmlDoc.getElementsByTagName('result');
var ctrl = document.getElementById('new_defaultview');
//Clear picklist values
for(var i = ctrl.options.length-1; i >=0 ; i--)
{
ctrl.options[i] = null;
}
//Fill picklist with retrieved Views
for (var i = 0; i < results.length; i++)
{
var newoption = document.createElement("option");
newoption.setAttribute("value", results[i].selectSingleNode('./savedqueryid').nodeTypedValue);
newoption.innerHTML = results[i].selectSingleNode('./name').nodeTypedValue;
ctrl.appendChild(newoption);
}
Save and Close Form and publish changes. Give all users privileges at least to read this entity.
2. Plugin source:
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Crm.Sdk;
using Microsoft.Crm.SdkTypeProxy;
using Microsoft.Crm.Sdk.Query;
namespace InternalPVM
{
public class DefaultViewHandler : IPlugin
{
#region IPlugin Members
public void Execute(IPluginExecutionContext context)
{
if (context.PrimaryEntityName == EntityName.savedquery.ToString() &&
context.InputParameters.Contains("Query") &&
context.InputParameters["Query"] is QueryExpression)
{
QueryExpression resultExpression = (QueryExpression)context.InputParameters["Query"];
//I retrieve entity Type code of entity
string entityname = ((ConditionExpression)resultExpression.Criteria.Conditions[0]).Values[0].ToString();
ICrmService crmsevice = context.CreateCrmService(true);
//I create a request to retrieve default View for current entity
QueryExpression query = new QueryExpression("new_defaultuserview");
query.Criteria.AddCondition(new ConditionExpression("new_userid", ConditionOperator.Equal, context.UserId));
query.Criteria.AddCondition(new ConditionExpression("new_entitytypecode", ConditionOperator.Equal, entityname));
query.ColumnSet = new ColumnSet(new string[] { "new_defaultview" });
RetrieveMultipleRequest request = new RetrieveMultipleRequest();
request.ReturnDynamicEntities = true;
request.Query = query;
RetrieveMultipleResponse response = (RetrieveMultipleResponse)crmsevice.Execute(request);
//If there are no settings just exit from this method
if (response.BusinessEntityCollection.BusinessEntities.Count == 0)
return;
//Identifier of Default View
Guid defaultviewid = new Guid(((DynamicEntity)response.BusinessEntityCollection.BusinessEntities[0])["new_defaultview"].ToString());
BusinessEntityCollection result = (BusinessEntityCollection)context.OutputParameters["BusinessEntityCollection"];
//Scroll all Views one-By-One and Set default View from user Setting to be default in resultset
foreach (DynamicEntity de in result.BusinessEntities)
if (((Key)de["savedqueryid"]).Value.Equals(defaultviewid))
de["isdefault"] = new CrmBoolean(true);
else
de["isdefault"] = new CrmBoolean(false);
}
}
#endregion
}
}
Build and register assembly. Register new step - Message RetrieveMultiple, Primary entity - savedquery, Secondary Entity - none, Stage - Post Stage, Execution Mode = Syncronous, Pipeline - Parent Pipeline.
And the demonstration:
Hi a33ik;
ReplyDeleteare u sure, you´ve created
new_defaultview - for default view identifier
new_defaultview - display name of default View
(2 times new_defaultview)?
new_defaultview
new_displayname is looking much better?
Hi, Carsten.
ReplyDeleteI'm very appreciated for your feedback. Of course this is my mistake. Correct attribute name is new_defaultviewdisplayname.
It´s working for almost a week - only thing I was asked: Wouldn´t it be nice to set my personal views as default views as well?
ReplyDeleteWell I said - maybe this is something for a next version ;-)
You've deployed my solution on your production?
ReplyDeleteYes, tried this in "real life" - and I´m working on some modifications.
ReplyDelete- Entity Picklist sorting a-z
- Adding personal views as default views
- Adding support for personal views which are shared
- Adding support for system views which are shared
- Adding support to interact with public view manager
the topic is very interesting, but the support of personal views would be great. If somebody has a solution, please post.
ReplyDeleteThanks
This is amazing if I could get past the fact it's telling me i need a default view display name
ReplyDeleteSet the user defaultview from all views listed in the user view list from "System views" and "My Views" , It much more difficult ,since you need to control 2 retrives and the userquery don't have isdefault attribute.
ReplyDeleteThis looks just like what I need. Can anyone send me the plugin already compiled so all I can to do is register it and create the entity etc.
ReplyDeleteanyone know if this works in offline mode?
ReplyDeleteHi, Withers. I haven't tested it in offline mode. But you just have to register this plugin as offline and test.
ReplyDeleteAndriy,
ReplyDeleteWorking on the thread in the Developer forum that references this code. User wants to apply it to the "userquery" instead of "savedquery". I don't know what would be necessary to adjust with your code to achieve that (I'm working on an alternate solution that would convert a "userquery" into a "savedquery"). Any thoughts?
Has any of Carsten's suggestions been implemented into the code. His ideas of
ReplyDelete- Entity Picklist sorting a-z
- Adding personal views as default views
- Adding support for personal views which are shared
- Adding support for system views which are shared
- Adding support to interact with public view manager
Looked really useful.
First one can be done. All other - I haven't try but any way it will be unsupported stuff.
ReplyDeletedear good job, but i have a error, i change sigla 'new' for 'crm', this is my code
ReplyDeleteon change of entitye name
//Request to retrieve all Public Views for entity
var xml = ""+
""+
GenerateAuthenticationHeader()+
""+
""+
""+
"<fetch mapping='logical'>"+
" <entity name='savedquery'>"+
" <attribute name='name'/>"+
" <attribute name='savedqueryid'/>"+
" <filter type='and'>"+
" <condition attribute='isprivate' operator='eq' value='false'/>"+
" <condition attribute='inproduction' operator='eq' value='true'/>"+
" <condition attribute='isquickfindquery' operator='eq' value='false'/>"+
" <condition attribute='returnedtypecode' operator='eq' value='"+
document.getElementById('crm_entityname').options[document.getElementById('crm_entityname').selectedIndex].getAttribute('entitytypeid')+
"'/>"+
" <condition attribute='querytype' operator='eq' value='0'/>"+
" </filter>"+
" </entity>"+
"</fetch>"+
""+
""+
""+
"";
var xHReq = new ActiveXObject("Msxml2.XMLHTTP");
xHReq.Open("POST", "/mscrmservices/2007/CrmService.asmx", false);
xHReq.setRequestHeader("SOAPAction","http://schemas.microsoft.com/crm/2007/WebServices/Fetch");
xHReq.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
xHReq.setRequestHeader("Content-Length", xml.length);
xHReq.send(xml);
var resultXml = xHReq.responseXML;
var resultSet = resultXml.text;
resultSet.replace('<','<');
resultSet.replace('>','>');
var oXmlDoc = new ActiveXObject("Microsoft.XMLDOM");
oXmlDoc.async = false;
oXmlDoc.loadXML(resultSet);
//Results Retrieve
var results = oXmlDoc.getElementsByTagName('result');
var ctrl = document.getElementById('crm_defaultview');
//Clear picklist values
for(var i = ctrl.options.length-1; i >=0 ; i--)
{
ctrl.options[i] = null;
}
//Fill picklist with retrieved Views
for (var i = 0; i < results.length; i++)
{
var newoption = document.createElement("option");
newoption.setAttribute("value", results[i].selectSingleNode('./savedqueryid').nodeTypedValue);
newoption.innerHTML = results[i].selectSingleNode('./name').nodeTypedValue;
ctrl.appendChild(newoption);
}
continue above
plug-in
ReplyDeleteusing System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Crm.Sdk;
using Microsoft.Crm.SdkTypeProxy;
using Microsoft.Crm.Sdk.Query;
namespace InternalPVM
{
public class DefaultViewHandler : IPlugin
{
#region IPlugin Members
public void Execute(IPluginExecutionContext context)
{
if (context.PrimaryEntityName == EntityName.savedquery.ToString() &&
context.InputParameters.Contains("Query") &&
context.InputParameters["Query"] is QueryExpression)
{
QueryExpression resultExpression = (QueryExpression)context.InputParameters["Query"];
//I retrieve entity Type code of entity
string entityname = ((ConditionExpression)resultExpression.Criteria.Conditions[0]).Values[0].ToString();
ICrmService crmsevice = context.CreateCrmService(true);
//I create a request to retrieve default View for current entity
QueryExpression query = new QueryExpression("crm_defaultuserview");
query.Criteria.AddCondition(new ConditionExpression("crm_userid", ConditionOperator.Equal, context.UserId));
query.Criteria.AddCondition(new ConditionExpression("crm_entitytypecode", ConditionOperator.Equal, entityname));
query.ColumnSet = new ColumnSet(new string[] { "crm_defaultview" });
RetrieveMultipleRequest request = new RetrieveMultipleRequest();
request.ReturnDynamicEntities = true;
request.Query = query;
RetrieveMultipleResponse response = (RetrieveMultipleResponse)crmsevice.Execute(request);
//If there are no settings just exit from this method
if (response.BusinessEntityCollection.BusinessEntities.Count == 0)
return;
//Identifier of Default View
Guid defaultviewid = new Guid(((DynamicEntity)response.BusinessEntityCollection.BusinessEntities[0])["crm_defaultview"].ToString());
BusinessEntityCollection result = (BusinessEntityCollection)context.OutputParameters["BusinessEntityCollection"];
//Scroll all Views one-By-One and Set default View from user Setting to be default in resultset
foreach (DynamicEntity de in result.BusinessEntities)
if (((Key)de["savedqueryid"]).Value.Equals(defaultviewid))
de["isdefault"] = new CrmBoolean(true);
else
de["isdefault"] = new CrmBoolean(false);
}
}
#endregion
}
}
but its show me a errors, tipycal microsoft .. try again blabla...
please help me!!
thank for all
dear my problem is when press save button form, you can help me please!
ReplyDeletethanks
First off Andriy - great work - this has got me 90% of the way. I wonder if anyone has been able to implement a version that sets the default view to a user query view. Its easy enough to incorporate user query views into the Default View entity, the problem arises when you try and set the view to default in the plugin (as has already been pointed out there is no 'isdefault' equivalent in the userquery model).
ReplyDeleteHello Mark,
ReplyDeleteI'm afraid that it is impossible with supported methods. You can try to use unsupported approach - editing of aspx file to perform your task.
I thought as much, though :
ReplyDelete1. I'm not sure I want to edit core ASPX files
2. I don't know which ASPX to edit
I've got a clunky way round it that involves creating 'client specific' public views and setting them as the default view on the various entities we allow access to. Its a pain in that we need to publish each time a new client wants access (which fortunately isn't very often).
My next step is to allow IFD clients to search there default views.
This comment has been removed by the author.
ReplyDeleteHi and thanks for your code.
ReplyDeleteI made a function to order the entities alphabetically, but this editor truncates the code for it, so it will be useless to put it here.
Thanks,
ReplyDeleteAfter several implementations of this code I have implemented the same thing but I decided not to publish it here.