Показаны сообщения с ярлыком WCF. Показать все сообщения
Показаны сообщения с ярлыком WCF. Показать все сообщения

13 января 2013 г.

Фильтрация IP адресов при доступе к WCF сервису

Продолжая тему разработки REST сервисов на платформе WCF, хотелось бы поговорить о способах защиты ваших сервисов от несанкционированного доступа. В этой статье мы поговорим о такой мере защиты, как ограничение доступа на основе фильтрации по IP адресу.

Используя технологии от Microsoft такую возможность можно обеспечить на разных программных уровнях. Далее мы посмотрим как можно включить IP фильтр на сервере IIS и как контролировать доступ к методам на уровне WCF.

29 сентября 2012 г.

Разработка REST сервиса при помощи WCF.


Всем привет! Сегодня мы поговорим о подходе для разработки сетевой архитектуры под названием REST и способах его реализации на платформе .NET при помощи Windows Communication Foundation.
Для начала, разберемся, что такое REST и с чем его едят. В основе архитектуры REST лежит 3 основополагающих принципа:
  1. Протокол передачи данных HTTP. Для обмена данными между клиентом и сервисом используются классические запросы с командами HTTP: GET, POST, PUT, DELETE (получение, добавление, обновление и удаление данных соответственно);
  2. Ресурсно-ориентированная архитектура. Взаимодействие с сервисом – это обмен данными между клиентом и определенным ресурсом, расположенным на сервисе. При этом каждый ресурс обладает уникальным адресом (URI). Не правда ли, очень похоже на схему функционирования сети Интернет в целом?
  3. Формат передаваемых данных: XML или JSON.

2 сентября 2012 г.

Использование привязки Duplex Binding в WCF


Добрый день. Сегодня мы рассмотрим один из нестандартных типов связи, который предоставляет разработчикам Windows Communication Foundation - двухстороння связь или Duplex mode.
Классической схемой взаимодействия клиента с сервисом является режим запрос - ответ. Клиент посылает сервису запрос и немедленно получает от сервиса ответ с данными. Однако такая схема не всегда способна удовлетворить потребности разработчика, особенно при разработке сервисных систем со сложной архитектурой.

21 апреля 2012 г.

Организация работы с базой данных посредством сервисов WCF

 

Часть 1. Создание тестовой базы данных.

   Целью данной статьи является создание сервиса при помощи технологии Windows Communication Foundation для демонстрации слоя доступа к базе данных в контексте сервис-ориентированной архитектуры.

  Первым шагом является разработка тестовой базы данных, к которой будут осуществляться запросы.

  Для этого выполним следующую последовательность действий:

  1) Открыть приложение Microsoft SQL Server Management Studio и подключится к серверу баз данных на локальном компьютере или на удаленном хосте;

  2) Создадим базу данных выполнив следующий скрипт:

CREATE DATABASE [ProductsDB] ON PRIMARY

( NAME = N'ProductsDB',

FILENAME = N'c:\Program Files\Microsoft SQL Server\MSSQL10_50.SQLEXPRESS\MSSQL\DATA\ProductsDB.mdf' ,

SIZE = 3072KB , FILEGROWTH = 1024KB )

LOG ON ( NAME = N'ProductsDB_log',

FILENAME = N'c:\Program Files\Microsoft SQL Server\MSSQL10_50.SQLEXPRESS\MSSQL\DATA\ProductsDB_log.ldf' ,

SIZE = 1024KB , FILEGROWTH = 10%) GO

   При необходимости можно изменить параметр FILENAME для файла базы данных и лог-файла.

   3) Создадим таблицу Products в ранее созданной базе данных ProductsDB, выполнив следующий скрипт:

USE [ProductsDB] GO

CREATE TABLE [dbo].[tb_Products]

( [Id] [int] IDENTITY(1,1) NOT NULL, [Name] [nvarchar](50) NOT NULL, [Description] [nvarchar](500) NOT NULL,

[Price] [int] NOT NULL, CONSTRAINT [PK_tb_Products] PRIMARY KEY CLUSTERED

( [Id] ASC ) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] GO

   4) Для тестирования различных способов взаимодействия с базой данных создадим тестовую хранимую процедуру, которая будет возвращать записи из таблицы tb_Products, у которых поле Name будет совпадать с параметром @Name, переданным в хранимую процедуру:

CREATE PROCEDURE sp_GetProductsByName

@Name nvarchar(50)

AS BEGIN

SELECT Id, Name, Description, Price FROM tb_Products WHERE Name LIKE '%' + @Name + '%';

