4.1 API example for docs/reports

Discussions related to custom development with Select.
PeterKelly
Posts: 92
Joined: Tue Feb 04, 2014 3:34 pm

4.1 API example for docs/reports

Post by PeterKelly »

Can somebody please provide an example of how to generate a doc(which is really a report) in 4.1

For 4.0 we ran load tests on docs like Order Notes which were really reports that were generated by Crystal on the app server.

We accomplished this with an unofficial DLL RenderDoc.dll and we now need to understand how this is done in 4.1.

Thanks,
Peter
BobRichards
Posts: 1377
Joined: Wed Jan 15, 2014 3:50 pm
Location: Raleigh, NC
Contact:

Re: 4.1 API example for docs/reports

Post by BobRichards »

This is slated to be included in the next SDK accompanying Select 4.1.1. I will post a short example when it is done.
Bob Richards, Senior Software Developer, SoftPro
PeterKelly
Posts: 92
Joined: Tue Feb 04, 2014 3:34 pm

Re: 4.1 API example for docs/reports

Post by PeterKelly »

Bob,

We have a 4.1 loadtest scheduled for next week.

When do you think you will have time to create an example?

Thanks,
Peter
BobRichards
Posts: 1377
Joined: Wed Jan 15, 2014 3:50 pm
Location: Raleigh, NC
Contact:

Re: 4.1 API example for docs/reports

Post by BobRichards »

Here is a simple example. It opens an order and prints the Barcode Cover Sheet as a PDF. Be sure to build against .NET 4.6. (More examples coming.)

Code: Select all

using SoftPro.Documents.Client;
using SoftPro.Documents.Client.Rendering;
using SoftPro.OrderTracking.Client.Orders;
using SoftPro.Select.Client;
using SoftPro.Select.Documents.Shared;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace RenderDocWithoutUserPrompts
{
    class Program
    {
        static void Main(string[] args)
        {
            using (SelectServer ss = new SelectServer(new Uri("http://localhost:8080")))
            {
                string reason;
                if (!ss.TryAuthenticate(out reason))
                {
                    // Write login failure reason to console and exit.
                    Console.WriteLine(reason);
                    return;
                }

                // Fetch the desired order from the order store.
                IOrderStore os = ss.GetService<IOrderStore>();
                IOrderInfo search = os.Orders.Where(t => t.Number == "XAT16000014").FirstOrDefault();

                // Exit if didn't find order.
                if (search != null)
                {
                    // Open order in read-only mode (that's all that's needed for our purposes).
                    IOrder iorder = os.OpenOrder(search, true);

                    // Get a simple document that needs no user input - the barcode cover sheet.
                    IDocumentManager docMgr = ss.GetService<IDocumentManager>();
                    IDocumentInfo docInfo = docMgr.Documents
                        .Where(t => t.Title == "Barcode Cover Sheet").First();

                    // Create in-memory document.  No user input is necessary so passing null to prompts.
                    IRendererFactory renderFactory = ss.GetService<IRendererFactory>();
                    IRenderer renderer = renderFactory.Create();
                    IRendering rendering = renderer.Render(docInfo, iorder, null);

                    // Render the in-memory document as a PDF and write it to disk.
                    using (Stream file = File.Create("Barcode.pdf"))
                    {
                        Stream docStream = rendering.Export(DocumentFormat.PortableDocumentFormat);
                        docStream.Seek(0, SeekOrigin.Begin);
                        docStream.CopyTo(file);
                    }
                }
            }
        }
    }
}
Bob Richards, Senior Software Developer, SoftPro
BobRichards
Posts: 1377
Joined: Wed Jan 15, 2014 3:50 pm
Location: Raleigh, NC
Contact:

Re: 4.1 API example for docs/reports

Post by BobRichards »

