Developer Discussions

Discuss topics with other Hexagon Geospatial Power Portfolio developers and experts to get the most out of our products.
Showing results for 
Search instead for 
Do you mean 
Reply
Highlighted
Contributor
Posts: 23
Registered: ‎11-09-2015
Accepted Solution

Custom Trigger Creation

[ Edited ]

Hi

 

I've created the following custom trigger to automate report generation, I've added a lot of debug statements to figure out exactly what is passed through and how it is used so please excuse.  This trigger gets called on an action:

 

 <WorkflowTrigger name="AutoGenerateTrigger" type="GeospaceCustomTrigger" method="action">
            <Param name="ReportsToGenerate" value="{FORM.DSReportGridVisible}"/>
            <Param name="Directory" value="C:\Program Files\Intergraph\GeoMedia SmartClient\Program\Workflows\TestReports\"/>
          </WorkflowTrigger>
          

 

namespace GeospaceCustomTrigger
{
    [ExtensibleType("GeospaceCustomTrigger")]
    public class GeospaceCustomTrigger : WorkflowTriggerBase
    {
        private IDescriptionProvider descriptionProvider;
        private IReportProvider reportProvider;
        

        public string Directory { get; set; }
        public string[] ReportsToGenerate { get; set; }

       
        

        public GeospaceCustomTrigger(IDescriptionProvider descriptionProvider, IReportProvider reportProvider)
            : base()
        {
           
            
            this.descriptionProvider = descriptionProvider;
            this.reportProvider = reportProvider;
        }

      

          public override void Execute()
        {
            Log.DefaultLog.Debug("Starting to Execute");
            
              

            var querystring = WorkflowControllerContext.RequestProvider.GetQueryString();
            var workflow = querystring["workflow"];           
            var nodeId = "FieldWorkEditDS";
            var reportName = "Structure";
            var reportFormat = "pdf";
            DomainObject domainObject = null;           

            var currentNode = descriptionProvider.GetWorkflowNodeDescription(nodeId, workflow);
             var formDescription = descriptionProvider.GetFormDescription(currentNode.Form, workflow); 

             
             if(ReportsToGenerate != null)
            {
                foreach (string reportId in ReportsToGenerate)
                {
                    Log.DefaultLog.Debug("Start Per report");
                    Log.DefaultLog.Debug("formDescription=" + formDescription);

                    Log.DefaultLog.Debug("WorkflowControllerContext=" + WorkflowControllerContext);
                    Log.DefaultLog.Debug("WorkflowData=" + WorkflowData);
                    Form form = Form.CreateForm(formDescription, WorkflowControllerContext, WorkflowData, domainObject,   ModelScopes.Report);
                 
                    Log.DefaultLog.Debug("Form done");

                    ReportResult reportResult = WorkflowControllerContext.ReportProvider.RenderReport(reportName, reportFormat, formDescription, new List<Form>() { form },
                new List<WorkflowData>() { WorkflowData });
                    Log.DefaultLog.Debug("Report done");

                    Log.DefaultLog.Debug("ReportId=" + reportId);
                    
                    string Id = reportId;

                    string reportNameNew = System.IO.Path.GetFileNameWithoutExtension(reportResult.FileName);
                    reportNameNew = reportNameNew + "_" + Id + System.IO.Path.GetExtension(reportResult.FileName);

                    Log.DefaultLog.Debug("ReportName" +  reportNameNew );

                    using (FileStream fs = new FileStream(Path.Combine(Directory, reportNameNew + "." + reportFormat), FileMode.Create))
                    {
                        fs.Write(reportResult.Data, 0, reportResult.Data.Length);
                        Log.DefaultLog.Debug("Create single file");
                    }

                    Log.DefaultLog.Debug("Files completed");
                }                  
            }
        }   
    }
}

It seems like the problem is happening in the Form Creation line

Here is the extract from the log file  It seems like the object used for form creation is valid, but maybe there is something missing?

 