END GO

   На этом создание тестовой базы данных завершено, теперь перейдем к созданию бизнесс логики для доступа к данным.

 

Часть 2. Разработка WCF сервиса.

Следующий этап – создание кода ля выполнения запросов к базе данных средствами языка программирования C#.

Откроем среду разработки Microsoft Visual Studio 2010 и создадим новый проект, выбрав тип проекта – ASP.NET Empty Web Application. Проекты на основе языка программирования ASP.NET идеально подходят для быстрого создания и развертывания сервисов WCF. Назовем проект «WCF_DataAccess».

clip_image002

Теперь приступим к созданию WCF сервиса. Перейдем в Solution Explorer и поставив курсор на узел проекта нажмем правую кнопку мыши. Далее в контекстном меню необходимо выбрать пункт «Add – New Item». Далее на вкладке Web нужно выбрать тип файла – «WCF Service». Назовем файл «DbService.svc».

clip_image004

Среда выполнения добавит в наш проект два новых файла «DbService.svc» и «IDbService.cs»:

clip_image005

Также необходимо создать вспомогательный класс ProductBO, который будет выполнять сразу несколько функций – это будет оболочка для записи из таблицы tb_Products, а также контракт данных для использования его в WCF. Сигнатура класса приведена ниже:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Runtime.Serialization;
namespace WCF_DataAccess

{
   [DataContract]
   public class ProductBO
   {
       [DataMember]
       public int Id { get; set; }
       [DataMember]
       public string Name { get; set; }
       [DataMember]
       public string Description { get; set; }
       [DataMember]
       public int Price { get; set; }
}
}

Аттрибут [DataContract] означет что этот класс может использоваться для передачи данных между сервисом WCF и его клиентами. Атрибут [DataMember] указывает какие поля данных должны быть включены в сообщение при передаче по каналам связи WCF.

Теперь мы можем перейти к написанию сервиса. Сервис в WCF сосотит из двух частей:

1) Контракт сервиса – это файл «IDbService.cs». В этом файле находится контракт сервиса – интерфейс на языке C#, который помечен атрибутом [ServiceContract]. Интерфейс содержит набор определений методов, которые помечены атрибутом [OperationContract]. Данный интерфейс называется контрактом сервиса, птомучто он декларирует точное описание методов, которые будет предоставлять своим клиентам WCF сервис. Код интерфейса приведен ниже:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
namespace WCF_DataAccess
{
     [ServiceContract]
      public interface IDbService
      {
          [OperationContract]
          List<ProductBO> GetAllProducts();
          [OperationContract]
          void InsertProduct(ProductBO product);
          [OperationContract]
          void DeleteProductById(int productId);
         [OperationContract]
         List<ProductBO> GetProductsByName(string name);
     }
}

2) Реализация сервиса – файл «DbService.svc». Здесь находится класс DbService, который наследует и реализует контракт сервиса – интерфейс IDbService. Поскольку мы будем работать с базой данных через наш сервис, класс DbService будет также реализовывать интерфейс IDisposable.

public class DbService : IDbService, IDisposable

Класс будет содержать одно поле и конструктор:

private SqlConnection _connection;
public DbService()
{
    string connectionString = ConfigurationManager.ConnectionStrings["ProductsDBConnectionString"].ConnectionString;
    _connection = new SqlConnection(connectionString);
    _connection.Open();
}

В конструкторе создается соединение с базой данных. Строка соединения берется из файла конфигурации Web.config, где она имеет следующий вид:

<configuration>
     <connectionStrings>
            <add name="ProductsDBConnectionString" connectionString="Data Source=.\SQLEXPRESS;Initial Catalog=ProductsDB;Integrated Security=True" />
      </connectionStrings>

Приступим к реализации методов сервиса:

Выборка всех продуктов из таблицы:

public List<ProductBO> GetAllProducts()
{
       string query = "SELECT Id, Name, Description, Price FROM tb_Products";
       SqlCommand command = new SqlCommand(query, _connection);
       SqlDataReader dataReader = command.ExecuteReader();
       List<ProductBO> products = new List<ProductBO>();
       while (dataReader.Read())
      {
            products.Add(new ProductBO()
           {
               Id = dataReader.GetInt32(0),
               Name = dataReader.GetString(1),
               Description = dataReader.GetString(2),
               Price = dataReader.GetInt32(3)
          });
     }
     return products;
}

Добавление записи в таблицу продуктов:

