Сервис на WCF поддерживает WS-Addressing, то есть способен писать и читать в заголовке поле ReplyTo
, в котором содержится адрес для ответа.
Почему-то быстро с этим разобраться мне не удалось, потому после продолжительных поисков я решил описать, как это происходит при написании клиента для WCF-сервиса.
В общем-то, ответ дан уже тут: How do I use WS-Addressing in WCF and set the wsa:replyto header, но мне этого в тот момент не хватило.
Итак, у нас есть WCF-сервис. И сразу же ограничение: его Binding должен поддерживать спецификацию WS-Addressing, то есть, например, BasicHttpBinding
не подойдёт, а вот WSHttpBinding
- вполне. Напомню, что Binding задаётся при создании сервиса.
И мы пишем клиент, который будет отправлять асинхронные запросы в этот сервис, причём нам нужно, чтобы сервис отвечал на определённый адрес, который может меняться (например, будет ещё несколько клиентов, и каждому нужны будут ответы на какой-то другой адрес). Поэтому на стороне сервиса мы не можем зашить определённый адрес для ответа. Для этого и предназначена спецификация WS-Addressing - в заголовке запроса, в специальном поле ReplyTo
, записывается адрес, на который требуется отправить ответ.
Итак, ссылку на сервис в клиент мы добавили, сгенерировались нужные классы, в конфиг записались необходимые секции. Вызываем веб-метод и пишем в заголовок адрес для ответа:
SomeService.ServicesomeClient someClient = new SomeService.ServicesomeClient("WSHttpBinding_IServiceSome"); // это имя binding'а из конфига using (OperationContextScope scope = new OperationContextScope(someClient.InnerChannel)) // вот где зарыты заголовки запроса { OperationContext.Current.OutgoingMessageHeaders.ReplyTo = new EndpointAddress("http://some.domain/service.asmx/result"); // и всё, а дальше вызываем уже метод сервиса someClient.request("ololo"); }
Теперь на стороне сервиса можно читать это поле в заголовке:
// веб-метод, который вызывается выше в клиенте (точнее, реализация интерфейса) public void request(string requestContent) { // читаем адрес для ответа из заголовка string replyto = OperationContext.Current.IncomingMessageHeaders.ReplyTo.ToString(); // и вот в строке replyto лежит http://some.domen/service.asmx/result }