我在一些 BO REST 服务上遇到了同样的问题(其中一些在我们重新启动服务器后就消失了)。
您没有说明您使用哪种技术来调用 Web 服务,但这是您在 C# 应用程序中获取错误信息的方式。
在我的 C# 应用程序中,以下是我用来调用 GET & POST Business Objects 4.x REST 服务的函数,如果出现问题,它会尝试读取错误消息,因此我们得到的不仅仅是“404 not found” " 或 "503 服务器错误"...
要使用这些功能,您必须已登录 BO 并获得登录令牌。
protected string CallGETWebService(string URL, string token)
{
HttpWebRequest GETRequest = null;
try
{
GETRequest = (HttpWebRequest)WebRequest.Create(URL);
GETRequest.Method = "GET";
GETRequest.Accept = "application/xml";
GETRequest.Timeout = 3 * 60 * 1000; // Wait for upto 3 minutes
GETRequest.KeepAlive = false;
GETRequest.Headers.Add("X-SAP-LogonToken", token);
HttpWebResponse GETResponse = (HttpWebResponse)GETRequest.GetResponse();
Stream GETResponseStream = GETResponse.GetResponseStream();
StreamReader reader = new StreamReader(GETResponseStream);
string response = reader.ReadToEnd();
return response;
}
catch (WebException ex)
{
// If the web service throws an exception, attempt to see if it give us any clues about what went wrong.
string exception = GetExceptionMessage(URL, ex);
throw new Exception(exception);
}
}
protected string CallPOSTWebService(string URL, string token, string XMLdata)
{
try
{
// Call a "POST" web service, passing it some XML, and expecting some XML back as a Response.
byte[] formData = UTF8Encoding.UTF8.GetBytes(XMLdata);
HttpWebRequest POSTRequest = (HttpWebRequest)WebRequest.Create(URL);
POSTRequest.Method = "POST";
POSTRequest.ContentType = "application/xml";
POSTRequest.Accept = "application/xml";
POSTRequest.Timeout = 3 * 60 * 1000; // Wait for upto 3 minutes
POSTRequest.KeepAlive = false;
POSTRequest.ContentLength = formData.Length;
POSTRequest.Headers.Add("X-SAP-LogonToken", token);
Stream POSTstream = POSTRequest.GetRequestStream();
POSTstream.Write(formData, 0, formData.Length);
HttpWebResponse POSTResponse = (HttpWebResponse)POSTRequest.GetResponse();
StreamReader reader = new StreamReader(POSTResponse.GetResponseStream(), Encoding.UTF8);
string response = reader.ReadToEnd();
return response;
}
catch (WebException ex)
{
// If the web service throws an exception, attempt to see if it give us any clues about what went wrong.
string exception = GetExceptionMessage(URL, ex);
throw new Exception(exception);
}
}
protected string GetExceptionMessage(string URL, WebException ex)
{
// If one of the BO web service threw an exception, attempt to see if it give us any clues about what went wrong.
string exception = "An exception occurred whilst calling: " + URL + ", " + ex.Message;
try
{
if (ex.Response == null)
return exception;
if (ex.Response.ContentLength == 0)
return exception;
using (Stream sr = ex.Response.GetResponseStream())
{
// The web service will return a string containing XML, which we need to parse, to obtain the actual error message.
StreamReader reader = new StreamReader(sr);
string XMLResponse = reader.ReadToEnd();
XElement XML = XElement.Parse(XMLResponse);
XElement XMLException = XML.Elements().Where(e => e.Name.LocalName == "message").FirstOrDefault();
if (XMLException != null)
exception = XMLException.Value; // eg "Info object with ID 132673 not found. (RWS 000012)"
}
}
catch
{
// If the web service returned some other kind of response, don't let it crash our Exception handler !
}
return exception;
}
这里重要的是,如果 BO 的 REST 服务失败,GetResponse()
将抛出一个WebException
,然后我们使用我的GetExceptionMessage()
函数检查错误响应(BO REST 服务以 XML 格式返回)并尝试从中提取错误消息。
使用此功能,我们的 C# 代码可以抛出异常,其中包含一些有用的信息:
Info object with ID 132673 not found. (RWS 000012)
..而不是像这样抛出一个模糊的异常(顺便说一下,这是所有 SAP 自己的 C# 示例都会做的事情,因为没有一个包含任何错误处理)......
(404) Page not found
(503) Service unavailable
我也遇到过 BO REST 服务实际上会抛出“ (503) Service Unavailable
”异常的情况......这完全是误导!同样,此代码将有助于向我们提供真正的错误消息。
如果 BO 的 REST 服务成功,它们将返回一个包含一些 XML 数据的字符串。让我们看一些示例代码,展示我们如何使用我的函数调用 REST 服务以获取有关特定 Webi 报告的详细信息。
我们将调用 REST 服务,然后将 XML 响应字符串转换为XElement
,这样我们就可以从 XML 中获取报告的名称。
string token = /* Your login-token */
string URL = string.Format("http://MyServer:6405/biprws/infostore/{0}", ReportID);
string WebiReportResponse = CallGETWebService(URL, token);
// Parse the web service's XML response, and obtain the name of our Webi Report
XElement ReportDetails = XElement.Parse(WebiReportResponse);
XElement title = ReportDetails.Elements().Where(e => e.Name.LocalName == "title").FirstOrDefault();
string ReportName = (title == null) ? "Unknown" : title.Value;
我彻底厌恶 SAP 文档(并且缺少它)。
如果 SAP 自己提供一些这样的示例 .Net 代码,生活会容易得多……