cancel
Showing results for 
Search instead for 
Did you mean: 

How Can I Refresh Document Using SAP Rest APIS?

Can4
Explorer
0 Kudos
429

I am using SAP BO rest services and getting document parameters with below code;

 

public string GetDocumentParameters(string documentId)
{
return _client.GetStringAsync($"{ServiceParameters.BaseUrl}/raylight/v1/documents/{documentId}/parameters").GetAwaiter().GetResult();
}

 

Then I am parsing result and display parameters in the asp.net webform aspx page. For example, above code return string name, datetime birthday etc. then I am generating textbox or datetimepicker etc. When the user fills in these parameters on the screen, I assign the data entered by the user to a class called RootObject. Json root object value is below;

 

{
  "parameters": {
    "parameter": [
      {
        "id": 0,
        "answer": {
          "values": {
            "value": {
              "@id": "08/01/2024"
            }
          }
        }
      },
      {
        "id": 1,
        "answer": {
          "values": {
            "value": {
              "@id": "08/02/2024"
            }
          }
        }
      },
      {
        "id": 2,
        "answer": {
          "values": {
            "value": {
              "@id": "Test Dealer"
            }
          }
        }
      },
      {
        "id": 3,
        "answer": {
          "values": {
            "value": {
              "@id": "Test Brand"
            }
          }
        }
      }
    ]
  }
}

 

Then I want to create reports according to the parameters it fills in. So this purpose I am using below code;

 

public DocumentResult GetDocument(string documentId, RootObject rootObject)
{
UpdateDocumentParameters(documentId, rootObject);
var documentResult = FetchDocumentContent(documentId);

return documentResult;
}

private void UpdateDocumentParameters(string documentId, RootObject rootObject)
{
var json = JsonConvert.SerializeObject(rootObject, new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
Formatting = Newtonsoft.Json.Formatting.Indented
});

var content = new StringContent(json, Encoding.UTF8, "application/json");
var requestUri = $"{ServiceParameters.BaseUrl}/raylight/v1/documents/{documentId}/parameters";

var response = _client.PutAsync(requestUri, content).GetAwaiter().GetResult();
response.EnsureSuccessStatusCode();
}

private DocumentResult FetchDocumentContent(string documentId)
{
var requestUri = $"{ServiceParameters.BaseUrl}/raylight/v1/documents/{documentId}/reports";
var documentReports = GetDocumentReports(requestUri);
var reports = ParseReports(documentReports);
var reportContents = new Dictionary<int, string>();
foreach (var reportId in reports.Select(r => r.Id))
{
var reportUrl = $"{requestUri}/{reportId}";
var reportContentDoc = GetReport(reportUrl);
reportContents[reportId] = reportContentDoc;
}

return new DocumentResult
{
ReportContents = reportContents,
Reports = reports
};
}

private XDocument GetDocumentReports(string url)
{
var response = _client.GetStringAsync(url).GetAwaiter().GetResult();
return XDocument.Parse(response);
}

private List<ReportDetail> ParseReports(XDocument document)
{
return document.Descendants("report")
.Select(ParseReportDetail)
.ToList();
}

private ReportDetail ParseReportDetail(XElement reportElement)
{
return new ReportDetail
{
Id = int.Parse(reportElement.Element("id").Value),
Name = reportElement.Element("name").Value,
Content = reportElement.Element("reference").Value
};
}

private string GetReport(string url)
{
return _client.GetStringAsync(url).GetAwaiter().GetResult();
}

[Serializable]
public class DocumentResult
{
public List<ReportDetail> Reports { get; set; }
public Dictionary<int, string> ReportContents { get; set; }
}

[Serializable]
public class ReportDetail
{
public int Id { get; set; }
public string Name { get; set; }
public string Content { get; set; }
}

 

The UpdateDocumentParameters method works correctly because when I look at the response in that method, it says The resource of type "Document" with identifier "XX" has been successfully updated. When I am look at the DocumentResult reports not affected this parameters. There are 3 reports for the sample document. What I expect is for the relevant reports to be filled according to the parameters I send, but only one of the 3 reports is filled and the other two are empty.

How Can I fix this problem?

View Entire Topic
Joe_Peters
Active Contributor
0 Kudos

Your code for submitting the prompts looks ok.  But I don't see anywhere in your code where you retrieve the report data, only the structure, so how are you determining that the two reports are not filled?

One suggestion for debugging -- after you've submitted the prompts for refresh, save the report with a different name.  Then open it in WebI.  If not all of the expected data is there, then it may be a problem with your prompts.  But if the data is there, then the problem is with the way you're retrieving the report data.

Can4
Explorer
0 Kudos

Hi @Joe_Peters  thanks for your reply.

You said "But I don't see anywhere in your code where you retrieve the report data". I retrieve data with below code.  

var requestUri = $"{ServiceParameters.BaseUrl}/raylight/v1/documents/{documentId}/reports";
var documentReports = GetDocumentReports(requestUri);
var reports = ParseReports(documentReports);
var reportContents = new Dictionary<int, string>();
foreach (var reportId in reports.Select(r => r.Id))
{
var reportUrl = $"{requestUri}/{reportId}";
var reportContentDoc = GetReport(reportUrl);
reportContents[reportId] = reportContentDoc;
}

With GetReport(reportUrl) method I retrieve the data. I am using {ServiceParameters.BaseUrl}/raylight/v1/documents/{documentId}/reports/{reportId} adress to get refreshed report information. Is it right?

Joe_Peters
Active Contributor
0 Kudos
documents/{documentId}/reports/{reportId} only gives you the report metadata. To get the data you have to specify an "accept" value. See section 8.2.9 in the documentation: https://help.sap.com/doc/1eeee826c0154c62a5cbd29359ecbc18/4.3.4/en-US/sbo43sp2_webi_restws_dg_en.pdf
Can4
Explorer
0 Kudos

@Joe_Peters  I edited code like below;

var requestUri = $"{ServiceParameters.BaseUrl}/raylight/v1/documents/{documentId}/reports";
var documentReports = GetDocumentReports(requestUri);
var reports = ParseReports(documentReports);
var reportContents = new Dictionary<int, string>();
foreach (var reportId in reports.Select(r => r.Id))
{
var reportUrl = $"{requestUri}/{reportId}";
var reportContentDoc = GetReport(reportUrl);
reportContents[reportId] = reportContentDoc;
}

private string GetReport(string url)
{
_client.DefaultRequestHeaders.Accept.Clear();
_client.DefaultRequestHeaders.Add("accept", "text/html");
return _client.GetStringAsync(url).GetAwaiter().GetResult();
}

but the GetReport method only returns the report template and the report does not come with data.

Joe_Peters
Active Contributor
0 Kudos
Using text/html for "accept" will generate an HTML result that looks like the report page when viewed in WebI. If you just want the plan data with no HTML formatting, then you can use text/plain or text/csv. You said it returns "the report template" -- do you mean that the generated HTML includes the report structure including headers but no report data? If so, then it likely means that the parameters you entered did not produce results on that report. My suggestion above of saving the report so you can open it in WebI may help here. You can see exactly how the prompt values are being used, and if there are any filters on the report that are resulting in nothing being displayed.
Can4
Explorer
0 Kudos
Okey, I will try. You said, save the report with a different name. Then open it in WebI. how can I do this operations in my code?
Joe_Peters
Active Contributor
0 Kudos
After refreshing, do a POST to /documents/{doc id}, and include this form: <document><name>{document name}</name><folderId>{folder ID}</folderId></document> See section 8.1.5 in the docs for more info. Note that if you want to overwrite the report rather than creating a new one, you can simply PUT that same URL, and not include form data.