Skip to content

Ошибка “System.ArgumentException: propertyName” на форме для кастомных классов

Ошибка “System.ArgumentException: propertyName” на форме для кастомных классов published on 2 комментария к записи Ошибка “System.ArgumentException: propertyName” на форме для кастомных классов

Вы создали собственный класс, привязали к нему форму, отредактированную в Authoring Tool, и всё вроде бы замечательно. Но при попытке использовать форму в SCSM консоль падает, а в логе Operations Manager на компьютере, где запускается консоль, появляется ошибка “System.ArgumentException: propertyName”.

А происходит это потому, что SCSM как солдат в армии – выполняет ровно те приказы, которые ему отдают. И когда вы нацеливаете кастомизированную форму на класс, то SCSM при открытии формы загружает только свойства класса. Но обычно форма использует связанные объекты, к примеру связанные инциденты, создатель объекта, на кого назначено и т.д. И при попытке обратиться к этим связанным классам форма “падает”, т.к. SCSM их не загрузил.

Чтобы этого избежать, форма всегда (вернее, почти всегда – если форма не использует связанные классы, она может быть нацелена и на сам класс) должна быть нацелена не на сам класс, а на type projection (в русской версии консоли SCSM это называется “комбинированные классы”, далее используется сокращение TP). В этом случае при открытии формы будут загружать все связанные классы и форма сможет нормально работать.

Для того, чтобы это сделать, нужно посмотреть, на базе какого TP сделана изначальная форма и скопировать его. Сделать это можно и “руками” в базе данных, но это потребует несколько шагов, так что проще это сделать с помощью PowerShell и SMLets.

Следующий скрипт принимает на вход имя класса и выводит форму, которая связана с данным классом или любым из его TP. Также скрипт имеет параметр –ReturnTarget, который позволяет выводить класс или TP, на который нацелена форма (перед его вызовом необходимо импортировать модуль SMLets):

param([string]$className, [switch]$ReturnTarget)

$cl = Get-SCSMClass -Name "$className$"
$allIds = @{$cl.Id=$cl}

$tps = Get-SCSMTypeProjection | ? {$_.TargetType -eq $cl} | % { $allIds.Add($_.Id, $_)}

$form = Get-SCSMForm | ? { $allIds.Keys -contains $_.Target.Id}
if($ReturnTarget)
{
    return $allIds[$form.Target.Id]
}
else
{
    return $form
}

К примеру, вы создали новый класс на базе класса “Запрос на обслуживание”. Найдем форму для этого класса с помощью скрипта:
image
и в режиме –ReturnTarget:
image

Как видно, форма нацелена на ТР System.WorkItem.ServiceRequestProjection. Теперь нам необходимо скопировать определение этого TP в свой пакет управления. Для этого необходимо узнать, в каком пакете управления содержится TP. Почти все типы в SCSM поддерживают метод GetManagementPack(), поэтому узнать пакет также не сложно с помощью скрипта:

.\Get-SCSMFormByClassName.ps1 "System.WorkItem.ServiceRequest" -ReturnTarget | % {$_.__base.GetManagementPack()}

Обратите внимание, что сам тип при использовании SMLets “экранирован” и содержится в свойстве __base (впереди два символа подчеркивания). Вывод команды:
image
Пакет запечатан, поэтому у нас остается два пути: лезть в базу данных или использовать инструменты для экспорта данных из пакетов управления. Я предпочитаю первый путь. Запрос к БД будет выглядеть следующим образом:

USE ServiceManager
SELECT MPName,MPFriendlyName, CONVERT(xml, MPXML), MPIsSealed FROM ManagementPack
where
MPName = 'ServiceManager.ServiceRequest.Library'

С помощью этого запроса вы можете прямо в SQL Managemetn Studio открыть XML-код и посмотреть содержимое пакета управления. Поиском строки “System.WorkItem.ServiceRequestProjection” находите определение TP и копируете его в свой пакет управления. После этого вам необходимо лишь вменить свойство Type для TP на имя вашего нового класса, дать новое имя (ID):
image
и изменить свойство Target для вашей формы на ID созданного TP.

Поделиться в соц. сетях

Primary Sidebar