Доска рекордов на WCF и RavenDB. Сервис
Несколько раз на работе делали миниигры — пасхалки на новый год или еще какой праздник. Каждый раз единственное, что не успевали — таблица рекордов. Ее и буду делать. Доска будет представлять собой сервис с 2 методами — добавить результат и получить топ n результатов.
Для начала создадим интерфейс сервиса — контракт в терминах WCF
/// <summary> /// Контракт сервиса доски рекордов. /// </summary> [ServiceContract] public interface IScoreBoard { /// <summary> /// Получить список лучших результатов. /// </summary> /// <param name="count">Количество результатов.</param> /// <returns>Список лучших результатов.</returns> [OperationContract] List<ScoreBoardResult> GetTopResults(int count); /// <summary> /// Добавить результат. /// </summary> /// <param name="result">Результат.</param> [OperationContract] void AddResult(ScoreBoardResult result); }
и класс, в котором будут храниться результаты
/// <summary> /// Результат в таблице рекордов. /// </summary> [DataContract] public class ScoreBoardResult { /// <summary> /// Игра. /// </summary> [DataMember] public string Game { get; set; } /// <summary> /// Код пользователя. /// </summary> [DataMember] public string UserCode { get; set; } /// <summary> /// Имя пользователя. /// </summary> [DataMember] public string UserName { get; set; } /// <summary> /// Набранные очки. /// </summary> [DataMember] public int Score { get; set; } }
Подробнее об атрибутах:
ServiceContract — атрибут контракта сервиса. Это интерфейс, по которому можно работать с сервисом.
OperationContract — метод интерфейса сервиса.
DataContract — данные, которые передаются между клиентом и сервером.
DataMember — свойство, которое передается при передаче класса, помеченного DataContract.
Теперь добавляем в конфиг приложения такой кусок:
<system.serviceModel> <services> <service name="ScoreBoardServer.ScoreBoardService" behaviorConfiguration="returnFaults"> <host> <baseAddresses> <add baseAddress="http://localhost:9875"/> </baseAddresses> </host> <endpoint address="net.tcp://localhost:9876/" binding="netTcpBinding" contract="ScoreBoardServer.IScoreBoard" /> <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" /> </service> </services> <behaviors> <serviceBehaviors> <behavior name="returnFaults"> <serviceMetadata httpGetEnabled="True"/> <serviceDebug includeExceptionDetailInFaults="True" /> </behavior> </serviceBehaviors> </behaviors> </system.serviceModel>
Осталось только добавить класс с реализацией самого сервиса:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)] internal class ScoreBoardService : IScoreBoard
Здесь InstanceContextMode.Single означает, что все запросы клиентов будет обрабатывать один и тот же экземпляр сервиса.
При старте приложения сервис запускается так:
using (var serviceHost = new ServiceHost(typeof(ScoreBoardService))) { serviceHost.Open(); Console.WriteLine("The service is ready."); Console.WriteLine("Press <ENTER> to terminate service."); Console.ReadLine(); serviceHost.Close(); }
Теперь, если открыть http://localhost:9875, то появится сообщение о том, что сервис успешно запущен. Можно приступать к клиенту и хранению данных. Об этом во второй части.