Recopilar errores
Un código AL puede capturar varios errores y mostrarlos en la interfaz de usuario. Esta característica, denominada errores coleccionables, puede simplificar los escenarios de validación. Concretamente, puede simplificar escenarios en los que a los usuarios se les presenta una lista de errores a corregir.
Normalmente, cuando se produce un error en un procedimiento, este se detiene en el primer error que encuentra. El uso de errores coleccionables pospondrá básicamente el control de errores hasta el final de la llamada al procedimiento. La implementación del código AL no se detendrá ante errores. En cambio, continuará hasta el final y recopilará los errores a medida que se produzcan.
AL incluye varios métodos, propiedades y atributos diseñados específicamente para la característica de errores coleccionables.
ErrorInfo.Create(String [, Boolean] [, var Record] [, Integer] [, Integer] [, String] [, Verbosity] [, DataClassification] [, Dictionary of [Text, Text]]): crea un nuevo objeto ErrorInfo.
ErrorInfo.Callstack(): especifica una pila de llamadas donde se ha recopilado el objeto ErrorInfo.
ErrorInfo.Collectible([Boolean]): especifica si el error es coleccionable mediante el uso de ErrorBehavior.Collect.
ErrorInfo.CustomDimensions([Dictionary of [Text, Text]]): un conjunto de dimensiones, especificado como un diccionario que se relaciona con el error.
ErrorInfo.FieldNo([Integer]): especifica el id. de campo que está relacionado con el error.
ErrorInfo.PageNo([Integer]): especifica el número de página que está relacionado con el error.
ErrorInfo.RecordId([RecordId]): especifica el id. de registro del error que está relacionado con el error.
ErrorInfo.SystemId([Guid]): especifica el id. de sistema del registro que está relacionado con el error.
ErrorInfo.TableId([Integer]): especifica el id. de tabla que está relacionado con el error.
ErrorInfo.AddAction(Text, Integer, Text): especifica una acción para el error.
El método AddAction acepta tres parámetros.
Título: la cadena de texto que aparece como título de la acción en la interfaz de usuario del error.
CodeunitID: el id. de codeunit que se ejecutará cuando la acción se inicie desde la interfaz de usuario de error. El codeunit debe contener al menos un método global para ser llamado por la acción de error. El método global debe tener un parámetro de tipo de datos ErrorInfo para aceptar el objeto ErrorInfo.
Nombre del método: el nombre del método en codeunit, que se especifica mediante el parámetro CodeunitID que desea ejecutar para la acción.
Los siguientes métodos están disponibles en el Tipo de datos del sistema para gestionar los errores recopilados. Puede invocar estos métodos utilizando la sintaxis de acceso a la propiedad.
System.HasCollectedErrors(): obtiene un valor que indica si los errores se han recopilado en el ámbito actual de recopilación de errores.
System.GetCollectedErrors([Boolean]): obtiene todos los errores recopilados en el ámbito de recopilación actual.
System.ClearCollectedErrors(): borra todos los errores recopilados del ámbito de recopilación actual.
Si borra la lista de errores recopilados, los cambios realizados en la base de datos no se revertirán. Por lo tanto, en la mayoría de los casos, tiene sentido combinar la operación de Borrar con una instrucción if Codeunit.Run then ....
El atributo ErrorBehavior especifica el comportamiento de los errores coleccionables dentro del ámbito del método. Agregar [ErrorBehavior(ErrorBehavior.Collect)] a un procedimiento hace posible recopilar y gestionar los errores que se generan en el ámbito del procedimiento.
En el siguiente ejemplo de código se ilustra cómo usar los errores coleccionables. Está creado alrededor de la codeunit DoPost, que establece criterios básicos sobre lo que se puede o no incluir en los campos de la tabla. Este procedimiento se detendrá cuando se produzcan errores.
Los procedimientos PostWithErrorCollect () y PostWithErrorCollectCustomUI () le muestran formas de recopilar y presentar estos errores aplicando el atributo ErrorBehavior(ErrorBehavior::Collect).
pageextension 50100 CollectingErrorsExt extends "Customer List"
{
actions
{
addfirst(processing)
{
// This action doesn't collect errors. Any procedure will stop on the first error that occurs,
// and return the error.
action(Post)
{
ApplicationArea = All;
trigger OnAction()
var
i: Record Integer;
begin
i.Number := -9;
Codeunit.Run(Codeunit::DoPost, i);
end;
}
// This action collects errors. The PostWithErrorCollect procedure continues on errors,
// and displays the errors in a dialog to the user done.
action(PostWithErrorCollect)
{
ApplicationArea = All;
trigger OnAction()
begin
PostWithErrorCollect();
end;
}
// This action collects errors. The PostWithErrorCollectCustomUI procedure continues on errors,
// and displays error details in a list page when done.
// This implementation illustrates how you could design your own UI for displaying and
// troubleshooting errors.
action(PostWithErrorCollectCustomUI)
{
ApplicationArea = All;
trigger OnAction()
begin
PostWithErrorCollectCustomUI();
end;
}
}
}
[ErrorBehavior(ErrorBehavior::Collect)]
procedure PostWithErrorCollect()
var
i: Record Integer;
begin
i.Number := -9;
Codeunit.Run(Codeunit::DoPost, i);
// After executing the codeunit, there will be collected errors,
// and therefore an error dialog will be shown when exiting this procedure.
end;
[ErrorBehavior(ErrorBehavior::Collect)]
procedure PostWithErrorCollectCustomUI()
var
errors: Record "Error Message" temporary;
error: ErrorInfo;
i: Record Integer;
begin
i.Number := -9;
// By using Codeunit.Run, you ensure any changes to the database within
// Codeunit::DoPost are rolled back in case of errors.
if not Codeunit.Run(Codeunit::DoPost, i) then begin
// If Codeunit.Run fails, a non-collectible error was encountered,
// add this to the list of errors.
errors.ID := errors.ID + 1;
errors.Description := GetLastErrorText();
errors.Insert();
end;
// If there are collected errors, iterate through each of them and
// add them to "Error Message" record.
if HasCollectedErrors then
foreach error in system.GetCollectedErrors() do begin
errors.ID := errors.ID + 1;
errors.Description := error.Message;
errors.Validate("Record ID", error.RecordId);
errors.Insert();
end;
// Clearing the collected errors will ensure the built-in error dialog
// will not show, but instead show our own custom "Error Messages" page.
ClearCollectedErrors();
page.RunModal(page::"Error Messages", errors);
end;
}
codeunit 50100 DoPost
{
TableNo = Integer;
trigger OnRun()
begin
if Number mod 2 <> 0 then
Error(ErrorInfo.Create('Number should be equal', true, Rec, Rec.FieldNo(Number)));
if Number <= 0 then
Error(ErrorInfo.Create('Number should be larger than 0', true, Rec, Rec.FieldNo(Number)));
if Number mod 3 = 0 then
Error(ErrorInfo.Create('Number should not be divisible by 10', true, Rec, Rec.FieldNo(Number)));
// Everything was valid, do the actual posting.
end;
}