Desta forma, segue um mecanismo para efetuar um CRUD no CRM, a partir do portal. O procedimento abaixo é um resumo do artigo criado pela UDS.
O exemplo abaixo faz uma atualização de status na tabela de apontamento.
1 - Criar a entidade PortalActions (escopo de organização), com os campos [new_action, new_parameters]
IMPORTANTE: Área de permissões do portal no Dyn365: Adicionar esta tabela no item [Permissões de Entidade], Escopo [Global], todos os privilégios, e no grid [Funções da Web], adicionar o [Administrador] e [Usuários Autenticados].
2 - Criar uma Page Template (chamada CustomActions) com o seguinte conteúdo Liquid:
{% assign action = request.params['action'] %}
{% assign parameters = request.params['parameters'] %}
{% fetchxml portalAction %}
<fetch>
<entity name="new_portalactions">
<attribute name="new_name" />
<filter type="and">
<condition attribute="new_action" operator="eq" value="{{action}}" />
<condition attribute="new_parameters" operator="eq" value="{{parameters}}" />
</filter>
</entity>
</fetch>
{% endfetchxml %}
{% for item in portalAction.results.entities %}
<p>{{ item.new_name }}</p>
{% endfor %}
3 - Criar o seguinte Plugin (Message: RetrieveMultiple, EntityName: portalaction, Stage: pre)
public class ActionPlugin : IPlugin
{
private IDictionary<string, Func<string, IOrganizationService, string>> _actionMap;
public ActionPlugin()
{
_actionMap = new Dictionary<string, Func<string, IOrganizationService, string>>() {
{ "UpdateAppointmentStatus", UpdateAppointmentStatus }
};
}
public void Execute(IServiceProvider serviceProvider)
{
var context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
var serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
var service = serviceFactory.CreateOrganizationService(null);
FetchExpression currentQuery = context.InputParameters["Query"] as FetchExpression;
if (currentQuery != null) {
XDocument parsedQuery = XDocument.Parse(currentQuery.Query);
var requestParameters = parsedQuery.Descendants("filter").Elements().ToDictionary(e => e.Attribute("attribute").Value, e => e.Attribute("value").Value);
if (requestParameters.ContainsKey("new_action") &&
requestParameters.ContainsKey("new_parameters") &&
_actionMap.ContainsKey(requestParameters["new_action"])) {
string parameters = Encoding.UTF8.GetString(Convert.FromBase64String(requestParameters["new_parameters"]));
parameters = parameters.Replace("\"", "");
string result = _actionMap[requestParameters["new_action"]](parameters, service);
var restulCollection = new EntityCollection();
Guid id = Guid.NewGuid();
restulCollection.Entities.Add(
new Entity("new_portalactions") {
Id = id,
Attributes =
{
{ "new_portalactionsid", id },
{ "new_result", result }
}
});
}
}
}
private string UpdateAppointmentStatus(string id, IOrganizationService service)
{
try {
var _state = new SetStateRequest();
_state.State = new OptionSetValue(1);
_state.Status = new OptionSetValue(2);
_state.EntityMoniker = new EntityReference("ENTITY_NAME", Guid.Parse(id));
var stateSet = (SetStateResponse)crmService.Execute(_state);
}
catch (Exception ex) {
return "Error: " + ex.Message;
}
return "Success";
}
}
4 - Criar a classe JS [CrmActionHelper] e EXECUTÁ-LA em uma Portal Page (ONLOAD da página)
CrmActionHelper = CrmActionHelper || { __namespace: true };
(function (CrmActionHelperNamespace) {
CrmActionHelperNamespace.Action = function (action, parameters) {
var request;
var url = "/CustomActions?action=" + action + "¶meters=" + prepareParameters(parameters);
var $result = $.ajax({
type: "GET",
dataType : "json",
url: url,
beforeSend: function(xhr) {
request = xhr;
},
error: function (jqXHR, textStatus, errorThrown) {
}
});
return { deferred: $result, request: request };
}
function prepareParameters(parameters) {
return btoa(JSON.stringify(parameters));
}
})(CrmActionHelper);
CrmActionHelper
.Action("UpdateAppointmentStatus", "ID DO APONTAMENTO")
.deferred
.done (function (result) {
});
That's it!