ASMX异步Web方法返回空响应

时间:2019-02-03 10:22:58

标签: c# .net asynchronous soap asmx

我有一个针对.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调用异步方法?

1 个答案:

答案 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);
    }

}