WCF和确认 - 我是否需要向客户发回'OK got it'?

10 wcf confirmation

如果我有数百/数千个客户端计算机WCP到我的服务器,我应该回复一个'200 OK'类型的消息,说明我收到数据并成功存储在数据库中?

这已经内置到WCF了吗?

Dav*_*all 18

这里提到了三种消息模式:

  1. 同步请求 - 响应
  2. 异步发送(使用单向服务发送和忘记)
  3. 异步请求 - 响应(单向服务的双工服务调用)

这三个都显示不同的消息传递行为,应根据您的需要选择要使用的模式.

对于在数据持久保存到数据库时向客户端返回成功的要求,选项1或3是合适的.

选项1

这是默认配置.

一旦服务完成其所有任务,这将在同一http连接上返回200响应.这意味着在等待响应时对服务的调用将被阻塞 - 您的客户端将挂起,直到服务已写入数据库并完成其他任何需要的操作.

选项2

只要传输层和消息传递基础结构层成功,就返回202响应.返回的202表示该消息已被接受.来自http rfc:

该请求已被接受处理,但处理尚未完成.(......)202回应是故意不承诺的.

这意味着只要服务基础结构成功启动了服务,您的客户端就会继续执行,并且您将不会收到有关数据库调用是否成功的信息.

选项3

与选项2类似,响应是http 202,而不是200,但现在当您从客户端调用服务时,您提供了一个InstanceContext指定处理回调的对象的对象.客户端重新获得控制权,并且新线程异步等待服务响应,通知您成功或失败.


以下是有关在WCF中实现这些模式的更多信息.写完之后,它很长,但有一些有用的注释和代码.

正如打蛋器提到,朱瓦尔·洛具有覆盖很多这个细节的文章(和更多!)在这里

选项1

这是WCF中的默认行为,因此您不需要执行任何操作 - 它适用于许多不同的绑定,包括wsHttpBinding和basicHttpBinding.

需要注意的一点是,即使您有一个无效的操作,您的客户端挂起等待200响应的行为也会发生:

[ServiceContract]
interface IMyServiceContract
{
    [OperationContract]       
    void DoSomeThing(InputMessage Message);
}
Run Code Online (Sandbox Code Playgroud)

选项2

要将操作设置为单向,您只需将其装饰为:

[ServiceContract]
interface IMyServiceContract
{
    [OperationContract(IsOneWay = true)]       
    void DoSomeThing(InputMessage Message);
}
Run Code Online (Sandbox Code Playgroud)

以这种方式装饰的方法必须只有返回类型的void.一个问题是该服务将很乐意构建,您将不会得到一个例外,说服务配置无效,直到您连接到它.

选项3

用于创建双工回调服务的接口代码是:

[ServiceContract(CallbackContract = typeof(IMyContractCallback))]
interface IMyContract
{
    [OperationContract(IsOneWay=true)]       
    void DoSomeThing(InputMessage Message);
}

public interface IMyContractCallback
{
    [OperationContract(IsOneWay = true)]
    void ServiceResponse(string result);      
}
Run Code Online (Sandbox Code Playgroud)

在客户端,你需要这样的东西来设置回调:

public class CallbackHandler : IMyContractCallback        
{
    #region IEchoContractCallback Members

    public void ServiceResponse(string result)
    {
        //Do something with the response
    }

    #endregion
}

// And in the client when you set up the service call:

InstanceContext instanceContext = new InstanceContext(new CallbackHandler());
MyContractClient client = new MyContractClient(instanceContext);

InputMessage msg = new InputMessage();

client.DoSomething(msg);           
Run Code Online (Sandbox Code Playgroud)

在服务中你可能会有一些代码,如:

class MyContractImplementation : IMyContract
{
    public void DoSomeThing(MyMessage Message)
    {

        string responseMessage;

        try
        {
           //Write to the database
           responseMessage = "The database call was good!";
        }
        catch (Exception ex)
        {
            responseMessage = ex.Message;
        }

        Callback.ServiceResponse(responseMessage);
    }
}
Run Code Online (Sandbox Code Playgroud)

需要注意的一件重要事情是,一开始就把我弄出来,就是要注意异常.如果你:

  • 消耗一个异常,你不会得到错误的警告(但回调会发生)

  • 抛出未处理的异常,服务将终止,客户端甚至不会收到回调.

与选项1相比,这是此方法的一大缺点,选项1将在抛出未处理的异常时返回异常.


Whi*_*isk 1

有两种方法可以做到这一点 - 从 wcf 调用返回一个值来指示成功或失败,或者假设成功并使用回调来告诉客户端是否存在问题。

我的偏好是使用带有双工服务的单向服务调用,并使用服务的回调协定来通知客户端失败。这里这里有关于回调合约的很好的描述。

我认为,如果您遵循第二条路径,您会得到一个更好、更异步的架构,但对于简单的应用程序,仅返回成功或失败可能会更容易。