And here is an example where the document requires user prompts to be answered - programmatically. The responses to the document prompts are created in a separate class and passed to the Render() method. For each prompt requested, we examine the Text member and compare it against the prompt text we are expecting. When we find the matching one, we cast it to the appropriate request object that has type specific properties to set. In these cases, the IValueRequest is the target type that provides a way to provide a single value response (of any type). In one case we answer with a string and in another we pass a boolean. In any case, be sure to set the Handled property to true. The object also have a bool that can be set to handle the "Skip remaining prompts". Other prompt type examples to follow.

Code: Select all

using SoftPro.Documents.Client;
using SoftPro.Documents.Client.Rendering;
using SoftPro.OrderTracking.Client.Orders;
using SoftPro.Select.Client;
using System;
using System.IO;
using System.Linq;

namespace RenderDocWithUserPrompts
{
    class Program
    {
        static void Main(string[] args)
        {
            using (SelectServer ss = new SelectServer(new Uri("http://localhost:8080")))
            {
                string reason;
                if (!ss.TryAuthenticate(out reason))
                {
                    // Write login failure reason to console and exit.
                    Console.WriteLine(reason);
                    return;
                }

                // Fetch the desired order from the order store.
                IOrderStore os = ss.GetService<IOrderStore>();
                IOrderInfo search = os.Orders.Where(t => t.Number == "TestOrder2").FirstOrDefault();

                // Exit if didn't find order.
                if (search != null)
                {
                    // Open order in read-only mode (that's all that's needed for our purposes).
                    IOrder iorder = os.OpenOrder(search, true);

                    // Get a simple document that requires user prompts.
                    IDocumentManager docMgr = ss.GetService<IDocumentManager>();
                    IDocumentInfo docInfo = docMgr.Documents
                        .Where(t => t.Title == "ALTA Loan Policy (6-17-06)").First();

                    // Create instance of class that has all the answered prompts needed by the document.
                    RenderPrompts prompts = new RenderPrompts();

                    // Create in-memory document and pass prompts.
                    IRendererFactory renderFactory = ss.GetService<IRendererFactory>();
                    IRenderer renderer = renderFactory.Create();
                    IRendering rendering = renderer.Render(docInfo, iorder, prompts);

                    // Render the in-memory document as a PDF and write it to disk.
                    using (Stream file = File.Create("ALTA Loan Policy.pdf"))
                    {
                        Stream docStream = rendering.Export(DocumentFormat.PortableDocumentFormat);
                        docStream.Seek(0, SeekOrigin.Begin);
                        docStream.CopyTo(file);
                    }
                }
            }
        }
    }

    /// <summary>
    /// Class with answers to all prompts required by document.
    /// </summary>
    class RenderPrompts : IPrompt<PromptEventArgs>
    {
        public void Request(PromptEventArgs value)
        {
            // Handle requests one at a time.  Examine the prompt then cast to appropriate response type.
            //  Here we handle requests for single values - a string then a boolean.
            //  Other request types are possible...
            foreach (var prompt in value.Requests)
            {
                if (prompt.Text == "Witness clause ALTA")
                {
                    // Handle request for a string value.
                    IValueRequest response = (IValueRequest)prompt;
                    response.Handled = true;
                    response.Value = "This is the witness clause information...";
                }
                else if (prompt.Text.StartsWith("Select if optional Item 6 (endorsement incorporation)"))
                {
                    // Handle request for a boolean value.
                    IValueRequest response = (IValueRequest)prompt;
                    response.Handled = true;
                    response.Value = true;
                }
            }
        }
    }
}
Bob Richards, Senior Software Developer, SoftPro
PeterKelly
Posts: 92
Joined: Tue Feb 04, 2014 3:34 pm

Re: 4.1 API example for docs/reports

Post by PeterKelly »

Bob,

Thanks for the 2 examples!

What happens if you don't handle prompts? Is it equivalent to just clicking OK on the options screen?

I tried that with one of the docs and did not get any errors.

Thanks,
Peter
BobRichards
Posts: 1377
Joined: Wed Jan 15, 2014 3:50 pm
Location: Raleigh, NC
Contact:

Re: 4.1 API example for docs/reports

Post by BobRichards »

