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

时间:2008-10-22 18:17:54

标签: wcf confirmation

如果我的服务器上有数百/数千台客户端计算机WCP,我是否应该回复“200 OK”类型的消息,说明我已收到数据并将其成功存储在数据库中?

这已经内置到WCF中了吗?

4 个答案:

答案 0 :(得分:18)

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

  1. 同步请求 - 响应
  2. 异步发送(使用单向服务点火和忘记)
  3. 异步请求 - 响应(使用单向服务的双工服务呼叫)
  4. 所有三个都显示不同的消息传递行为,应根据您的需要选择要使用的模式。

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

    选项1

    这是默认配置。

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

    选项2

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

      

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

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

    选项3

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


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

    正如Whisk所提到的,Juval Lowy有一篇文章涵盖了很多细节(以及更多!)here

    选项1

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

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

    [ServiceContract]
    interface IMyServiceContract
    {
        [OperationContract]       
        void DoSomeThing(InputMessage Message);
    }
    

    选项2

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

    [ServiceContract]
    interface IMyServiceContract
    {
        [OperationContract(IsOneWay = true)]       
        void DoSomeThing(InputMessage Message);
    }
    

    以这种方式装饰的方法必须只有返回类型的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);      
    }
    

    在客户端,您需要这样的设置回调:

    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);           
    

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

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

    需要注意的一件重要事情是,一开始就把我弄出来,就是要注意例外情况。如果你:

    • 消耗异常,您将不会收到错误警告(但会发生回调)

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

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

答案 1 :(得分:2)

默认情况下,除非抛出异常,否则您的服务将向客户端返回“OK”消息(即使您的服务方法指定了void返回类型)。客户端将等到收到此消息后再继续使用它。

因此,根据您的问题,您将获得默认情况下所需的行为。

如果您不想这样,我会同意Whisk并将您的操作标记为One Way(操作合同中的设置)。

祝你好运!

答案 2 :(得分:1)

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

我的偏好是使用one-wayduplex service服务调用,并使用该服务的回调合同来通知客户端失败。对回调合约herehere有很好的描述。

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

答案 3 :(得分:0)

我认为这个问题可以使用更多细节来正确回答。主要的,您目前使用哪种类型的绑定?

如果您正在使用支持可靠性的绑定,并且您只是想确保从客户端那个服务器确实收到了消息,那么只需打开可靠性就可以了。有了这个,WCF会自动地在会话的每一边说:   “你说对了?”   “我明白了。你明白了吗?”   “我明白了。”