我刚刚有一个关于 svcutil 从 WSDL 生成的 WCF 客户端与使用具有正确参数的 HttpClient 进行调用的一般性问题。在最近与外部 API 集成之前,我什至不知道 WCF 的存在。他们为我们提供了一个 WSDL,我能够使用 svcutil 命令在 C# 中生成客户端,我将其导入我的项目并在我的配置中添加绑定,一切都运行良好。我可以使用下面的模型来调用它。
using (ServiceClient client = new ServiceClient())
{
System.Xml.XmlElement resp = client.GetAllItems(new ItemRequest() { Key = "License Key"});
var items = DataSerializer.DeserializeXml<ExternalItemCollection>(resp.InnerXml);
foreach (var item in items)
{
_logger.LogInfo("Item Id is" + item.Id);
}
}
生成的客户端的唯一问题是调用“client.GetAllItems()”需要大约 1200 毫秒才能完成,如果我通过另一个程序(如 SOAP UI)运行该服务,它会在大约 3000 毫秒内返回 XML 字符串。我不知道生成的客户端的开销是多少(就像我说过在此之前从未使用过 WCF 哈哈哈)但是因为它是生成的并且我无法控制 WSDL 我一直在寻找优化它的方法.我的假设是,由于生成的所有调用都返回“System.Xml.XmlElement”,这让我觉得它在后台进行了某种反序列化和解析,但我终究无法弄清楚为什么整个调用是与 SOAP UI 相比,花费的时间几乎是 4 倍。
我决定尝试在 POSTMAN 中重新创建整个请求,只需设置标头和正文并在 3000 毫秒内返回。因此,我决定编写一个 PoC,并使用具有正确标头和正文的 HttpClient 库创建整个请求。整个请求在 3000 毫秒内返回。
using (var client = new System.Net.Http.HttpClient())
{
client.DefaultRequestHeaders.TryAddWithoutValidation("apikey", request.Key);
client.DefaultRequestHeaders.TryAddWithoutValidation("SOAPAction", "http://url.for.wcf/GetAllItems");
client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "text/xml");
var getAllItemsReq = $@"<soapenv:Envelope xmlns:soapenv=""http://schemas.xmlsoap.org/soap/envelope/"">
<soapenv:Header>
<web:AuthInfo>
<web:LicenseKey>{request.Key}</web:SiteID>
</web:AuthInfo>
</soapenv:Header>
<soapenv:Body>
<web:GetAllItems>
<web:status>Current</web:status>
</web:GetAllItems>
</soapenv:Body>
</soapenv:Envelope>";
var resp = client.PostAsync("https://api.external.vendor/service.svc", new System.Net.Http.StringContent(getAllItemsReq, System.Text.Encoding.UTF8, "text/xml"));
resp.Wait();
resp.Result.EnsureSuccessStatusCode();
var xmlResp = resp.Result.Content.ReadAsStringAsync();
xmlResp.Wait();
var xmlReader = System.Xml.XmlReader.Create(new System.IO.StringReader(xmlResp.Result));
xmlReader.ReadToDescendant("GetAllItemsResponse");
return xmlReader.ReadInnerXml();
}
我想我的问题是,通过 HttpClient 而不是使用由外部供应商提供的 WSDL 生成的 WCF 客户端来做这件事有什么大问题吗?或者,如果有人对我可以做些什么来优化 WCF 调用有什么建议,而不是像 Web 请求那样花费 4 倍的时间?
谢谢!