If no response is "Required", then you can pass null to the Render() method and it is perfectly happy.
Bob Richards, Senior Software Developer, SoftPro
BobRichards
Posts: 1377
Joined: Wed Jan 15, 2014 3:50 pm
Location: Raleigh, NC
Contact:

Re: 4.1 API example for docs/reports

Post by BobRichards »

This example shows the second of three types of responses you might need to handle cases where you are required to enter an item(s) from a list of options provided by the document prompt. In this case, we use the IRequest.ID to determine the desired response instead of the IRequest.Text as in the other examples. IRequest.ID is the preferred member to use.

Since you know that your request will require you to choose from a list, cast the IRequest to an ISelectionRequest object. Then you will have a collection of acceptable responses (ISelectionRequest.Available). Pass one, none, or multiple as required by the specific request.

Code: Select all

...
if (prompt.ID == "ORDERTYPE")
{
    // Handle request for a boolean value.
    ISelectionRequest response = (ISelectionRequest)prompt;
    response.Handled = true;
    response.Selected = new object[] { response.Available["Policy"] };
    return;
}
Bob Richards, Senior Software Developer, SoftPro
BobRichards
Posts: 1377
Joined: Wed Jan 15, 2014 3:50 pm
Location: Raleigh, NC
Contact:

Re: 4.1 API example for docs/reports

Post by BobRichards »

And finally the last type of response object - IRequestRange. In this example, the document is passing multiple prompts to the program, but all we want to enter for the "Orders Received" report is the period of time specifying the last 30 days. We are ignoring all the other prompts since they are optional.

We are also showing examples of using the generic versions of the IRequest family members. By providing the data type (since you know it ahead of time), use the generic versions so you can detect errors at build time if you pass the wrong type.

Code: Select all

class RenderPrompts : IPrompt<PromptEventArgs>
{
	public void Request(PromptEventArgs value)
	{
		foreach (var prompt in value.Requests)
		{
			if (prompt.ID == "ORDERDATERANGE")
			{
				// Handle request for a string value.
				IRangeRequest<DateTime> response = (IRangeRequest<DateTime>)prompt;
				response.Handled = true;
				response.Value = Range<DateTime>.Bound(DateTime.Now.AddDays(-30), DateTime.Now);
			}
		}
	}
}
Bob Richards, Senior Software Developer, SoftPro
PeterKelly
Posts: 92
Joined: Tue Feb 04, 2014 3:34 pm

Re: 4.1 API example for docs/reports

Post by PeterKelly »

Bob,

I'm trying to generate 4.1.3 Disclosure docs in our WA loadtest environment but get a "Missing parameter values" exception.

What does this exception mean?

If I manually create the doc in the UI I am not required to enter any options, I just press OK.

Similarly named docs in our IL environment work using he same code.

Any ideas?

Thanks,
Peter


Event[0]:
Log Name: Application
Source: SoftPro Select Server
Date: 2016-07-21T22:37:58.000
Event ID: 0
Task: N/A
Level: Error
Opcode: Info
Keyword: Classic
User: N/A
User Name: N/A
Computer: JTCSSPSAPP99Q-T.fnfglobal.local
Description:
Work task failed. Error: One or more errors occurred.
Stack Trace:

***********************************************************************************
Error: Missing parameter values.

Stack Trace:

Server stack trace:
at System.ServiceModel.Channels.ServiceChannel.HandleReply(ProxyOperationRuntime operation, ProxyRpc& rpc)
at System.ServiceModel.Channels.ServiceChannel.EndCall(String action, Object[] outs, IAsyncResult result)
at System.ServiceModel.Channels.ServiceChannelProxy.InvokeEndService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)

Exception rethrown at [0]:
at SoftPro.Reporting.Server.ReportingController.SoftPro.Reporting.Server.IReportingController.EndRunReport(IAsyncResult result)
at SoftPro.Reporting.Server.ReportAnalyzerService.<>c__DisplayClass3_0.<RunReport>b__0(IProgress`1 p, CancellationToken c)
at System.Threading.Tasks.Task.Execute()
Post Reply