We have migrated personal views, charts and dashboards from CRM 2013 to Dynamics 365 using a console application. Two things were different in our case; one because of different AD(Azure) UserIds were different in source and destination environments., other was objecttypecode of custom entities. We created 2 temporary tables in the application to do one to one mapping between users and objecttypecodes. Basically we are getting data from these three tables in source system:-
1. UserQueryBase for Personal Views
2. UserFormBase for Dashboards
3. UserQueryVisualizationBase for Charts
We can get this information from source system and after correcting objecttypecodes we can create views/charts/dashboards in destination system. As I had access to SQL server of CRM2013 therefore I used following queries for getting views info:-
"SELECT UserQueryId AS 'ViewId', Name AS 'ViewName', OwnerId AS 'ViewOwnerId', OwnerIdName AS 'ViewOwner', FetchXml AS 'FetchXML', LayoutXml, ReturnedTypeCode, Description, CreatedOn, StateCode FROM dbo.UserQuery WHERE (CreatedOn > CONVERT(DATETIME, '2012-04-13 10:15:26', 102)) AND (StateCode = 0) ORDER BY CreatedOn";
To get the sharing info I used following query:-
"SELECT dbo.UserQuery.UserQueryId AS 'ViewId', dbo.UserQuery.OwnerIdName, dbo.UserQuery.Name AS 'ViewName', dbo.UserQuery.OwnerId AS 'ViewOwnerId', dbo.UserQuery.OwnerIdName AS 'ViewOwner', dbo.SystemUser.SystemUserId AS 'SharedWithUserId', dbo.SystemUser.FullName AS 'SharedWithUser', dbo.Team.TeamId AS 'SharedWithTeamId', dbo.Team.Name AS 'SharedWithTeam', dbo.UserQuery.FetchXml AS 'FetchXML', dbo.UserQuery.LayoutXml, dbo.UserQuery.ReturnedTypeCode, dbo.UserQuery.Description, dbo.PrincipalObjectAccess.AccessRightsMask as 'AccessRightsMask', dbo.UserQuery.CreatedOn FROM dbo.PrincipalObjectAccess RIGHT OUTER JOIN dbo.UserQuery ON dbo.PrincipalObjectAccess.ObjectId = dbo.UserQuery.UserQueryId LEFT OUTER JOIN dbo.SystemUser ON dbo.PrincipalObjectAccess.PrincipalId = dbo.SystemUser.SystemUserId LEFT OUTER JOIN dbo.Team ON dbo.PrincipalObjectAccess.PrincipalId = dbo.Team.TeamId where dbo.PrincipalObjectAccess.AccessRightsMask is not null ORDER BY dbo.UserQuery.Name"
Now for creating view in destination system I used following method:-
object viewName = viewrow["ViewName"];
if (viewName != DBNull.Value)
{
newViewName = (string)viewrow["ViewName"];
}
System.String layoutXml = (string)viewrow["LayoutXml"];
System.String fetchXml = (string)viewrow["FetchXML"];
int currentOTC = (int)viewrow["ReturnedTypeCode"];
int newOTC = getNewCode(OTCResultData, currentOTC);
string OTCEntity = getEntityName(oldTypeCodeData, currentOTC);
if (newOTC != 0)
{
layoutXml = layoutXml.Replace(currentOTC.ToString(), newOTC.ToString());
}
string newViewDesc = string.Empty;
object valueDescription = viewrow["Description"];
if (valueDescription != DBNull.Value)
{
newViewDesc = (string)viewrow["Description"];
}
UserQuery sq = new UserQuery
{
Name = newViewName,
Description = newViewDesc,
ReturnedTypeCode = OTCEntity,
FetchXml = fetchXml,
LayoutXml = layoutXml,
QueryType = 0
};
_customViewId = service.Create(sq);
After creating the view I used the second query to get sharing info. Based on the data in source system were shared using following code:-
Guid ShareWithId = Guid.Empty;
string shareUserName = string.Empty;
ShareWithId = (Guid)sharerow["SharedWithUserId"];
shareUserName = (string)sharerow["SharedWithUser"];
DataRow[] getNewShareWithGuid = ResultData.Select("old_ID = '" + ShareWithId + "'");
object shareUser = getNewShareWithGuid[0].Field<object>("new_ID");
if (shareUser != null)
{
Guid shareUserId = getNewShareWithGuid[0].Field<Guid>("new_ID");
string shareUserEntity = getNewShareWithGuid[0].Field<string>("Entity");
var grantAccessRequest = new GrantAccessRequest
{
PrincipalAccess = new PrincipalAccess
{
AccessMask = AccessMaskValue,
Principal = new EntityReference(shareUserEntity, shareUserId)
},
Target = new EntityReference(UserQuery.EntityLogicalName, veiwId)
};
service.Execute(grantAccessRequest);
Console.WriteLine("Successfully shared with " + shareUserName);
CreateLog("Successfully shared with " + shareUserName);
}
else
{
Console.WriteLine("MISSING USER IN ONLINE : " + (string)sharerow["SharedWithUser"].ToString());
CreateLog("ERROR: User Missing in Online Environment : " + shareUserName);
}
Following method will give you privileges based on Accessmask:-
public static AccessRights getAccessMask(int MaskValue)
{
AccessRights statement;
switch (MaskValue)
{
case 1:
statement = AccessRights.ReadAccess;
break;
case 3:
statement = AccessRights.ReadAccess | AccessRights.WriteAccess;
break;
case 65539:
statement = AccessRights.ReadAccess | AccessRights.WriteAccess | AccessRights.DeleteAccess;
break;
case 524291:
statement = AccessRights.ReadAccess | AccessRights.WriteAccess | AccessRights.AssignAccess;
break;
case 589827:
statement = AccessRights.ReadAccess | AccessRights.WriteAccess | AccessRights.DeleteAccess | AccessRights.AssignAccess;
break;
case 262145:
statement = AccessRights.ReadAccess | AccessRights.ShareAccess;
break;
case 262147:
statement = AccessRights.ReadAccess | AccessRights.WriteAccess | AccessRights.ShareAccess;
break;
case 327683:
statement = AccessRights.ReadAccess | AccessRights.WriteAccess | AccessRights.DeleteAccess | AccessRights.ShareAccess;
break;
case 786435:
statement = AccessRights.ReadAccess | AccessRights.WriteAccess | AccessRights.ShareAccess | AccessRights.AssignAccess;
break;
case 851971:
statement = AccessRights.ReadAccess | AccessRights.WriteAccess | AccessRights.DeleteAccess | AccessRights.ShareAccess | AccessRights.AssignAccess;
break;
default:
statement = AccessRights.ReadAccess;
break;
}
return statement;
}
And the last job was to assign the view to actual owner:-
var requestAssign = new AssignRequest
{
Assignee = new EntityReference(userEntity, OwnerId),
Target = new EntityReference(UserQuery.EntityLogicalName, veiwId)
};
service.Execute(requestAssign);
If any one finds any issue I can be accessed at faisalfiaz@yahoo.com