14.12.2015 11:39:38 DEBUG - Starting to Execute
14.12.2015 11:39:38 DEBUG - Start Per report
14.12.2015 11:39:38 DEBUG - formDescription=AssessmentFormReport
14.12.2015 11:39:38 DEBUG - WorkflowControllerContext=Intergraph.Emea.Workflows.DatabaseWorkflowControllerContext
14.12.2015 11:39:38 DEBUG - WorkflowData=Intergraph.Emea.Workflows.WorkflowData
14.12.2015 11:39:38 ERROR - Controller Trigger has raised an exception in Action FireData.
System.FormatException: Input string was not in a correct format.
at System.Number.StringToNumber(String str, NumberStyles options, NumberBuffer& number, NumberFormatInfo info, Boolean parseDecimal)
at System.Number.ParseDecimal(String value, NumberStyles options, NumberFormatInfo numfmt)
at System.Convert.ToDecimal(String value, IFormatProvider provider)
at Intergraph.Emea.Workflows.FormFieldDataTypeConverter.ConvertValue(Object value, FormFieldDataType dataType)
at Intergraph.Emea.Workflows.FormField._CreateFormField(FormFieldDescription formFieldDescription, IWorkflowControllerContext workflowControllerContext, WorkflowData workflowData, DomainObject domainObject, ModelScopes modelScope, Boolean includeActions)
at Intergraph.Emea.Workflows.FormField.CreateFormField(FormFieldDescription formFieldDescription, IWorkflowControllerContext workflowControllerContext, WorkflowData workflowData, DomainObject domainObject)
at Intergraph.Emea.Workflows.Form.CreateForm(FormDescription formDescription, IWorkflowControllerContext workflowControllerContext, WorkflowData workflowData, DomainObject domainObject, ModelScopes modelScope)
at GeospaceCustomTrigger.GeospaceCustomTrigger.Execute()
at Intergraph.Emea.Workflows.TriggerController.ExecuteTriggers(TriggerExecution triggerExecution, IEnumerable`1 workflowTriggerDescriptions, IWorkflowControllerContext workflowControllerContext, WorkflowData workflowData)
at Intergraph.Emea.Workflows.TriggerController.ExecuteTrigger(IEnumerable`1 triggerNames, WorkflowNodeDescription nodeDescription, IWorkflowControllerContext workflowControllerContext, WorkflowData workflowData)
at Intergraph.Emea.Workflows.TriggerController.FireData(List`1 triggerNames, DomainObject domainObject)
at lambda_method(Closure , ControllerBase , Object[] )
at System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters)
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters)
at System.Web.Mvc.Async.AsyncControllerActionInvoker.<BeginInvokeSynchronousActionMethod>b__39(IAsyncResult asyncResult, ActionInvocation innerInvokeState)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`2.CallEndDelegate(IAsyncResult asyncResult)
at System.Web.Mvc.Async.AsyncControllerActionInvoker.AsyncInvocationWithFilters.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3f()
at System.Web.Mvc.Async.AsyncControllerActionInvoker.AsyncInvocationWithFilters.<>c__DisplayClass48.<InvokeActionMethodFilterAsynchronouslyRecursive>b__41()
at System.Web.Mvc.Async.AsyncControllerActionInvoker.AsyncInvocationWithFilters.<>c__DisplayClass48.<InvokeActionMethodFilterAsynchronouslyRecursive>b__41()
at System.Web.Mvc.Async.AsyncControllerActionInvoker.AsyncInvocationWithFilters.<>c__DisplayClass48.<InvokeActionMethodFilterAsynchronouslyRecursive>b__41()
at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass33.<BeginInvokeActionMethodWithFilters>b__32(IAsyncResult asyncResult)
at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass21.<>c__DisplayClass2b.<BeginInvokeAction>b__1c()
at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass21.<BeginInvokeAction>b__1e(IAsyncResult asyncResult)

 

 

Hope someone can help!

Please let me know if you need anything else - thanks!

Highlighted
Occasional Contributor
Posts: 9
Registered: ‎11-09-2015

Re: Custom Trigger Creation

Hi Anchen,

 

It seems the issue is in the internal procedure of CreateForm, in fact the exception has generated at

 

Intergraph.Emea.Workflows.FormField._CreateFormField(FormFieldDescription formFieldDescription, IWorkflowControllerContext

 

I don't know the details of the original form that you want to create, but maybe you can exclude or not that depends of it trying with an empty one.

 

Let me know please

 

Cheers

Azzurra

 

 

 

 

Highlighted
Contributor
Posts: 23
Registered: ‎11-09-2015

Re: Custom Trigger Creation

Hi Azzurra

 

Sorry for the delay in replying I've been on leave. 

I've tried sending through an empty or null Form but keep getting errors so I assume it is not allowed. 

 

There must be something wrong with the construction of my Form but I am not sure what. 

Each of the objects seems to be valid, except the domainObject which is null

 

 

Form form = Form.CreateForm(formDescription, WorkflowControllerContext, WorkflowData, domainObject, ModelScopes.Report);
Highlighted
Community Manager
Posts: 167
Registered: ‎10-09-2015

Re: Custom Trigger Creation

Hi Anchen,

please find a working sample of such a custom trigger here:
https://bitbucket.org/HGDN/hgdn_gmsc/src/2eef0f0f7111d9de952d94e8f91052c2bc6946c7/IntegratedSamples/... (you must be HGDN Member to be able to access the shared samples). 

What is needed is a valid DomainObject as the system needs the values that have to be used to create the report. 

Could it be that your form description is not correct - means that there seems to be a field using datatype number but actually it seems to be a string (first guess). Otherwise, could you create a valid DomainObject that is not null matching the current entity (just like in the sample)?

 

Regards

Thomas

Thomas Anzinger
Community Manager
thomas.anzinger@hexagongeospatial.com
Highlighted
Contributor
Posts: 23
Registered: ‎11-09-2015

Re: Custom Trigger Creation

Hi Thomas

 

I've tried implementing your example of the Domain Object but it seems that there is some problem in my case with the followng line:

 WorkflowData.GetValue(PlaceholderType.Form, currentFormDescription.IdField)

If I try this in the If statement

 WorkflowData.Contains(PlaceholderType.Form, currentFormDescription.IdField)

 it doesn't pass and if I ommit the If then I get the error:

Controller Trigger has raised an exception in Action FireData.
System.ArgumentNullException: Value cannot be null.
Parameter name: id

 

The individual values seems valid. I tried to investigate each of the fields as well to see if I can find one that is supposed to be number but is actually string but coudn't find the problem yet. 

Highlighted
Community Manager
Posts: 167
Registered: ‎10-09-2015

Re: Custom Trigger Creation

[ Edited ]

Hi Anchen,

so it looks like you do not get any form data posted. The action that you use to call the trigger is placed on the same form that you use in the trigger and if so, is the form filled with the correct values?
Could you pass the FormAction definition used to call the trigger and the WorkflowNode-Definition + WorkflowTrigger-Definition for the current node?

 

Regards

Thomas

Thomas Anzinger
Community Manager
thomas.anzinger@hexagongeospatial.com
Highlighted
Contributor
Posts: 23
Registered: ‎11-09-2015

Re: Custom Trigger Creation

No that is the problem the action is not on the form with the data..

 

The form with the roport on is the detail of one structure

The action is on the the list of structures as I need to select the list of reports to generate automatically.

 

It used to work great when it was manually done Select one structure from list, open up detail of one structure and create report of that one structure. 

But now for the automated run from the reports, I need to mark which ones on the list need to be created. So I haven't loaded the detail form yet. 

Highlighted
Community Manager
Posts: 167
Registered: ‎10-09-2015

Re: Custom Trigger Creation

So what you need is a FormTable (with selectionmode="multiple") that shows the list of items so that the user may select the items that should be used to generate the report. Is this correct or is there a different behavior?

 

In your trigger you want to iterate over the selected items and create a report for each of them. Is this correct too?

 

If so, you could create the report like this will be returned as 1 pdf containing the content for all selected items):

//the FormTable must be like this:
//<FormTable idField="ID" datatype="string" selectionmode="multiple" ....>
string[] selectedItems = WorkflowData.GetValue<string[]>(PlaceholderType.Form, "ItemsFormTable");
List<DomainObject> domainObjects = new List<DomainObject>();
List<WorkflowData> workflowData = new List<WorkflowData>();
List<Form> forms = new List<Form>();
FormDescription currentFormDescription = WorkflowControllerContext.DescriptionProvider.GetFormDescription(FormName, WorkflowControllerContext.Workflow);
foreach(string item in selectedItems)
{
    DomainObject domainObject = WorkflowControllerContext.GetDatabase().SelectById(GetDomainObjectMetadata(currentFormDescription), item);             
    WorkflowData copyWorkflowData = WorkflowData.Copy();
    forms.Add(Form.CreateForm(FormDescription, WorkflowControllerContext, copyWorkflowData, domainObject, ModelScopes.Report));
    workflowData.Add(copyWorkflowData);
}
ReportResult reportResult = WorkflowControllerContext.ReportProvider.RenderReport(reportName, reportFormat, FormDescription, forms, workflowData);

Please be aware that this is only a sample code so please take care of adding some checks,...

 

Regards

Thomas

Thomas Anzinger
Community Manager
thomas.anzinger@hexagongeospatial.com
Highlighted
Contributor
Posts: 23
Registered: ‎11-09-2015

Re: Custom Trigger Creation

[ Edited ]

Hi Thomas

I do use it like you suggested but the problem is that because the table has too many fields that can't be displayed. I use a hidden table with most of the fields and then have the table that gets displayed (with selectionmode multiple) with only a few fields. 

 

I also have a FormMap field that display the structure plus a few Image fields that gets poppulated by a trigger and stored in session and all of this only happen on the next form. Smiley Sad

Highlighted
Community Manager
Posts: 167
Registered: ‎10-09-2015

Re: Custom Trigger Creation

Hi,

this is not really a problem, it only makes things a bit more complicated ;-)

Therefore you can load whatever FormDescription is needed and fits the current content of your DomainObject(s). 

Thomas Anzinger
Community Manager
thomas.anzinger@hexagongeospatial.com