AXForum  
Вернуться   AXForum > Microsoft Dynamics AX > DAX: Программирование
All
Забыли пароль?
Зарегистрироваться Правила Справка Пользователи Сообщения за день Поиск

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 27.12.2017, 22:02   #1  
sukhanchik is offline
sukhanchik
Administrator
Аватар для sukhanchik
MCBMSS
Злыдни
Лучший по профессии 2015
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,311 / 3547 (125) ++++++++++
Регистрация: 13.06.2004
Адрес: Москва
D365 FO Ссылка на конкретную запись. Параметры URL
Добрый день! В рамках исследования параметров URL, через которые можно задать те или иные команды системе были найдены следующие интересные моменты:

1. Встроенные команды.
https://community.dynamics.com/ax/b/...url-parameters
В том числе, наиболее интересные:
prt=[partitionID] - указание раздела, в котором будет проводиться работа
cmp=[legal entity] - указание компании, в которой будет проводиться работа
lng=[LanguageId] - указание языка интерфейса. Очень удобно, когда хочется посмотреть как одна и та же надпись выглядит как по-русски, так и по-английски
mi=[menuItem] - указание пункта меню, который требуется вызвать
f=[formName] - указание названия формы, которую нужно открыть напрямую, не через пункт меню
q=[queryString] - запрос, который передается на форму и позволяет отфильтровать данные формы