public void InsertProduct(ProductBO product)
{
       string query = "INSERT INTO tb_Products VALUES (@name, @desc, @price);";
       SqlCommand command = new SqlCommand(query, _connection);
       command.Parameters.Add(new SqlParameter()
       {
            DbType = DbType.String,
            Value = product.Name,
            ParameterName = "name"
      });
      command.Parameters.Add(new SqlParameter()
      {
           DbType = DbType.String,
           Value = product.Description,
           ParameterName = "desc"
     });
     command.Parameters.Add(new SqlParameter()
     {
          DbType = DbType.Int32,
          Value = product.Price,
          ParameterName = "price"
     });
     command.ExecuteNonQuery();
}

Удаление продукта из таблицы по его Id:

public void DeleteProductById(int productId)
{
        string query = "DELETE FROM tb_Products WHERE Id = @id";
        SqlCommand command = new SqlCommand(query, _connection);
        command.Parameters.Add(new SqlParameter()
       {
            DbType = DbType.Int32,
            Value = productId,
            ParameterName = "id"
       });
       command.ExecuteNonQuery();
}

Выборка продуктов с фильтрацией продуктов по полю Name, при помощи хранимой процедуры:

public List<ProductBO> GetProductsByName(string name)
{
         SqlCommand command = new SqlCommand();
         command.Connection = _connection;
         command.CommandType = CommandType.StoredProcedure;
        command.CommandText = "sp_GetProductsByName";
        command.Parameters.Add(new SqlParameter()
        {
             DbType = DbType.String,
             Value = name,
             ParameterName = "Name"
        });
        SqlDataReader dataReader = command.ExecuteReader();
        List<ProductBO> products = new List<ProductBO>();
        while (dataReader.Read())
        {
              products.Add(new ProductBO()
              {
                    Id = dataReader.GetInt32(0),
                    Name = dataReader.GetString(1),
                    Description = dataReader.GetString(2),
                    Price = dataReader.GetInt32(3)
              });
       }
       return products;
}

И последний метод – член интерфейса IDisposable – Dispose:

public void Dispose()
{
       _connection.Close();
}

Данный метод будет вызываться автоматически после завершения работы сервиса.

На этом написание кода сервиса завершено. Попробуем его запустить, для этого в Solution Explorer необходимо установить курсор на файл DbService.svc и в контекстном меню выбрать пункт “View In Browser”. После нажатия откроется окно браузера. Адрес страницы, которая откроется в браузере, и будет адресом нашего сервиса(он нам понадобится позже, для тестирования сервиса). В окне браузера должно быть приблизительно следующее содержимое:

clip_image007

Это значит, что наш сервис правильно настроен и работает. На этом разработка сервиса завершена. Давайте проверим его в действии.

 

Часть 3. Разработка клиента для тестирования сервиса.

Для тестирования сервиса создадим простое консольное приложение:

clip_image001

Для работы с сервисом нам понадобится ссылка на этот сервис. Чтобы ее добавить необходимо в Solution Explorer установить курсор на узел проекта и выбрать пункт «Add Service Reference». На экране появится следущее окно:

clip_image003

В поле Address необхимо ввести адрес из браузера и нажать кнопку Go. Затем в поле Namespace указать значение «Service Refference» - это пространство имен в котором будут расположены классы для работы с сервисом. В конце жмем кнопку «Ok».

Модифицируем файл Program.cs внеся туда код для использования нашего сервиса:

class Program
{
    static void Main(string[] args)
    {
          var service = new DbServiceClient();
          Console.WriteLine("Add product: ");
          ProductBO newProduct = new ProductBO() { Name = "Book", Description = "Classic", Price = 5 };
          service.InsertProduct(newProduct);
          Console.WriteLine("Success!\n");
          Console.WriteLine("Add product: ");
          newProduct = new ProductBO() { Name = "Pencil", Description = "Red", Price = 1 };
          service.InsertProduct(newProduct);
          Console.WriteLine("Success!\n");
          Console.WriteLine("Products list:");
          List<ProductBO> products = service.GetAllProducts().ToList();
          string productFormat = "Id - {0}, Name - {1}, Desc - {2}, Price - {3}";
          products.ForEach(product => Console.WriteLine(String.Format(productFormat, product.Id, product.Name,      product.Description, product.Price)));
          Console.WriteLine("Search by Name 'Book':");
          products = service.GetAllProducts().ToList();
          products.ForEach(product => Console.WriteLine(String.Format(productFormat, product.Id, product.Name,  product.Description, product.Price)));
          Console.WriteLine("Delete product with Id = 1: ");
          service.DeleteProductById(1);
          Console.WriteLine("Success!");
   }
}

Теперь нажав комбинацию клавиш Ctrl + F5 можно запустить тестовую программу.

На этом написание всех модулей системы завершено. Спасибо за внимание.