cancel
Showing results for 
Search instead for 
Did you mean: 

Crystal Reports Server - Restful API & Parameters

mhswa
Discoverer
0 Kudos

 

Hi everyone,

I'm encountering a challenge while attempting to generate a transient report on our Crystal Server. The report, originally created with Crystal Reports Designer, works flawlessly when accessed through the BI interface. It prompts for a parameter, and upon receiving it, generates the report without any hitches.

However, the problem arises when I try to execute this same report through the RESTful API, aiming to pass the necessary parameter. Instead of the expected outcome, I'm met with generic error messages.



Failed to create report instance. Status code: InternalServerError
Response: <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<error>
    <error_code>RWS 00070</error_code>
    <message>Internal server error. (RWS 00070)</message>
</error>

I opted for the RESTful API over the Crystal Reports SDK because our setup doesn't utilize the runtime environment. The goal is to enable internal report generation across various computers seamlessly.

Here is my code from VS 2022

using System;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;

class Program
{
    static readonly HttpClient client = new HttpClient();

    static async Task Main(string[] args)
    {
        string baseUri = "http://servername.local:8080/biprws";
        string username = "user";
        string password = "password";
        string reportId = "6380";
        int pickslipNumber = 615710;

        string logonToken = await AuthenticateAndGetLogonToken(baseUri, username, password);
        if (string.IsNullOrEmpty(logonToken))
        {
            Console.WriteLine("Authentication failed.");
            return;
        }
        Console.WriteLine($"Authentication successful. Logon Token: {logonToken}");

        await CreateReportInstance(baseUri, reportId, logonToken, pickslipNumber);
    }

    static async Task<string> AuthenticateAndGetLogonToken(string baseUri, string username, string password)
    {
        string authUrl = $"{baseUri}/logon/long";
        var authPayload = $"<attrs xmlns='http://www.sap.com/rws/bip'>" +
                          $"<attr name='userName' type='string'>{username}</attr>" +
                          $"<attr name='password' type='string'>{password}</attr>" +
                          $"<attr name='auth' type='string' possibilities='secEnterprise,secLDAP,secWinAD'>secEnterprise</attr>" +
                          $"</attrs>";

        HttpContent content = new StringContent(authPayload, Encoding.UTF8, "application/xml");

        var response = await client.PostAsync(authUrl, content);

        if (response.IsSuccessStatusCode)
        {
            var data = await response.Content.ReadAsStringAsync();
            return ExtractLogonToken(data);
        }

        return null;
    }

    static string ExtractLogonToken(string xmlResponse)
    {
        var xDoc = XDocument.Parse(xmlResponse);
        XNamespace ns = "http://www.sap.com/rws/bip";
        var logonTokenElement = xDoc.Descendants(ns + "attr").FirstOrDefault(x => x.Attribute("name")?.Value == "logonToken");
        return logonTokenElement?.Value;
    }

    static async Task CreateReportInstance(string baseUri, string reportId, string logonToken, int pickslipNumber)
    {
        string url = $"{baseUri}/infostore/{reportId}/rpt/instance";

        string requestBody = $@"<feed xmlns='http://www.w3.org/2005/Atom'>
                                <title type='text'>Crystal Reports New Instance</title>
                                <entry>
                                    <title type='text'>SuppressData</title>
                                    <content type='application/xml'>
                                        <attrs>
                                            <attr name='value' type='boolean'>false</attr>
                                        </attrs>
                                    </content>
                                </entry>
                                <entry>
                                    <title type='text'>Report Parameter</title>
                                    <id>PickslipNumber</id>
                                    <content type='application/xml'>
                                        <attrs>
                                            <attr name='value' type='number'>{pickslipNumber}</attr>
                                        </attrs>
                                    </content>
                                </entry>
                            </feed>";

        HttpContent content = new StringContent(requestBody, Encoding.UTF8, "application/xml");

        client.DefaultRequestHeaders.Clear();
        client.DefaultRequestHeaders.Add("X-SAP-LogonToken", $"\"{logonToken}\"");

        var response = await client.PostAsync(url, content);

        if (response.IsSuccessStatusCode)
        {
            string instanceId = await response.Content.ReadAsStringAsync();
            Console.WriteLine($"Report instance created successfully. Instance ID: {instanceId}");
        }
        else
        {
            Console.WriteLine($"Failed to create report instance. Status code: {response.StatusCode}");
            Console.WriteLine($"Response: {await response.Content.ReadAsStringAsync()}");
        }
    }
}

Any insights or suggestions to overcome these errors would be greatly appreciated. Thank you in advance for your help!

Accepted Solutions (0)

Answers (0)