Кастомизация
12
Дек
3

Фильтрация записей в Представлениях

Иногда клиенты предъявляют требования к реализации безопасности несколько большие, чем можно реализовать с помощью стандартного функционала (Ролей) CRM. Каждый раз при открытии Представления в CRM, платформа CRM выполняет запрос RetrieveMultiple. Плагин, который «висит» на этом запросе, может изменить его прежде он будет передан платформе CRM. Сейчас рассмотрим небольшой пример по изменению плагином данных, возвращаемых в Представление. Пример показывает добавление простого условия к запросу, но в реальности его можно усложнить и задавать условия, например, в зависимости от Пользователя, который вызвал срабатывание плагина.

Итак, предположим, что на форме Организации есть кастомный флажок «Скрытый» и по-умолчанию в Представления не должны выводится записи помеченные этим флажком. Код будет таков:

using System;
using System.Diagnostics;
using System.Linq;
using System.ServiceModel;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using Microsoft.Xrm.Sdk.Messages;

namespace filterPlugin
{
    public class RetrieveMultiple : Microsoft.Xrm.Sdk.IPlugin
    {
        public void Execute(IServiceProvider serviceProvider)
        {
            IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
            IOrganizationServiceFactory factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
            IOrganizationService service = factory.CreateOrganizationService(context.UserId);
            
            if (context.InputParameters.Contains("Query"))
            {
                if (context.InputParameters["Query"] is QueryExpression)
                {
                    // Получаем текущий фильтр
                    QueryExpression objQueryExpression = (QueryExpression)context.InputParameters["Query"];

                    // Формируем новое условие
                    ConditionExpression privateFlagCondition = new ConditionExpression()
                    { AttributeName = "new_private", Operator = ConditionOperator.Equal, Values = { false } };

                    // Добавляем условие в текущий фильтр
                    objQueryExpression.Criteria.AddCondition(privateFlagCondition);
                }
            }
        }
    }
}

Плагин нужно зарегистрировать на:

  • Нужный объект;
  • Сообщение RetrieveMultiple;
  • Стадия Pre;
  • Синхронно.

Здесь мы независимо от того, какие условия содержит исходный запрос, мы добавляем дополнительное условие, что автоматически делает нам недоступными для любых Представлений записи помеченные галкой «Скрытый».



З.Ы. мы также можем полностью переопределить исходный запрос, добавиви в QueryExpression новый фильтр:

using System;
using System.Diagnostics;
using System.Linq;
using System.ServiceModel;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using Microsoft.Xrm.Sdk.Messages;

namespace filterPlugin
{
    public class RetrieveMultiple : Microsoft.Xrm.Sdk.IPlugin
    {
        public void Execute(IServiceProvider serviceProvider)
        {
            IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
            IOrganizationServiceFactory factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
            IOrganizationService service = factory.CreateOrganizationService(context.UserId);
            
            if (context.InputParameters.Contains("Query"))
            {
                if (context.InputParameters["Query"] is QueryExpression)
                {
                    // Получаем текущий фильтр
                    QueryExpression objQueryExpression = (QueryExpression)context.InputParameters["Query"];

                    // Формируем новые условия
                    ConditionExpression privateFlagCondition = new ConditionExpression()
                    { AttributeName = "new_private", Operator = ConditionOperator.Equal, Values = { false } };

                    ConditionExpression owningUserCondition = new ConditionExpression() 
                    { AttributeName = "owninguser", Operator = ConditionOperator.EqualUserId, };

                    ConditionExpression owningTeamCondition = new ConditionExpression() 
                    { AttributeName = "owningteam", Operator = ConditionOperator.EqualUserTeams, };

                    // Добавляем условие в новый фильтр
                    FilterExpression newFilter = new FilterExpression() 
                    { FilterOperator = LogicalOperator.Or, Conditions = { privateFlagCondition, owningUserCondition, owningTeamCondition } };

                    // Добавляем фильтр в текущий запрос
                    objQueryExpression.Criteria.AddFilter(newFilter);
                }
            }
        }
    }
}
Комментарии (3)
  • Светлана 12.12.2011

    Здравствуйте!Помогите, пожалуйста, реализовать для пользователей видимость записей, например только по выбранным регионам? А так же, чтобы он мог формировать отчеты и расширенный поиск только по ним. Сложность заключается в том, что у разных пользователей разный список регионов, но некоторые регионы могут присутствовать и в том и в другом списке.

  • slivka_83 12.12.2011

    Добрый день!

    У Вас возникнут проблемы не только с Расширенным поиском, но и с выгрузкой в Excel например. Ваша задача в принципе реализцема, но нужно либо пользоваться способом описанным здесь (но в целом это не тревиальная доработка), либо делать у всех пользователей видимость только на себя и расшаривать на кого нужно конкретные записи (тоже достаточно сложная доработка). Но эти способы влекут за собой большие проблемы производительности, поэтому такие вещи лучше не реализовывать.

  • Filo 12.12.2011

    Подскажите, для вложенного представления требуется осуществлять фильтрацию на основе полей существующих на форме, тоесть к примеру:
    Сущность заявка, поля: адрес, этаж, планировка.
    Вложенное представление отображает список например квартир и на основании тех данных что введены в поля требуется отфильтровать данные в представлении, тоесть к примеру этаж с 3-5й соответственно квартиры в таком диапазоне этажей

*

code