In this article, we will explain our way to integrate Dynamics Portal with SharePoint.
As you all definitely know, SharePoint is widely used for documents and files management, and there are plenty of ready solutions for SharePoint and Dynamics CRM integration (like PowerAttachment). But unfortunately, OOB Dynamics Portal has no options to integrate with SharePoint, and that’s what we offer in case you plan to do it.
This task was divided into 2 subtasks:
- How to transfer files from Dynamics Portal to SharePoint.To be able to do that, you need to allow to attach files in Portal parameters (Portals -> Entity Form) and configure PowerAttachment (or you can write your own plugin to transfer files from CRM to SharePoint)
- How to transfer files from SharePoint to Dynamics Portal.
To do that, you have to create a new custom page sharepointfoldercontent with the custom page template. This new page will process file retrieval requests using CRM fetch queries to sharepointfile entity. The data is returned in JSON format. {% fetchxml sharepointfetch %}
On custom page template, the query was implemented using LIQUID fetchxml query.
{% Fetchxml sharepointfetch%}
<fetch>
<entity name="uds_sharepointfile">
<attribute name="uds_sharepointresponse"></attribute>
<filter type="and">
<condition attribute="uds_targetid" operator="eq"
value="{{request.params['id']}}"></condition>
<condition attribute="uds_userid" operator="eq"
value{{user.id}}"></condition>
<condition attribute="uds_name" operator="eq"
value="{{now}}"></condition>
</filter>
</entity>
</fetch>
{% endfetchxml %}
{% assign entities = sharepointfetch.results.entities %}
{% assign object = entities.first %}
{{ object. uds_sharepointfilesjson }}
We added a new entity to Dynamics CRM – uds_sharepointfile, and developed plugin on RetrieveMultiple event.
Do not forget to add Entity Permissions for this new entity.
- Parameter
uds_targetidcontains Guid entries. - Parameter
uds_useridcan be used for checking the user access rights for the files he requests. - Parameter
<condition attribute="uds_name" operator="eq" value="{{now}}"></condition>allows to avoid query cashing.
In the plugin the FetchXML is parsed, and its parameters are extracted.
If the query contains the conditions of this type <condition attribute="uds_targetid" operator="eq" value="{Guid}"></condition>, after that, the received guid is used, the destination folder in SharePoint is defined for this entry by sharepointdocumentlocation entity.
public void Execute(IServiceProvider serviceProvider)
{
var context = (IPluginExecutionContext)
serviceProvider.GetService(typeof(IPluginExecutionContext));
var serviceFactory = (IOrganizationServiceFactory)
serviceProvider.GetService(typeof(IOrganizationServiceFactory));
var service =
serviceFactory.CreateOrganizationService(context.UserId);
//string query = "";
Guid targetId = Guid.Empty;
Guid userId = Guid.Empty;
string fileRelativeUrlBase64 = String.Empty;
string result = String.Empty;
switch (context.MessageName)
{
case "RetrieveMultiple":
FetchExpression currentQuery =
context.InputParameters["Query"] as FetchExpression;
if (currentQuery != null)
{
try
{
XDocument parsedQuery =
XDocument.Parse(currentQuery.Query);
var attribute = parsedQuery
.Descendants("attribute")
.Where(e =>
e.Attribute("name
").Value == "uds_jsoncontent")
.Select(e => e)
.FirstOrDefault();
if (attribute != null)
{
string targetIdStringValue = parsedQuery
.Descendants("condition")
.Where(e =>
e.Attribute("attribute") != null &&
e.Attribute("operator") != null &&
e.Attribute("value") != null &&
String.Equals(e.Attribute("
attribute").Value, "uds_targetid_string",
StringComparison.InvariantCultureIgnoreCase) &&
String.Equals(e.Attribute("
operator").Value, "eq", StringComparison.InvariantCultureIgnoreCase))
.Select(e => e.Attribute("value").Value)
.FirstOrDefault();
if (!String.IsNullOrWhiteSpace(
targetIdStringValue))
{
try
{
targetId = new Guid(
targetIdStringValue);
}
catch (Exception ex)
{
result = String.Format("
Error: {0}", ex.Message);
}
}
string userIdStringValue = parsedQuery
.Descendants("condition")
.Where(e =>
e.Attribute("attribute")
!= null &&
e.Attribute("operator")
!= null &&
e.Attribute("value")
!= null &&
String.Equals(e.Attribute("
attribute").Value, "uds_userid", StringComparison
.InvariantCultureIgnoreCase) &&
String.Equals(e.Attribute("
operator").Value, "eq", StringComparison
.InvariantCultureIgnoreCase))
.Select(e => e.Attribute("
value").Value)
.FirstOrDefault();
if (!String.IsNullOrWhiteSpace(
userIdStringValue))
{
try
{
userId = new Guid(userIdStringValue);
}
catch (Exception ex)
{
result = String.Format("
Error: {0}", ex.Message);
}
}
fileRelativeUrlBase64 = parsedQuery
.Descendants("condition")
.Where(e =>
e.Attribute("attribute
") != null &&
e.Attribute("operator
") != null &&
e.Attribute("value
") != null &&
String.Equals(e.Attribute("
attribute").Value, "uds_filepath", StringComparison
.InvariantCultureIgnoreCase) &&
String.Equals(e.Attribute("
operator").Value, "eq", StringComparison.InvariantCultureIgnoreCase))
.Select(e => e.Attribute("
value").Value)
.FirstOrDefault();
}
}
catch (Exception ex)
{
result = String.Format("Error: {0}", ex.Message);
}
}
break;
}
SharePointService sharepointService = new SharePointService();
if (targetId != Guid.Empty)
{
DocumentLocationService locService =
new DocumentLocationService(service);
try
{
var folders = locService.GetSharePointLocation(targetId);
result = sharepointService
.GetAllSharePointFilesJSON(folders);
}
catch (Exception ex)
{
result = String.Format("Error: {0}", ex.Message);
}
}
else if (!String.IsNullOrEmpty(fileRelativeUrlBase64))
{
result =
sharepointService.GetSharePointFileAsBase64(fileRelativeUrlBase64);
}
if (!String.IsNullOrWhiteSpace(result))
{
Entity sharepointResponse = new Entity("uds_sharepointfile")
{
Id = targetId
};
sharepointResponse["uds_jsoncontent"] = result;
EntityCollection outputEntities =
context.OutputParameters["BusinessEntityCollection"] as EntityCollection;
outputEntities.Entities.Clear();
outputEntities.Entities.Add(sharepointResponse);
}
}
public Dictionary<string, string>
GetSharePointLocation(Guid targetId)
{
Dictionary<string, string> pathDictionary =
new Dictionary<string, string>();
var query = new QueryExpression("sharepointdocumentlocation")
{
ColumnSet = new ColumnSet("relativeurl", "parentsiteorlocation"),
Criteria = new FilterExpression(LogicalOperator.Or)
{
Conditions =
{
new ConditionExpression("regardingobjectid",
ConditionOperator.Equal, targetId
}
}
};
var results = _service.RetrieveMultiple(query).Entities.Select(x =>
x.ToEntity());
foreach (var location in results)
{
if (!String.IsNullOrWhiteSpace(location.RelativeUrl
) && !pathDictionary.Keys.Contains(location.RelativeUrl))
{
pathDictionary.Add(location.RelativeUrl,
location.RelativeUrl);
}
}
return pathDictionary;
return pathDictionary;
}
Then the service receives data about every catalog content. At this time, only file preview is returned (not the whole file), which is received with SharePoint API.
| This article contains long codes. Please proceed to full version Microsoft Dynamics Portal and SharePoint integration. |

Like
Report
*This post is locked for comments