2. Запрос система может генерить сама (см https://axology.wordpress.com/2016/1...or-operations/). Для этого нужно в параметрах пользователя включить параметр "Автоматическое обновление параметров запроса"
Название: SNAG_Program-0018.png
Просмотров: 1643

Размер: 8.5 Кб
и воспользоваться расширенным фильтром на форме
Нажмите на изображение для увеличения
Название: SNAG_Program-0019.png
Просмотров: 521
Размер:	49.5 Кб
ID:	11798
Запрос зашифрован, однако если его расшифровать - то там будет строка вида Параметр1=Значение1&Параметр2=Значение2, где параметры - это поля фильтра запроса (по сути - предложение WHERE в SQL-запросе). Однако D365 принимает только зашифрованную строку, так что смысла в дешифровке особой нет. Возможно, есть параметры, при которых шифрование отключается - но я их пока не видел (в АХ 2012 и ранее на портале такой параметр был)

3. Каждый запускаемый объект имеет право самостоятельно определять дополнительные параметры URL, которые он готов принять. Пример - см класс SysTableBrowser и параметр TableName:
Нажмите на изображение для увеличения
Название: SNAG_Program-0020.png
Просмотров: 472
Размер:	27.3 Кб
ID:	11799

4. Есть официальная статья Create and use deep links, в которой приводится пример, как сгенерить URL-адрес, открывающий заданный пункт меню с заданным фильтром (Query)

X++:
// gets the generator instance
var generator     = new Microsoft.Dynamics.AX.Framework.Utilities.UrlHelper.UrlGenerator();
var currentHost   = new System.Uri(UrlUtility::getUrl());
generator.HostUrl = currentHost.GetLeftPart(System.UriPartial::Authority);
generator.Company = curext();
generator.MenuItemName = <menu item name>;
generator.Partition = getCurrentPartition(); 

// repeat this segment for each datasource to filter
var requestQueryParameterCollection = generator.RequestQueryParameterCollection;
requestQueryParameterCollection.AddRequestQueryParameter(
    <datasource name>,
    <field1>, <value1>,
    <field2>, <value2>,
    <field3>, <value3>,
    <field4>, <value4>,
    <field5>, <value5>
);

System.Uri fullURI = generator.GenerateFullUrl();

// to get the encoded URI, use the following code
fullURI.AbsoluteUri
Соответственно, на базе этого кода можно написать свой, который будет фильтровать по RecId и т.о. отображать текущие записи. Тут правда есть нюанс - в стародавние времена было модно сложные запросы вида %1.%2 == %3.%4 || %5.%6 == %7.%8 делать как Range по полю RecId, как по наиболее редко используемому полю в запросах. В этом случае фильтрация по RecID может работать некорректно. Поэтому я немного видоизменил код и попробовал фильтроваться по первичному ключу:

X++:
    public str generateFullURL()
    {
        str ret;
        FormRun formRun = element.args().caller();
        FormDataSource formDS = formRun.dataSource();
        if (formRun && formRun.isRootNavigable())
        {
            System.Uri host = SessionContext::Get_Current().Get_RequestUrl();
            UrlHelper.UrlGenerator generator = new UrlHelper.UrlGenerator();
            generator.MenuItemName = formRun.args().menuItemName();
            generator.MenuItemType = formRun.args().menuItemType();
            generator.HostUrl = host.GetLeftPart(System.UriPartial::Path);
            generator.Company = curExt();
            generator.EncryptRequestQuery = true;
            Microsoft.Dynamics.AX.Framework.Utilities.UrlHelper.RequestQueryParameterCollection requestQueryParameterCollection = generator.RequestQueryParameterCollection;
            DictTable dictTable = new DictTable(formDS.cursor().TableId);
            FieldId primaryKey = dictTable.primaryKeyField();
            if (!primaryKey)
            {
                primaryKey = fieldnum(Common, RecId);
            }
            requestQueryParameterCollection.AddRequestQueryParameter(formDS.name(), fieldId2Name(dictTable.id(), primaryKey), strfmt("%1", formDS.cursor().(primaryKey)));
            
            ret = generator.GenerateFullUrl().AbsoluteUri;
        }
        
        return ret;
    }
Осталась последняя деталь - этот код надо вывести на форму, которая открывается при нажатии на кнопку "Получить ссылку" на закладке Параметры
Нажмите на изображение для увеличения
Название: SNAG_Program-0021.png
Просмотров: 485
Размер:	19.7 Кб
ID:	11800

Здесь вызывается пункт меню FormRunGetLinkAction, который вызывает одноименную форму.
Теперь есть 2 варианта, как вставить наш код в эту форму (без оверлеинга):

А. Добавить Post-обработчик на метод run формы и в контрол Link записать наш текст. Это легкий способ, но он перезатирает стандартную функциональность
Б. Добавить Post-обработчик на метод run формы и добавить в рантайме динамически новый контрол.

Расширение (Extension) к самой форме создать не получится - установленные паттерны на ней не позволяют без ошибок компиляции добавить статический контрол. А менять паттерны Extension не разрешает.

Пойдем вторым путем (вариант Б). Не забудем вставить проверку существования контрола, на случай, если кнопку "Получить ссылку" попробуют нажать при уже открытой форме
X++:
    public void postRun()
    {
        this.showFullLink();
    }

    public void showFullLink()
    {
        if (element.args() && element.args().caller() && element.args().callerType() == UtilElementType::Form)
        {
            FormStringControl ctrlFullLink = this.ctrlFullLink();
            if (!ctrlFullLink)
            {
                ctrlFullLink = element.design().addControl(FormControlType::String, ctrlFullLinkName);
            }
            ctrlFullLink.allowEdit(false);
            ctrlFullLink.displayLengthMode(this.ctrlLink().displayLengthMode());
            ctrlFullLink.displayLength(this.ctrlLink().displayLength());
            ctrlFullLink.label("@SYS22569");
            ctrlFullLink.text(this.generateFullURL());
        }
    }
Теперь осталось самая малость - оформить все в полноценный класс

X++:
using Microsoft.Dynamics.AX.Framework.Utilities;
using Microsoft.Dynamics.@Client.ServerForm.Contexts;

class FormRunGetLinkActionHandler
{
    FormRun  element;
    private const str ctrlFullLinkName = "FullLink";
    
    
    public FormRun formRun (FormRun _formRun = element)
    {
        element = _formRun;
        return element;
    }

    public static FormRunGetLinkActionHandler construct(FormRun _formRun)
    {
        FormRunGetLinkActionHandler handler = new FormRunGetLinkActionHandler();
        handler.formRun(_formRun);
        return handler;
    }

    public str generateFullURL()
    {
        str ret;
        FormRun formRun = element.args().caller();
        FormDataSource formDS = formRun.dataSource();
        if (formRun && formRun.isRootNavigable())
        {
            System.Uri host = SessionContext::Get_Current().Get_RequestUrl();
            UrlHelper.UrlGenerator generator = new UrlHelper.UrlGenerator();
            generator.MenuItemName = formRun.args().menuItemName();
            generator.MenuItemType = formRun.args().menuItemType();
            generator.HostUrl = host.GetLeftPart(System.UriPartial::Path);
            generator.Company = curExt();
            generator.EncryptRequestQuery = true;
            Microsoft.Dynamics.AX.Framework.Utilities.UrlHelper.RequestQueryParameterCollection requestQueryParameterCollection = generator.RequestQueryParameterCollection;
            DictTable dictTable = new DictTable(formDS.cursor().TableId);
            FieldId primaryKey = dictTable.primaryKeyField();
            if (!primaryKey)
            {
                primaryKey = fieldnum(Common, RecId);
            }
            requestQueryParameterCollection.AddRequestQueryParameter(formDS.name(), fieldId2Name(dictTable.id(), primaryKey), strfmt("%1", formDS.cursor().(primaryKey)));
            
            ret = generator.GenerateFullUrl().AbsoluteUri;
        }
        
        return ret;
    }

    public void postRun()
    {
        this.showFullLink();
    }

    public void showFullLink()
    {
        if (element.args() && element.args().caller() && element.args().callerType() == UtilElementType::Form)
        {
            FormStringControl ctrlFullLink = this.ctrlFullLink();
            if (!ctrlFullLink)
            {
                ctrlFullLink = element.design().addControl(FormControlType::String, ctrlFullLinkName);
            }
            ctrlFullLink.allowEdit(false);
            ctrlFullLink.displayLengthMode(this.ctrlLink().displayLengthMode());
            ctrlFullLink.displayLength(this.ctrlLink().displayLength());
            ctrlFullLink.label("@SYS22569");
            ctrlFullLink.text(this.generateFullURL());
        }
    }

    public FormStringControl ctrlLink()
    {
        return element.design().controlName(formControlStr(FormRunGetLinkAction, Link));
    }

    public FormStringControl ctrlFullLink()
    {
        return element.design().controlName(ctrlFullLinkName);
    }

    [PostHandlerFor(formStr(FormRunGetLinkAction), formMethodStr(FormRunGetLinkAction, run))]
    public static void FormRunGetLinkAction_Post_run(XppPrePostArgs _args)
    {
        FormRunGetLinkActionHandler handler = FormRunGetLinkActionHandler::construct(_args.getThis());
        handler.postRun();
    }

}
На выходе мы получаем:
Нажмите на изображение для увеличения
Название: SNAG_Program-0022.png
Просмотров: 570
Размер:	109.0 Кб
ID:	11805
По нижней ссылке можно открыть одну отфильтрованную запись.

Ну и можно приложить модель (я все делал в отдельной модели) - файл axmodel (выгружался из PU10), выгруженный проект (axpp-файл) и решение (solution) в студии, чтобы пример было удобно открыть из студии
SysGetFullShareLink-VSUH.axmodel.rar
SysGetFullShareLink.axpp
SysGetFullShareLink_Project.rar
__________________
Возможно сделать все. Вопрос времени

Последний раз редактировалось sukhanchik; 28.12.2017 в 13:49.
За это сообщение автора поблагодарили: mazzy (10), S.Kuskov (2), belugin (10), Logger (10), raz (10), Jorj (1), Ivanhoe (10), trud (7), gl00mie (10).
Теги
d365o, deep link, полезное

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
Кликабельная URL-ссылка в отчёте tindomka DAX: Программирование 2 01.06.2017 23:06
dynaxtips: The URL Parameters Blog bot DAX Blogs 0 21.03.2017 03:13
Позиционирование на конкретную запись датасета Lucky13 DAX: Программирование 8 21.12.2005 19:26
Ошибка при импорте демоданных (Axapta 3.0 CIS SP1) KocDm DAX: Администрирование 2 11.08.2005 12:04

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 11:17.