我有一个针对.NET 4.5的Web服务,该服务实现了异步WebMethod和其他同步方法。同步方法可以正常工作。意思是,我使用WCF测试客户端应用程序调用它们,然后它们返回响应。但!异步网络方法似乎在return语句中返回了实际对象,但是没有任何内容返回到测试客户端。
我创建了一个示例。请考虑以下方法:
[WebMethod]
public int Test()
{
return 42;
}
我通过以下方式调用它:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://tempuri.org/Test</Action>
</s:Header>
<s:Body>
<Test xmlns="http://tempuri.org/" />
</s:Body>
</s:Envelope>
然后我得到答复:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<s:Header xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" />
<soap:Body>
<TestResponse xmlns="http://tempuri.org/">
<TestResult>42</TestResult>
</TestResponse>
</soap:Body>
</soap:Envelope>
到目前为止,一切都很好。但是当我尝试这样做时:
[WebMethod]
public async Task<int> Test()
{
await Task.Delay(10);
return 42;
}
然后调用:
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope">
<s:Header>
<Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://tempuri.org/Test</Action>
</s:Header>
<s:Body>
<Test xmlns:d3p1="http://schemas.datacontract.org/2004/07/" i:nil="true" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://tempuri.org/" />
</s:Body>
</s:Envelope>
我得到一个空的答复。我尝试返回的任何对象都会发生这种情况。
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<s:Header xmlns:s="http://www.w3.org/2003/05/soap-envelope" />
<soap:Body>
<TestResponse xmlns="http://tempuri.org/">
<TestResult />
</TestResponse>
</soap:Body>
</soap:Envelope>
这是在VS2017中完成的。类签名看起来像这样:
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
public class MyService : System.Web.Services.WebService
我需要更改什么,以便Web服务支持使用SOAP调用异步方法?
答案 0 :(得分:1)
Asynchronous Programming Model (APM)
使用IAsyncResult设计模式的异步操作是 实现为名为BeginOperationName和 开始和结束异步操作的EndOperationName 分别为OperationName。
下面的示例包括两个名为 SyncUpdateRecords 和 AsyncUpdateRecords 的Web方法。请仔细查看下面的继承类。
WebService1.asmx.cs
public class WebService1 : System.Web.Services.Protocols.SoapHttpClientProtocol
{
public WebService1()
{
this.Url = "http://localhost:61192/WebService1.asmx";
}
[WebMethod]
public string SyncUpdateRecords()
{
return "Records updated => sync";
}
[WebMethod]
public IAsyncResult BeginAsyncUpdateRecords(AsyncCallback cb, object state)
{
var updateRecords = new UpdateRecords();
return updateRecords.BeginUpdateRecords(cb, state);
}
[WebMethod]
public string EndAsyncUpdateRecords(IAsyncResult result)
{
return UpdateRecords.EndUpdateRecords(result);
}
}
UpdateRecords.cs
public class UpdateRecords
{
private static string SleepAndWake()
{
System.Threading.Thread.Sleep(1000);
return "Records updated => async";
}
private delegate string SleepAndWakeRecords();
private class RecordsState
{
public readonly SleepAndWakeRecords AsyncDelegate = new SleepAndWakeRecords(SleepAndWake);
}
public IAsyncResult BeginUpdateRecords(AsyncCallback cb, object s)
{
var state = new RecordsState();
return state.AsyncDelegate.BeginInvoke(cb, state);
}
public static string EndUpdateRecords(IAsyncResult result)
{
var returnDelegate = (RecordsState)result.AsyncState;
return returnDelegate.AsyncDelegate.EndInvoke(result);
}
}