Если у меня есть сотни/тысячи клиентских компьютеров, подключающихся к моему серверу через WCP, должен ли я ответить сообщением типа «200 OK», в котором говорится, что я получил данные и успешно сохранил их в базе данных?
Это уже встроено в WCF?
Если у меня есть сотни/тысячи клиентских компьютеров, подключающихся к моему серверу через WCP, должен ли я ответить сообщением типа «200 OK», в котором говорится, что я получил данные и успешно сохранил их в базе данных?
Это уже встроено в WCF?
Здесь упоминаются три шаблона обмена сообщениями:
Все три демонстрируют различное поведение при обмене сообщениями, и шаблон, который будет использоваться, следует выбирать в зависимости от ваших потребностей.
Для вашего требования возвращать клиенту сообщение об успешном завершении, когда данные были сохранены в базе данных, подходят варианты 1 или 3.
Это конфигурация по умолчанию.
Это возвращает ответ 200 по тому же http-соединению после того, как служба выполнила все свои задачи. Это означает, что вызовы службы будут блокироваться в ожидании ответа — ваш клиент будет зависать до тех пор, пока служба не выполнит запись в базу данных и не сделает все необходимое.
Возвращает ответ 202, если транспортный уровень и уровень инфраструктуры обмена сообщениями работают успешно. Возвращенный код 202 означает, что сообщение было принято. Из http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html:
Запрос принят в обработку, но обработка не завершена. (...) Ответ 202 намеренно ни к чему не обязывает.
Это означает, что ваш клиент продолжит выполнение, как только инфраструктура службы успешно запустит службу, и вы не получите никакой информации о том, был ли вызов базы данных успешным или нет.
Подобно варианту 2, ответ представляет собой http 202, а не 200, но теперь, когда вы вызываете службу от клиента, вы предоставляете объект InstanceContext
, который указывает объект для обработки обратного вызова. Клиент восстанавливает управление, и новый поток асинхронно ожидает ответа службы, информирующего вас об успехе или неудаче.
Ниже приведены дополнительные сведения о реализации этих шаблонов в WCF. После написания это довольно долго, но есть пара полезных комментариев, а также код.
Как упомянул Виск, у Ювала Лоуи есть статья, в которой подробно описывается (и не только!) здесь
Это поведение по умолчанию в WCF, поэтому вам не нужно ничего делать — оно работает с множеством различных привязок, включая wsHttpBinding и basicHttpBinding.
Следует отметить, что поведение, описанное с вашим клиентом, зависающим в ожидании ответа 200, происходит, даже если у вас есть пустая операция, например:
[ServiceContract]
interface IMyServiceContract
{
[OperationContract]
void DoSomeThing(InputMessage Message);
}
Чтобы установить операцию как одностороннюю, вы просто оформляете ее следующим образом:
[ServiceContract]
interface IMyServiceContract
{
[OperationContract(IsOneWay = true)]
void DoSomeThing(InputMessage Message);
}
Методы, оформленные таким образом, должны иметь только возвращаемый тип void. Одна из проблем заключается в том, что служба будет успешно построена, и вы не получите исключение о том, что конфигурация службы недействительна, пока вы не подключитесь к ней.
Код интерфейса для создания дуплексной службы обратного вызова:
[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 возвращает исключение при возникновении необработанного исключения.
По умолчанию ваша служба будет возвращать клиенту сообщение «ОК» (даже если ваш метод службы указывает тип возвращаемого значения void), если не будет выбрано исключение. Клиент будет ждать, пока не получит это сообщение, прежде чем продолжить свою жизнь.
Итак, исходя из вашего вопроса, вы получаете поведение, которое хотите по умолчанию.
Если вы этого не хотите, я бы согласился с Whisk и пометил вашу операцию как One Way (настройка в вашем контракте на операцию).
Удачи!
Это можно сделать двумя способами: вернуть значение из вашего вызова wcf, указывающее на успех или неудачу, или предположить успех и использовать обратный вызов, чтобы сообщить клиенту, есть ли проблема.
Я бы предпочел использовать односторонний сервисный вызов с дуплексная служба и использовать контракт обратного вызова для службы, чтобы уведомить клиента неудачи. Хорошее описание контрактов обратного вызова можно найти здесь и здесь.
Я думаю, что вы получите более красивую, более асинхронную архитектуру, если пойдете по второму пути, но для простых приложений может быть проще просто возвращать успех или неудачу.
Я думаю, что вопрос мог бы использовать немного больше разработки, чтобы ответить правильно. Первичный, какой тип привязки вы используете в настоящее время?
Если вы используете привязку, которая поддерживает надежность, и вы просто хотите быть уверены со стороны клиента, что этот сервер действительно получил сообщение, тогда просто включите надежность, и все готово. Когда это включено, WCF автоматически заставит каждую сторону разговора сказать: «Вы поняли?» — Я понял. Ты понял? "Я понял."