Настройка Visual Studio Development Server для разработки WCF сервисов
Веб сервер встроенный в среду разработки — Visual Studio Development Server, по умолчанию использует динамически назначаемый порт. Обычно это не причиняет нам никаких неудобств. Но когда мы разрабатываем WCF сервис, динамически назначаемый порт весьма неудобен. Дело в том, что при обновлении Service Reference делается попытка обновления с того порта, который использовался при создании Service Reference, но так как он меняется, то попытка обновления будет неудачной. Мы конечно можем изменить настройки, изменив порт в адресе сервиса, но делать это каждый раз неудобно:
Решение этой проблемы, это задание постоянного порта для веб сервера Visual Studio.
Откройте свойства вашего Web проекта в котором находятся WCF сервисы и на закладке Web смените Auto-assign Port на Specific port:
Простая регистрация в ASP.NET приложении
Разрабатывая приложение на ASP.NET, требующее регистрации пользователей, мы сталкиваемся с проблемой слишком сложной процедуры регистрации. Во-первых по умолчанию требуется задавать достаточно сложный пароль, длинной от 7 символов с обязательным использованием не только цифр но и спец-символов типа @#$. Во-вторых требуется указать секретный вопрос и ответ. Это хорошие требования, но не все наши ASP.NET приложения настолько серьезны, что требуют длинного и сложного пароля и секретных вопросов.
Для того, чтобы упростить процедуру регистрации есть простой способ. Он заключается в изменении файла конфигурации Web.config. В секции
<providers></providers>нам необходимо добавить дополнительные атрибуты для Membership Provider.
<configuration>
<system.web>
<membership defaultProvider=»MembershipProvider»>
<providers>
<clear/>
<add name=»MembershipProvider» connectionStringName=»MemberchipConnection» applicationName=»My.WebApplication» type=»System.Web.Security.SqlMembershipProvider»
requiresQuestionAndAnswer=»false»
requiresUniqueEmail=»true»
minRequiredPasswordLength=»6″
minRequiredNonalphanumericCharacters=»0″
/>
</providers>
</membership>
</system.web>
</configuration>
Как видите, мы избавились от требований задавать секретные вопросы и ответы, использовать спец-символы в пароле, уменьшили минимальную длинну пароля но оставили требование уникальности Email адреса, если мы не хотим дублирующихся регистраций одного и того-же пользователя.
Если же вам нравится использовать регулярные выражения, то вы можете задать атрибут passwordStrengthRegularExpression=»…» и прописать в нем условие, каким бы вам хотелось видеть пароль.
Существует и множество дополнительных атрибутов для настройки MembershipProvider:
enablePasswordRetrieval=»false»
enablePasswordReset=»true»
passwordFormat=»Hashed»
maxInvalidPasswordAttempts=»5″
passwordAttemptWindow=»10″
Полный их список можно посмотреть в MSDN: http://msdn.microsoft.com/en-us/library/f1kyba5e.aspx
ДалееХостинг WCF сервиса на IIS 7 для Silverlight приложения
После переноса WCF сервиса с компьютера разработчика на сервер хостинг-провайдера возникает несколько проблем. В интернете вы найдёте противоречивые статьи и обсуждения на форумах, предлагающие то слишком избыточные решения, а то и вовсе ошибочные.
Поэтому я собрал в одном месте минимально достаточные инструкции по настройке WCF сервиса. Исходные возможности такие: хостинг с IIS7, ASP.NET 2.0, .NET Framework 3.5 SP1 (хостинг-провайдер masterhost, конфигурация Windows 2008 хостинга на текущее время), WCF сервис для Silverlight2 приложения. Отсутствует возможность запуска в командной строке сервера любых утилит для настроек IIS под WCF а также запуска IIS Manager Administration Tool (masterhost предоставляет возможность использовать для IIS7 Manager Administration Tool, но эта утилита не будет работать если ваш доступ в интернет осуществляется через proxy-сервер). Необходимо добиться устойчивой работы WCF сервиса.
Шаг 1. Single WCF Service in multiple domains
Деплоим Web проект на сервер хостинга и проверяем работу WCF сервиса: http://domain.tld/MyService.svc
Появляется сообщение об ошибке «Server Error in ‘/’ Application.» и предложение установить в файле конфигурации Web.config тэг <customErrors mode=»Off»> для возможности узнать детальные сведения об ошибке. Устанавливаем требуемые настройки, не забывая, что позднее их необходимо будет вернуть в прежнее состояние для production сервера.
<configuration>
<system.web>
<customErrors mode="Off"/>
</system.web>
</configuration>
Снова тестируем сервис: http://domain.tld/MyService.svc
Теперь мы видим сообщение об ошибке, оно гласит:
[ServiceActivationException: The service ‘/WcfService.svc’ cannot be activated due to an exception during compilation. The exception message is: This collection already contains an address with scheme http. There can be at most one address per scheme in this collection. Parameter name: item.]
Многие источники рекомендуют в данной ситуации написать свой ServiceHostFactory, но этого делать не надо! Для исправления этой ошибки достаточно добавить в файл конфигурации тэг baseAddressPrefixFilters с указанием протокола, хоста и порта сервера на котором размещается ваш сервис. Например, если ваш сервис располагается по адресу http://domain.tld:8080/Services/WcfService.svc, то порт необходимо указать, а вот путь /Services/WcfService.svc — нет, т.е. мы используем строку «http://domain.tld:8080/».
Было:
<configuration>
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
</system.serviceModel>
</configuration>
Стало:
<configuration>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true">
<baseAddressPrefixFilters>
<add prefix="http://domain.tld"/>
</baseAddressPrefixFilters>
</serviceHostingEnvironment>
</configuration>
Полностью секция system.serviceModel должна выглядеть так:
<configuration>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="Namespace.WcfServiceBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true">
<baseAddressPrefixFilters>
<add prefix="http://domain.tld"/>
</baseAddressPrefixFilters>
</serviceHostingEnvironment>
<services>
<service behaviorConfiguration="Namespace.WcfServiceBehavior" name="Namespace.WcfService">
<endpoint address="" binding="basicHttpBinding" contract="Namespace.WcfService"/>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
</system.serviceModel>
</configuration>
Тестируем: http://domain.tld/MyService.svc, сервис работает.
Отлично, однако, это только начало.
Учтите, что локально WCF сервис при этом перестанет работать, а указать несколько префиксов с разными доменами, но одинаковым протоколом невозможно, поэтому ввиду большого числа различий между файлами конфигурации Web.config на хостинге и на компьютере разработчика, рекомендуется редактировать их раздельно и отключить deploy этого файла на production сервер.
На компьютере разработчика соответственно префикс должен быть таким:
<add prefix="http://localhost:1656/"/>
или с другим портом в соответствии с вашими настройками. Либо лучше вообще закомментировать в файле конфигурации разработчика всю секцию baseAddressPrefixFilters, т.к. порт может меняться, и его правка причинит неудобства.
Кстати при разработке WCF сервисов для удобства разработчика желательно настроить использование постоянного порта для сервера встроенного в среду разработки (Visual Studio Development Server).
Не забудте отредактировать на сервере хостинга файл Web.config, убрав тэг <customErrors mode=»Off»/>. Заодно для production сервера рекомендуется отключить режим отладки в тэге <compilation debug=»true»>.
Шаг 2.
Другая ошибка, с которой вы можете столкнуться: IIS не видит .svc файл, сообщая об ошибке 404 — файл не найден.
Один из советов заключается в том, что необходимо установить Windows Communication Foundation в Панели управления->Установка и удаление->Включение и отключение компонентов Windows. Но так как нам недоступны такие операции на сервере хостинга, то проблема решается редактированием в файле Web.config специфичной для IIS7 секции system.webServer. Мы добавляем в нее Handler для обработки *.svc файлов.
<configuration>
<system.webServer>
<handlers>
<remove name="SvcHandler"/>
<add name="SvcHandler" path="*.svc" verb="*" type="System.ServiceModel.Activation.HttpHandler, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" resourceType="Unspecified" preCondition="integratedMode" />
</handlers>
</system.webServer>
</configuration>
Шаг 3.
Теперь нам необходимо настроить Silverlight приложение на работу с WCF сервисом расположенным не на компьютере разработчика, а на сервере хостинга.
Рассмотрим файл ServiceReferences.Config расположенный в корне Silverlight приложения:
<configuration>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_WcfService" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647">
<security mode="None" />
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:1656/WcfService.svc" binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_WcfService" contract="WcfReference.WcfService" name="BasicHttpBinding_WcfService" />
</client>
</system.serviceModel>
</configuration>
Меняем адрес сервиса на реальный:
<endpoint address="http://domain.tld/WcfService.svc" binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_WcfService" contract="WcfReference.WcfService" name="BasicHttpBinding_WcfService" />
Шаг 4. Cross domain WCF access
Запускаем Silverlight приложение. При попытке обращения к WCF сервису оно выдает сообщение об ошибке:
An error occurred while trying to make a request to URI ‘http://domain.tld/WcfService.svc’. This could be due to attempting to access a service in a cross-domain way without a proper cross-domain policy in place, or a policy that is unsuitable for SOAP services. You may need to contact the owner of the service to publish a cross-domain policy file and to ensure it allows SOAP-related HTTP headers to be sent. Please see the inner exception for more details.
Для устранения этой ошибки необходимо разместить в корне вашего Web-сервера (обратите внимание — в корне сервера, а не приложения) файл clientaccesspolicy.xml со следующим содержимым:
<?xml version="1.0" encoding="utf-8" ?>
<access-policy>
<cross-domain-access>
<policy>
<allow-from http-request-headers="SOAPAction">
<domain uri="*"/>
</allow-from>
<grant-to>
<resource path="/" include-subpaths="true"/>
</grant-to>
</policy>
</cross-domain-access>
</access-policy>
Далее
Свежие комментарии